001package com.box.sdkgen.box.oauth; 002 003import static com.box.sdkgen.internal.utils.UtilsManager.entryOf; 004import static com.box.sdkgen.internal.utils.UtilsManager.mapOf; 005import static com.box.sdkgen.internal.utils.UtilsManager.prepareParams; 006import static com.box.sdkgen.serialization.json.JsonManager.sdToUrlParams; 007 008import com.box.sdkgen.box.errors.BoxSDKError; 009import com.box.sdkgen.box.tokenstorage.TokenStorage; 010import com.box.sdkgen.managers.authorization.AuthorizationManager; 011import com.box.sdkgen.networking.auth.Authentication; 012import com.box.sdkgen.networking.network.NetworkSession; 013import com.box.sdkgen.schemas.accesstoken.AccessToken; 014import com.box.sdkgen.schemas.postoauth2revoke.PostOAuth2Revoke; 015import com.box.sdkgen.schemas.postoauth2token.PostOAuth2Token; 016import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenGrantTypeField; 017import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenSubjectTokenTypeField; 018import com.box.sdkgen.serialization.json.JsonManager; 019import java.util.List; 020import java.util.Map; 021 022public class BoxOAuth implements Authentication { 023 024 /** Configuration object of OAuth. */ 025 public final OAuthConfig config; 026 027 /** 028 * An object responsible for storing token. If no custom implementation provided, the token will 029 * be stored in memory. 030 */ 031 public final TokenStorage tokenStorage; 032 033 public BoxOAuth(OAuthConfig config) { 034 this.config = config; 035 this.tokenStorage = this.config.getTokenStorage(); 036 } 037 038 /** Get the authorization URL for the app user. */ 039 public String getAuthorizeUrl() { 040 return getAuthorizeUrl(new GetAuthorizeUrlOptions()); 041 } 042 043 /** 044 * Get the authorization URL for the app user. 045 * 046 * @param options The options parameter 047 */ 048 public String getAuthorizeUrl(GetAuthorizeUrlOptions options) { 049 Map<String, String> paramsMap = 050 prepareParams( 051 mapOf( 052 entryOf( 053 "client_id", 054 (!(options.getClientId() == null) 055 ? options.getClientId() 056 : this.config.getClientId())), 057 entryOf( 058 "response_type", 059 (!(options.getResponseType() == null) ? options.getResponseType() : "code")), 060 entryOf("redirect_uri", options.getRedirectUri()), 061 entryOf("state", options.getState()), 062 entryOf("scope", options.getScope()))); 063 return String.join( 064 "", 065 "https://account.box.com/api/oauth2/authorize?", 066 sdToUrlParams(JsonManager.serialize(paramsMap))); 067 } 068 069 /** 070 * Acquires token info using an authorization code. 071 * 072 * @param authorizationCode The authorization code to use to get tokens. 073 */ 074 public AccessToken getTokensAuthorizationCodeGrant(String authorizationCode) { 075 return getTokensAuthorizationCodeGrant(authorizationCode, null); 076 } 077 078 /** 079 * Acquires token info using an authorization code. 080 * 081 * @param authorizationCode The authorization code to use to get tokens. 082 * @param networkSession An object to keep network session state 083 */ 084 public AccessToken getTokensAuthorizationCodeGrant( 085 String authorizationCode, NetworkSession networkSession) { 086 AuthorizationManager authManager = 087 new AuthorizationManager.Builder() 088 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 089 .build(); 090 AccessToken token = 091 authManager.requestAccessToken( 092 new PostOAuth2Token.Builder(PostOAuth2TokenGrantTypeField.AUTHORIZATION_CODE) 093 .code(authorizationCode) 094 .clientId(this.config.getClientId()) 095 .clientSecret(this.config.getClientSecret()) 096 .build()); 097 this.tokenStorage.store(token); 098 return token; 099 } 100 101 /** 102 * Get the current access token. If the current access token is expired or not found, this method 103 * will attempt to refresh the token. 104 */ 105 public AccessToken retrieveToken() { 106 return retrieveToken(null); 107 } 108 109 /** 110 * Get the current access token. If the current access token is expired or not found, this method 111 * will attempt to refresh the token. 112 * 113 * @param networkSession An object to keep network session state 114 */ 115 @Override 116 public AccessToken retrieveToken(NetworkSession networkSession) { 117 AccessToken token = this.tokenStorage.get(); 118 if (token == null) { 119 throw new BoxSDKError( 120 "Access and refresh tokens not available. Authenticate before making any API call first."); 121 } 122 return token; 123 } 124 125 /** Get a new access token for the platform app user. */ 126 public AccessToken refreshToken() { 127 return refreshToken(null); 128 } 129 130 /** 131 * Get a new access token for the platform app user. 132 * 133 * @param networkSession An object to keep network session state 134 */ 135 @Override 136 public AccessToken refreshToken(NetworkSession networkSession) { 137 AccessToken oldToken = this.tokenStorage.get(); 138 String tokenUsedForRefresh = (!(oldToken == null) ? oldToken.getRefreshToken() : null); 139 AuthorizationManager authManager = 140 new AuthorizationManager.Builder() 141 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 142 .build(); 143 AccessToken token = 144 authManager.requestAccessToken( 145 new PostOAuth2Token.Builder(PostOAuth2TokenGrantTypeField.REFRESH_TOKEN) 146 .clientId(this.config.getClientId()) 147 .clientSecret(this.config.getClientSecret()) 148 .refreshToken(tokenUsedForRefresh) 149 .build()); 150 this.tokenStorage.store(token); 151 return token; 152 } 153 154 public String retrieveAuthorizationHeader() { 155 return retrieveAuthorizationHeader(null); 156 } 157 158 @Override 159 public String retrieveAuthorizationHeader(NetworkSession networkSession) { 160 AccessToken token = this.retrieveToken(networkSession); 161 return String.join("", "Bearer ", token.getAccessToken()); 162 } 163 164 /** 165 * Revoke an active Access Token, effectively logging a user out that has been previously 166 * authenticated. 167 */ 168 public void revokeToken() { 169 revokeToken(null); 170 } 171 172 /** 173 * Revoke an active Access Token, effectively logging a user out that has been previously 174 * authenticated. 175 * 176 * @param networkSession An object to keep network session state 177 */ 178 @Override 179 public void revokeToken(NetworkSession networkSession) { 180 AccessToken token = this.tokenStorage.get(); 181 if (token == null) { 182 return; 183 } 184 AuthorizationManager authManager = 185 new AuthorizationManager.Builder() 186 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 187 .build(); 188 authManager.revokeAccessToken( 189 new PostOAuth2Revoke.Builder() 190 .clientId(this.config.getClientId()) 191 .clientSecret(this.config.getClientSecret()) 192 .token(token.getAccessToken()) 193 .build()); 194 } 195 196 /** 197 * Downscope access token to the provided scopes. Returning a new access token with the provided 198 * scopes, with the original access token unchanged. 199 * 200 * @param scopes The scope(s) to apply to the resulting token. 201 * @param resource The file or folder to get a downscoped token for. If None and shared_link None, 202 * the resulting token will not be scoped down to just a single item. The resource should be a 203 * full URL to an item, e.g. https://api.box.com/2.0/files/123456. 204 * @param sharedLink The shared link to get a downscoped token for. If None and item None, the 205 * resulting token will not be scoped down to just a single item. 206 * @param networkSession An object to keep network session state 207 */ 208 @Override 209 public AccessToken downscopeToken( 210 List<String> scopes, String resource, String sharedLink, NetworkSession networkSession) { 211 AccessToken token = this.retrieveToken(networkSession); 212 if (token == null || token.getAccessToken() == null) { 213 throw new BoxSDKError("No access token is available."); 214 } 215 AuthorizationManager authManager = 216 new AuthorizationManager.Builder() 217 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 218 .build(); 219 AccessToken downscopedToken = 220 authManager.requestAccessToken( 221 new PostOAuth2Token.Builder( 222 PostOAuth2TokenGrantTypeField.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE) 223 .subjectToken(token.getAccessToken()) 224 .subjectTokenType( 225 PostOAuth2TokenSubjectTokenTypeField 226 .URN_IETF_PARAMS_OAUTH_TOKEN_TYPE_ACCESS_TOKEN) 227 .resource(resource) 228 .scope(String.join(" ", scopes)) 229 .boxSharedLink(sharedLink) 230 .build()); 231 return downscopedToken; 232 } 233 234 public TokenStorage getTokenStorage() { 235 return tokenStorage; 236 } 237}