001package com.box.sdkgen.box.ccgauth; 002 003import com.box.sdkgen.box.errors.BoxSDKError; 004import com.box.sdkgen.box.tokenstorage.InMemoryTokenStorage; 005import com.box.sdkgen.box.tokenstorage.TokenStorage; 006import com.box.sdkgen.managers.authorization.AuthorizationManager; 007import com.box.sdkgen.networking.auth.Authentication; 008import com.box.sdkgen.networking.network.NetworkSession; 009import com.box.sdkgen.schemas.accesstoken.AccessToken; 010import com.box.sdkgen.schemas.postoauth2revoke.PostOAuth2Revoke; 011import com.box.sdkgen.schemas.postoauth2token.PostOAuth2Token; 012import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenBoxSubjectTypeField; 013import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenGrantTypeField; 014import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenSubjectTokenTypeField; 015import com.box.sdkgen.serialization.json.EnumWrapper; 016import java.util.List; 017 018public class BoxCCGAuth implements Authentication { 019 020 /** Configuration object of Client Credentials Grant auth. */ 021 public final CCGConfig config; 022 023 /** 024 * An object responsible for storing token. If no custom implementation provided, the token will 025 * be stored in memory. 026 */ 027 public final TokenStorage tokenStorage; 028 029 /** 030 * The ID of the user or enterprise to authenticate as. If not provided, defaults to the 031 * enterprise ID if set, otherwise defaults to the user ID. 032 */ 033 public String subjectId; 034 035 /** The type of the subject ID provided. Must be either 'user' or 'enterprise'. */ 036 public EnumWrapper<PostOAuth2TokenBoxSubjectTypeField> subjectType; 037 038 public BoxCCGAuth(CCGConfig config) { 039 this.config = config; 040 this.tokenStorage = this.config.getTokenStorage(); 041 this.subjectId = 042 (!(this.config.getUserId() == null) 043 ? this.config.getUserId() 044 : this.config.getEnterpriseId()); 045 this.subjectType = 046 new EnumWrapper<PostOAuth2TokenBoxSubjectTypeField>( 047 (!(this.config.getUserId() == null) 048 ? PostOAuth2TokenBoxSubjectTypeField.USER 049 : PostOAuth2TokenBoxSubjectTypeField.ENTERPRISE)); 050 } 051 052 /** Get a new access token using CCG auth */ 053 public AccessToken refreshToken() { 054 return refreshToken(null); 055 } 056 057 /** 058 * Get a new access token using CCG auth 059 * 060 * @param networkSession An object to keep network session state 061 */ 062 @Override 063 public AccessToken refreshToken(NetworkSession networkSession) { 064 AuthorizationManager authManager = 065 new AuthorizationManager.Builder() 066 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 067 .build(); 068 AccessToken token = 069 authManager.requestAccessToken( 070 new PostOAuth2Token.Builder(PostOAuth2TokenGrantTypeField.CLIENT_CREDENTIALS) 071 .clientId(this.config.getClientId()) 072 .clientSecret(this.config.getClientSecret()) 073 .boxSubjectType(this.subjectType) 074 .boxSubjectId(this.subjectId) 075 .build()); 076 this.tokenStorage.store(token); 077 return token; 078 } 079 080 /** Return a current token or get a new one when not available. */ 081 public AccessToken retrieveToken() { 082 return retrieveToken(null); 083 } 084 085 /** 086 * Return a current token or get a new one when not available. 087 * 088 * @param networkSession An object to keep network session state 089 */ 090 @Override 091 public AccessToken retrieveToken(NetworkSession networkSession) { 092 AccessToken oldToken = this.tokenStorage.get(); 093 if (oldToken == null) { 094 AccessToken newToken = this.refreshToken(networkSession); 095 return newToken; 096 } 097 return oldToken; 098 } 099 100 public String retrieveAuthorizationHeader() { 101 return retrieveAuthorizationHeader(null); 102 } 103 104 @Override 105 public String retrieveAuthorizationHeader(NetworkSession networkSession) { 106 AccessToken token = this.retrieveToken(networkSession); 107 return String.join("", "Bearer ", token.getAccessToken()); 108 } 109 110 /** 111 * Create a new BoxCCGAuth instance that uses the provided user ID as the subject ID. May be one 112 * of this application's created App User. Depending on the configured User Access Level, may also 113 * be any other App User or Managed User in the enterprise. 114 * <https://developer.box.com/en/guides/applications/> 115 * <https://developer.box.com/en/guides/authentication/select/> 116 * 117 * @param userId The id of the user to authenticate 118 */ 119 public BoxCCGAuth withUserSubject(String userId) { 120 return withUserSubject(userId, new InMemoryTokenStorage()); 121 } 122 123 /** 124 * Create a new BoxCCGAuth instance that uses the provided user ID as the subject ID. May be one 125 * of this application's created App User. Depending on the configured User Access Level, may also 126 * be any other App User or Managed User in the enterprise. 127 * <https://developer.box.com/en/guides/applications/> 128 * <https://developer.box.com/en/guides/authentication/select/> 129 * 130 * @param userId The id of the user to authenticate 131 * @param tokenStorage Object responsible for storing token in newly created BoxCCGAuth. If no 132 * custom implementation provided, the token will be stored in memory. 133 */ 134 public BoxCCGAuth withUserSubject(String userId, TokenStorage tokenStorage) { 135 CCGConfig newConfig = 136 new CCGConfig.Builder(this.config.getClientId(), this.config.getClientSecret()) 137 .enterpriseId(this.config.getEnterpriseId()) 138 .userId(userId) 139 .tokenStorage(tokenStorage) 140 .build(); 141 return new BoxCCGAuth(newConfig); 142 } 143 144 /** 145 * Create a new BoxCCGAuth instance that uses the provided enterprise ID as the subject ID. 146 * 147 * @param enterpriseId The id of the enterprise to authenticate 148 */ 149 public BoxCCGAuth withEnterpriseSubject(String enterpriseId) { 150 return withEnterpriseSubject(enterpriseId, new InMemoryTokenStorage()); 151 } 152 153 /** 154 * Create a new BoxCCGAuth instance that uses the provided enterprise ID as the subject ID. 155 * 156 * @param enterpriseId The id of the enterprise to authenticate 157 * @param tokenStorage Object responsible for storing token in newly created BoxCCGAuth. If no 158 * custom implementation provided, the token will be stored in memory. 159 */ 160 public BoxCCGAuth withEnterpriseSubject(String enterpriseId, TokenStorage tokenStorage) { 161 CCGConfig newConfig = 162 new CCGConfig.Builder(this.config.getClientId(), this.config.getClientSecret()) 163 .enterpriseId(enterpriseId) 164 .userId(null) 165 .tokenStorage(tokenStorage) 166 .build(); 167 return new BoxCCGAuth(newConfig); 168 } 169 170 /** 171 * Downscope access token to the provided scopes. Returning a new access token with the provided 172 * scopes, with the original access token unchanged. 173 * 174 * @param scopes The scope(s) to apply to the resulting token. 175 * @param resource The file or folder to get a downscoped token for. If None and shared_link None, 176 * the resulting token will not be scoped down to just a single item. The resource should be a 177 * full URL to an item, e.g. https://api.box.com/2.0/files/123456. 178 * @param sharedLink The shared link to get a downscoped token for. If None and item None, the 179 * resulting token will not be scoped down to just a single item. 180 * @param networkSession An object to keep network session state 181 */ 182 @Override 183 public AccessToken downscopeToken( 184 List<String> scopes, String resource, String sharedLink, NetworkSession networkSession) { 185 AccessToken token = this.retrieveToken(networkSession); 186 if (token == null) { 187 throw new BoxSDKError( 188 "No access token is available. Make an API call to retrieve a token before calling this method."); 189 } 190 AuthorizationManager authManager = 191 new AuthorizationManager.Builder() 192 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 193 .build(); 194 AccessToken downscopedToken = 195 authManager.requestAccessToken( 196 new PostOAuth2Token.Builder( 197 PostOAuth2TokenGrantTypeField.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE) 198 .subjectToken(token.getAccessToken()) 199 .subjectTokenType( 200 PostOAuth2TokenSubjectTokenTypeField 201 .URN_IETF_PARAMS_OAUTH_TOKEN_TYPE_ACCESS_TOKEN) 202 .resource(resource) 203 .scope(String.join(" ", scopes)) 204 .boxSharedLink(sharedLink) 205 .build()); 206 return downscopedToken; 207 } 208 209 /** Revoke the current access token and remove it from token storage. */ 210 public void revokeToken() { 211 revokeToken(null); 212 } 213 214 /** 215 * Revoke the current access token and remove it from token storage. 216 * 217 * @param networkSession An object to keep network session state 218 */ 219 @Override 220 public void revokeToken(NetworkSession networkSession) { 221 AccessToken oldToken = this.tokenStorage.get(); 222 if (oldToken == null) { 223 return; 224 } 225 AuthorizationManager authManager = 226 new AuthorizationManager.Builder() 227 .networkSession((!(networkSession == null) ? networkSession : new NetworkSession())) 228 .build(); 229 authManager.revokeAccessToken( 230 new PostOAuth2Revoke.Builder() 231 .clientId(this.config.getClientId()) 232 .clientSecret(this.config.getClientSecret()) 233 .token(oldToken.getAccessToken()) 234 .build()); 235 this.tokenStorage.clear(); 236 } 237 238 public TokenStorage getTokenStorage() { 239 return tokenStorage; 240 } 241}