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   * &lt;https://developer.box.com/en/guides/applications/&gt;
115   * &lt;https://developer.box.com/en/guides/authentication/select/&gt;
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   * &lt;https://developer.box.com/en/guides/applications/&gt;
128   * &lt;https://developer.box.com/en/guides/authentication/select/&gt;
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}