All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.auth.oauth2.UserAuthorizer Maven / Gradle / Ivy

There is a newer version: 1.30.0
Show newest version
/*
 * Copyright 2015, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *
 *    * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.google.auth.oauth2;

import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.util.GenericData;
import com.google.api.client.util.Joiner;
import com.google.api.client.util.Preconditions;
import com.google.auth.http.HttpTransportFactory;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/** Handles an interactive 3-Legged-OAuth2 (3LO) user consent authorization. */
public class UserAuthorizer {

  /**
   * Represents the client authentication types as specified in RFC 7591.
   *
   * 

For more details, see RFC 7591. */ public enum ClientAuthenticationType { CLIENT_SECRET_POST, CLIENT_SECRET_BASIC, NONE } static final URI DEFAULT_CALLBACK_URI = URI.create("/oauth2callback"); private final String TOKEN_STORE_ERROR = "Error parsing stored token data."; private final String FETCH_TOKEN_ERROR = "Error reading result of Token API:"; private final ClientId clientId; private final Collection scopes; private final TokenStore tokenStore; private final URI callbackUri; private final HttpTransportFactory transportFactory; private final URI tokenServerUri; private final URI userAuthUri; private final PKCEProvider pkce; private final ClientAuthenticationType clientAuthenticationType; /** Internal constructor. See {@link Builder}. */ private UserAuthorizer(Builder builder) { this.clientId = Preconditions.checkNotNull(builder.clientId); this.scopes = ImmutableList.copyOf(Preconditions.checkNotNull(builder.scopes)); this.callbackUri = (builder.callbackUri == null) ? DEFAULT_CALLBACK_URI : builder.callbackUri; this.transportFactory = (builder.transportFactory == null) ? OAuth2Utils.HTTP_TRANSPORT_FACTORY : builder.transportFactory; this.tokenServerUri = (builder.tokenServerUri == null) ? OAuth2Utils.TOKEN_SERVER_URI : builder.tokenServerUri; this.userAuthUri = (builder.userAuthUri == null) ? OAuth2Utils.USER_AUTH_URI : builder.userAuthUri; this.tokenStore = (builder.tokenStore == null) ? new MemoryTokensStorage() : builder.tokenStore; this.pkce = builder.pkce; this.clientAuthenticationType = (builder.clientAuthenticationType == null) ? ClientAuthenticationType.CLIENT_SECRET_POST : builder.clientAuthenticationType; } /** * Returns the Client ID user to identify the OAuth2 consent prompt. * * @return The Client ID. */ public ClientId getClientId() { return clientId; } /** * Returns the scopes defining the user consent. * * @return The collection of scopes defining the user consent. */ public Collection getScopes() { return scopes; } /** * Returns the URI for implementation of the OAuth2 web callback. * * @return The URI for the OAuth2 web callback. */ public URI getCallbackUri() { return callbackUri; } /** * Returns the URI for implementation of the OAuth2 web callback, optionally relative to the * specified URI. * *

The callback URI is often relative to enable an application to be tested from more than one * place so this can be used to resolve it relative to another URI. * * @param baseUri The URI to resolve the callback URI relative to. * @return The resolved URI. */ public URI getCallbackUri(URI baseUri) { if (callbackUri.isAbsolute()) { return callbackUri; } if (baseUri == null || !baseUri.isAbsolute()) { throw new IllegalStateException( "If the callback URI is relative, the baseUri passed must" + " be an absolute URI"); } return baseUri.resolve(callbackUri); } /** * Returns the implementation of a component for long term storage of tokens. * * @return The token storage implementation for long term storage of tokens. */ public TokenStore getTokenStore() { return tokenStore; } /** * Returns the client authentication type as defined in RFC 7591. * * @return The {@link ClientAuthenticationType} */ public ClientAuthenticationType getClientAuthenticationType() { return clientAuthenticationType; } /** * Return a URL that performs the authorization consent prompt web UI. * * @param userId Application's identifier for the end user. * @param state State that is passed on to the OAuth2 callback URI after the consent. * @param baseUri The URI to resolve the OAuth2 callback URI relative to. * @return The URL that can be navigated or redirected to. */ public URL getAuthorizationUrl(String userId, String state, URI baseUri) { return this.getAuthorizationUrl(userId, state, baseUri, null); } /** * Return a URL that performs the authorization consent prompt web UI. * * @param userId Application's identifier for the end user. * @param state State that is passed on to the OAuth2 callback URI after the consent. * @param baseUri The URI to resolve the OAuth2 callback URI relative to. * @param additionalParameters Additional query parameters to be added to the authorization URL. * @return The URL that can be navigated or redirected to. */ public URL getAuthorizationUrl( String userId, String state, URI baseUri, Map additionalParameters) { URI resolvedCallbackUri = getCallbackUri(baseUri); String scopesString = Joiner.on(' ').join(scopes); GenericUrl url = new GenericUrl(userAuthUri); url.put("response_type", "code"); url.put("client_id", clientId.getClientId()); url.put("redirect_uri", resolvedCallbackUri); url.put("scope", scopesString); if (state != null) { url.put("state", state); } url.put("access_type", "offline"); url.put("approval_prompt", "force"); if (userId != null) { url.put("login_hint", userId); } url.put("include_granted_scopes", true); if (additionalParameters != null) { for (Map.Entry entry : additionalParameters.entrySet()) { url.put(entry.getKey(), entry.getValue()); } } if (pkce != null) { url.put("code_challenge", pkce.getCodeChallenge()); url.put("code_challenge_method", pkce.getCodeChallengeMethod()); } return url.toURL(); } /** * Attempts to retrieve credentials for the approved end user consent. * * @param userId Application's identifier for the end user. * @return The loaded credentials or null if there are no valid approved credentials. * @throws IOException If there is error retrieving or loading the credentials. */ public UserCredentials getCredentials(String userId) throws IOException { Preconditions.checkNotNull(userId); if (tokenStore == null) { throw new IllegalStateException("Method cannot be called if token store is not specified."); } String tokenData = tokenStore.load(userId); if (tokenData == null) { return null; } GenericJson tokenJson = OAuth2Utils.parseJson(tokenData); String accessTokenValue = OAuth2Utils.validateString(tokenJson, "access_token", TOKEN_STORE_ERROR); Long expirationMillis = OAuth2Utils.validateLong(tokenJson, "expiration_time_millis", TOKEN_STORE_ERROR); Date expirationTime = new Date(expirationMillis); List scopes = OAuth2Utils.validateOptionalListString( tokenJson, OAuth2Utils.TOKEN_RESPONSE_SCOPE, FETCH_TOKEN_ERROR); AccessToken accessToken = AccessToken.newBuilder() .setExpirationTime(expirationTime) .setTokenValue(accessTokenValue) .setScopes(scopes) .build(); String refreshToken = OAuth2Utils.validateOptionalString(tokenJson, "refresh_token", TOKEN_STORE_ERROR); UserCredentials credentials = UserCredentials.newBuilder() .setClientId(clientId.getClientId()) .setClientSecret(clientId.getClientSecret()) .setRefreshToken(refreshToken) .setAccessToken(accessToken) .setHttpTransportFactory(transportFactory) .setTokenServerUri(tokenServerUri) .build(); monitorCredentials(userId, credentials); return credentials; } /** * Returns a UserCredentials instance by exchanging an OAuth2 authorization code for tokens. * * @param code Code returned from OAuth2 consent prompt. * @param baseUri The URI to resolve the OAuth2 callback URI relative to. * @return the UserCredentials instance created from the authorization code. * @throws IOException An error from the server API call to get the tokens. */ public UserCredentials getCredentialsFromCode(String code, URI baseUri) throws IOException { return getCredentialsFromCode(code, baseUri, null); } /** * Returns a UserCredentials instance by exchanging an OAuth2 authorization code for tokens. * * @param code Code returned from OAuth2 consent prompt. * @param baseUri The URI to resolve the OAuth2 callback URI relative to. * @param additionalParameters Additional parameters to be added to the post body of token * endpoint request. * @return the UserCredentials instance created from the authorization code. * @throws IOException An error from the server API call to get the tokens. */ public UserCredentials getCredentialsFromCode( String code, URI baseUri, Map additionalParameters) throws IOException { TokenResponseWithConfig tokenResponseWithConfig = getCredentialsFromCodeInternal(code, baseUri, additionalParameters); return UserCredentials.newBuilder() .setClientId(tokenResponseWithConfig.getClientId()) .setClientSecret(tokenResponseWithConfig.getClientSecret()) .setAccessToken(tokenResponseWithConfig.getAccessToken()) .setRefreshToken(tokenResponseWithConfig.getRefreshToken()) .setHttpTransportFactory(tokenResponseWithConfig.getHttpTransportFactory()) .setTokenServerUri(tokenResponseWithConfig.getTokenServerUri()) .build(); } /** * Handles OAuth2 authorization code exchange and returns a {@link TokenResponseWithConfig} object * containing the tokens and configuration details. * * @param code The authorization code received from the OAuth2 authorization server. * @param callbackUri The URI to which the authorization server redirected the user after granting * authorization. * @param additionalParameters Additional parameters to include in the token exchange request. * @return A {@link TokenResponseWithConfig} object containing the access token, refresh token (if * granted), and configuration details used in the OAuth flow. * @throws IOException If an error occurs during the token exchange process. */ public TokenResponseWithConfig getTokenResponseFromAuthCodeExchange( String code, URI callbackUri, Map additionalParameters) throws IOException { return getCredentialsFromCodeInternal(code, callbackUri, additionalParameters); } /** * Exchanges an authorization code for tokens and stores them. * * @param userId Application's identifier for the end user. * @param code Code returned from OAuth2 consent prompt. * @param baseUri The URI to resolve the OAuth2 callback URI relative to. * @return UserCredentials instance created from the authorization code. * @throws IOException An error from the server API call to get the tokens or store the tokens. */ public UserCredentials getAndStoreCredentialsFromCode(String userId, String code, URI baseUri) throws IOException { Preconditions.checkNotNull(userId); Preconditions.checkNotNull(code); UserCredentials credentials = getCredentialsFromCode(code, baseUri); storeCredentials(userId, credentials); monitorCredentials(userId, credentials); return credentials; } /** * Revokes the authorization for tokens stored for the user. * * @param userId Application's identifier for the end user. * @throws IOException An error calling the revoke API or deleting the state. */ public void revokeAuthorization(String userId) throws IOException { Preconditions.checkNotNull(userId); if (tokenStore == null) { throw new IllegalStateException("Method cannot be called if token store is not specified."); } String tokenData = tokenStore.load(userId); if (tokenData == null) { return; } IOException deleteTokenException = null; try { // Delete the stored version first. If token reversion fails it is less harmful to have an // non revoked token to hold on to a potentially revoked token. tokenStore.delete(userId); } catch (IOException e) { deleteTokenException = e; } GenericJson tokenJson = OAuth2Utils.parseJson(tokenData); String accessTokenValue = OAuth2Utils.validateOptionalString(tokenJson, "access_token", TOKEN_STORE_ERROR); String refreshToken = OAuth2Utils.validateOptionalString(tokenJson, "refresh_token", TOKEN_STORE_ERROR); // If both tokens are present, either can be used String revokeToken = (refreshToken != null) ? refreshToken : accessTokenValue; GenericUrl revokeUrl = new GenericUrl(OAuth2Utils.TOKEN_REVOKE_URI); GenericData genericData = new GenericData(); genericData.put("token", revokeToken); UrlEncodedContent content = new UrlEncodedContent(genericData); HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory(); HttpRequest tokenRequest = requestFactory.buildPostRequest(revokeUrl, content); tokenRequest.execute(); if (deleteTokenException != null) { throw deleteTokenException; } } /** * Puts the end user credentials in long term storage. * * @param userId Application's identifier for the end user. * @param credentials UserCredentials instance for the authorized consent. * @throws IOException An error storing the credentials. */ public void storeCredentials(String userId, UserCredentials credentials) throws IOException { if (tokenStore == null) { throw new IllegalStateException("Cannot store tokens if tokenStore is not specified."); } AccessToken accessToken = credentials.getAccessToken(); String acessTokenValue = null; Date expiresBy = null; List grantedScopes = new ArrayList<>(); if (accessToken != null) { acessTokenValue = accessToken.getTokenValue(); expiresBy = accessToken.getExpirationTime(); grantedScopes = accessToken.getScopes(); } String refreshToken = credentials.getRefreshToken(); GenericJson tokenStateJson = new GenericJson(); tokenStateJson.setFactory(OAuth2Utils.JSON_FACTORY); tokenStateJson.put("access_token", acessTokenValue); tokenStateJson.put(OAuth2Utils.TOKEN_RESPONSE_SCOPE, grantedScopes); tokenStateJson.put("expiration_time_millis", expiresBy.getTime()); if (refreshToken != null) { tokenStateJson.put("refresh_token", refreshToken); } String tokenState = tokenStateJson.toString(); tokenStore.store(userId, tokenState); } /** * Adds a listen to rewrite the credentials when the tokens are refreshed. * * @param userId Application's identifier for the end user. * @param credentials UserCredentials instance to listen to. */ protected void monitorCredentials(String userId, UserCredentials credentials) { credentials.addChangeListener(new UserCredentialsListener(userId)); } private TokenResponseWithConfig getCredentialsFromCodeInternal( String code, URI baseUri, Map additionalParameters) throws IOException { Preconditions.checkNotNull(code); URI resolvedCallbackUri = getCallbackUri(baseUri); GenericData tokenData = new GenericData(); tokenData.put("code", code); tokenData.put("client_id", clientId.getClientId()); tokenData.put("redirect_uri", resolvedCallbackUri); tokenData.put("grant_type", "authorization_code"); if (additionalParameters != null) { for (Map.Entry entry : additionalParameters.entrySet()) { tokenData.put(entry.getKey(), entry.getValue()); } } if (pkce != null) { tokenData.put("code_verifier", pkce.getCodeVerifier()); } if (this.clientAuthenticationType == ClientAuthenticationType.CLIENT_SECRET_POST) { tokenData.put("client_secret", clientId.getClientSecret()); } HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory(); UrlEncodedContent tokenContent = new UrlEncodedContent(tokenData); HttpRequest tokenRequest = requestFactory.buildPostRequest(new GenericUrl(tokenServerUri), tokenContent); tokenRequest.setParser(new JsonObjectParser(OAuth2Utils.JSON_FACTORY)); if (this.clientAuthenticationType == ClientAuthenticationType.CLIENT_SECRET_BASIC) { tokenRequest .getHeaders() .setAuthorization( OAuth2Utils.generateBasicAuthHeader( clientId.getClientId(), clientId.getClientSecret())); } HttpResponse tokenResponse = tokenRequest.execute(); GenericJson parsedTokens = tokenResponse.parseAs(GenericJson.class); String accessTokenValue = OAuth2Utils.validateString(parsedTokens, "access_token", FETCH_TOKEN_ERROR); int expiresInSecs = OAuth2Utils.validateInt32(parsedTokens, "expires_in", FETCH_TOKEN_ERROR); Date expirationTime = new Date(new Date().getTime() + expiresInSecs * 1000); String scopes = OAuth2Utils.validateOptionalString( parsedTokens, OAuth2Utils.TOKEN_RESPONSE_SCOPE, FETCH_TOKEN_ERROR); AccessToken accessToken = AccessToken.newBuilder() .setExpirationTime(expirationTime) .setTokenValue(accessTokenValue) .setScopes(scopes) .build(); String refreshToken = OAuth2Utils.validateOptionalString(parsedTokens, "refresh_token", FETCH_TOKEN_ERROR); return TokenResponseWithConfig.newBuilder() .setClientId(clientId.getClientId()) .setClientSecret(clientId.getClientSecret()) .setAccessToken(accessToken) .setRefreshToken(refreshToken) .setHttpTransportFactory(transportFactory) .setTokenServerUri(tokenServerUri) .build(); } /** * Implementation of listener used by monitorCredentials to rewrite the credentials when the * tokens are refreshed. */ private class UserCredentialsListener implements OAuth2Credentials.CredentialsChangedListener { private final String userId; /** Construct new listener. */ public UserCredentialsListener(String userId) { this.userId = userId; } /** Handle change event by rewriting to token store. */ @Override public void onChanged(OAuth2Credentials credentials) throws IOException { UserCredentials userCredentials = (UserCredentials) credentials; storeCredentials(userId, userCredentials); } } public static Builder newBuilder() { return new Builder(); } public Builder toBuilder() { return new Builder(this); } public static class Builder { private ClientId clientId; private TokenStore tokenStore; private URI callbackUri; private URI tokenServerUri; private URI userAuthUri; private Collection scopes; private HttpTransportFactory transportFactory; private PKCEProvider pkce; private ClientAuthenticationType clientAuthenticationType; protected Builder() {} protected Builder(UserAuthorizer authorizer) { this.clientId = authorizer.clientId; this.scopes = authorizer.scopes; this.transportFactory = authorizer.transportFactory; this.tokenServerUri = authorizer.tokenServerUri; this.tokenStore = authorizer.tokenStore; this.callbackUri = authorizer.callbackUri; this.userAuthUri = authorizer.userAuthUri; this.pkce = new DefaultPKCEProvider(); this.clientAuthenticationType = authorizer.clientAuthenticationType; } /** * Sets the OAuth 2.0 client ID. * * @param clientId the client ID * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setClientId(ClientId clientId) { this.clientId = clientId; return this; } /** * Sets the {@link TokenStore} to use for long term token storage. * * @param tokenStore the token store * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setTokenStore(TokenStore tokenStore) { this.tokenStore = tokenStore; return this; } /** * Sets the OAuth 2.0 scopes to request. * * @param scopes the scopes to request * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setScopes(Collection scopes) { this.scopes = scopes; return this; } /** * Sets the token exchange endpoint. * * @param tokenServerUri the token exchange endpoint to use * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setTokenServerUri(URI tokenServerUri) { this.tokenServerUri = tokenServerUri; return this; } /** * Sets the redirect URI registered with your OAuth provider. This is where the user's browser * will be redirected after granting or denying authorization. * * @param callbackUri the redirect URI * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setCallbackUri(URI callbackUri) { this.callbackUri = callbackUri; return this; } /** * Sets the authorization URI where the user is directed to log in and grant authorization. * * @param userAuthUri the authorization URI * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setUserAuthUri(URI userAuthUri) { this.userAuthUri = userAuthUri; return this; } /** * Sets the HTTP transport factory. * * @param transportFactory the {@code HttpTransportFactory} to set * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setHttpTransportFactory(HttpTransportFactory transportFactory) { this.transportFactory = transportFactory; return this; } /** * Sets the optional {@link PKCEProvider} to enable Proof Key for Code Exchange to be used. This * enhances security by using a code challenge and verifier to prevent authorization code * interception attacks. * * @param pkce the {@code PKCEProvider} to set * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setPKCEProvider(PKCEProvider pkce) { if (pkce != null) { if (pkce.getCodeChallenge() == null || pkce.getCodeVerifier() == null || pkce.getCodeChallengeMethod() == null) { throw new IllegalArgumentException( "PKCE provider contained null implementations. PKCE object must implement all PKCEProvider methods."); } } this.pkce = pkce; return this; } /** * Sets the optional {@link ClientAuthenticationType}, one of the client authentication methods * defined in RFC 7591. This specifies how your application authenticates itself to the * authorization server. * * @param clientAuthentication the {@code ClientAuthenticationType} to set * @return this {@code Builder} object */ @CanIgnoreReturnValue public Builder setClientAuthenticationType(ClientAuthenticationType clientAuthentication) { this.clientAuthenticationType = clientAuthentication; return this; } public ClientId getClientId() { return clientId; } public TokenStore getTokenStore() { return tokenStore; } public Collection getScopes() { return scopes; } public URI getTokenServerUri() { return tokenServerUri; } public URI getCallbackUri() { return callbackUri; } public URI getUserAuthUri() { return userAuthUri; } public HttpTransportFactory getHttpTransportFactory() { return transportFactory; } public PKCEProvider getPKCEProvider() { return pkce; } public ClientAuthenticationType getClientAuthenticationType() { return clientAuthenticationType; } public UserAuthorizer build() { return new UserAuthorizer(this); } } /** * Represents the response from an OAuth token exchange, including configuration details used to * initiate the flow. * *

This response can be used to initialize the following credentials types: * *

{@code
   * // UserCredentials when Google is the identity provider:
   * UserCredentials userCredentials = UserCredentials.newBuilder()
   *     .setHttpTransportFactory(tokenResponseWithConfig.getHttpTransportFactory())
   *     .setClientId(tokenResponseWithConfig.getClientId())
   *     .setClientSecret(tokenResponseWithConfig.getClientSecret())
   *     .setAccessToken(tokenResponseWithConfig.getAccessToken())
   *     .setRefreshToken(tokenResponseWithConfig.getRefreshToken())
   *     .setTokenServerUri(tokenResponseWithConfig.getTokenServerUri())
   *     .build();
   *
   * // ExternalAccountAuthorizedUserCredentials when using Workforce Identity Federation:
   * ExternalAccountAuthorizedUserCredentials externalAccountAuthorizedUserCredentials =
   *     ExternalAccountAuthorizedUserCredentials.newBuilder()
   *         .setHttpTransportFactory(tokenResponseWithConfig.getHttpTransportFactory())
   *         .setClientId(tokenResponseWithConfig.getClientId())
   *         .setClientSecret(tokenResponseWithConfig.getClientSecret())
   *         .setAccessToken(tokenResponseWithConfig.getAccessToken())
   *         .setRefreshToken(tokenResponseWithConfig.getRefreshToken())
   *         .setTokenUrl(tokenResponseWithConfig.getTokenServerUri().toURL().toString())
   *         .build();
   * }
*/ public static class TokenResponseWithConfig { private final String clientId; private final String clientSecret; private final String refreshToken; private final AccessToken accessToken; private URI tokenServerUri; private final HttpTransportFactory httpTransportFactory; private TokenResponseWithConfig(Builder builder) { this.clientId = builder.clientId; this.clientSecret = builder.clientSecret; this.accessToken = builder.accessToken; this.httpTransportFactory = builder.httpTransportFactory; this.tokenServerUri = builder.tokenServerUri; this.refreshToken = builder.refreshToken; } /** * Returns the OAuth 2.0 client ID used. * * @return The client ID. */ public String getClientId() { return clientId; } /** * Returns the OAuth 2.0 client secret used. * * @return The client secret. */ public String getClientSecret() { return clientSecret; } /** * Returns the access token obtained from the token exchange. * * @return The access token. */ public AccessToken getAccessToken() { return accessToken; } /** * Returns the HTTP transport factory used. * * @return The HTTP transport factory. */ public HttpTransportFactory getHttpTransportFactory() { return httpTransportFactory; } /** * Returns the URI of the token server used. * * @return The token server URI. */ public URI getTokenServerUri() { return tokenServerUri; } /** * Returns the refresh token obtained from the token exchange, if available. * * @return The refresh token, or null if not granted. */ @Nullable public String getRefreshToken() { return refreshToken; } static Builder newBuilder() { return new Builder(); } static class Builder { private String clientId; private String clientSecret; private String refreshToken; private AccessToken accessToken; private URI tokenServerUri; private HttpTransportFactory httpTransportFactory; @CanIgnoreReturnValue Builder setClientId(String clientId) { this.clientId = clientId; return this; } @CanIgnoreReturnValue Builder setClientSecret(String clientSecret) { this.clientSecret = clientSecret; return this; } @CanIgnoreReturnValue Builder setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; return this; } @CanIgnoreReturnValue Builder setAccessToken(AccessToken accessToken) { this.accessToken = accessToken; return this; } @CanIgnoreReturnValue Builder setHttpTransportFactory(HttpTransportFactory httpTransportFactory) { this.httpTransportFactory = httpTransportFactory; return this; } @CanIgnoreReturnValue Builder setTokenServerUri(URI tokenServerUri) { this.tokenServerUri = tokenServerUri; return this; } TokenResponseWithConfig build() { return new TokenResponseWithConfig(this); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy