/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.social.connect.support; import java.util.UUID; import org.springframework.social.connect.ApiAdapter; import org.springframework.social.connect.Connection; import org.springframework.social.connect.ConnectionData; import org.springframework.social.connect.ConnectionFactory; import org.springframework.social.oauth2.AccessGrant; import org.springframework.social.oauth2.OAuth2Operations; import org.springframework.social.oauth2.OAuth2ServiceProvider; /** * Factory for creating OAuth2-based {@link Connection}s. * May be subclassed to further simplify construction e.g. FacebookConnectionFactory. * @author Keith Donald * @param <S> the service API type. */ public class OAuth2ConnectionFactory<S> extends ConnectionFactory<S> { private String scope = null; /** * Create a {@link OAuth2ConnectionFactory}. * @param providerId the provider id e.g. "facebook" * @param serviceProvider the ServiceProvider model for conducting the authorization flow and obtaining a native service API instance. * @param apiAdapter the ApiAdapter for mapping the provider-specific service API model to the uniform {@link Connection} interface. */ public OAuth2ConnectionFactory(String providerId, OAuth2ServiceProvider<S> serviceProvider, ApiAdapter<S> apiAdapter) { super(providerId, serviceProvider, apiAdapter); } /** * Sets the default value to send in the scope parameter during authorization. * Null by default, meaning that no scope parameter will be sent and the default scope will be determined by the provider. * @param scope The default value to send as scope during authorization. */ public void setScope(String scope) { this.scope = scope; } public String getScope() { return scope; } /** * Generates a value for the state parameter. * @return a random UUID by default. */ public String generateState() { return UUID.randomUUID().toString(); } /** * Indicates that this provider supports the state parameter in callbacks to prevent against CSRF. * Default implementation returns true. * @return true if the provider supports the state parameter */ public boolean supportsStateParameter() { return true; } /** * Get the ServiceProvider's {@link OAuth2Operations} that allows the client application to conduct the OAuth2 flow with the provider. * @return an OAuth2Operations */ public OAuth2Operations getOAuthOperations() { return getOAuth2ServiceProvider().getOAuthOperations(); } /** * Create a OAuth2-based {@link Connection} from the {@link AccessGrant} returned after {@link #getOAuthOperations() completing the OAuth2 flow}. * @param accessGrant the access grant * @return the new service provider connection * @see OAuth2Operations#exchangeForAccess(String, String, org.springframework.util.MultiValueMap) */ public Connection<S> createConnection(AccessGrant accessGrant) { return new OAuth2Connection<S>(getProviderId(), extractProviderUserId(accessGrant), accessGrant.getAccessToken(), accessGrant.getRefreshToken(), accessGrant.getExpireTime(), getOAuth2ServiceProvider(), getApiAdapter()); } /** * Create a OAuth2-based {@link Connection} from the connection data. * @param data connection data from which to create the connection */ public Connection<S> createConnection(ConnectionData data) { return new OAuth2Connection<S>(data, getOAuth2ServiceProvider(), getApiAdapter()); } // subclassing hooks /** * Hook for extracting the providerUserId from the returned {@link AccessGrant}, if it is available. * Default implementation returns null, indicating it is not exposed and another remote API call will be required to obtain it. * Subclasses may override. * @param accessGrant an AccessGrant from which to extract the provider ID * @return the pvodier ID, if available */ protected String extractProviderUserId(AccessGrant accessGrant) { return null; } // internal helpers private OAuth2ServiceProvider<S> getOAuth2ServiceProvider() { return (OAuth2ServiceProvider<S>) getServiceProvider(); } }