001package com.box.sdkgen.box.developertokenauth;
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.PostOAuth2TokenGrantTypeField;
013import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenSubjectTokenTypeField;
014import java.util.List;
015
016public class BoxDeveloperTokenAuth implements Authentication {
017
018  public final String token;
019
020  /** Configuration object of DeveloperTokenAuth. */
021  public DeveloperTokenConfig 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  public BoxDeveloperTokenAuth(String token) {
030    this.token = token;
031    this.config = new DeveloperTokenConfig();
032    this.tokenStorage =
033        new InMemoryTokenStorage.Builder()
034            .token(new AccessToken.Builder().accessToken(this.token).build())
035            .build();
036  }
037
038  protected BoxDeveloperTokenAuth(Builder builder) {
039    this.token = builder.token;
040    this.config = builder.config;
041    this.tokenStorage =
042        new InMemoryTokenStorage.Builder()
043            .token(new AccessToken.Builder().accessToken(this.token).build())
044            .build();
045  }
046
047  /** Retrieves stored developer token */
048  public AccessToken retrieveToken() {
049    return retrieveToken(null);
050  }
051
052  /**
053   * Retrieves stored developer token
054   *
055   * @param networkSession An object to keep network session state
056   */
057  @Override
058  public AccessToken retrieveToken(NetworkSession networkSession) {
059    AccessToken token = this.tokenStorage.get();
060    if (token == null) {
061      throw new BoxSDKError("No access token is available.");
062    }
063    return token;
064  }
065
066  /** Developer token cannot be refreshed */
067  public AccessToken refreshToken() {
068    return refreshToken(null);
069  }
070
071  /**
072   * Developer token cannot be refreshed
073   *
074   * @param networkSession An object to keep network session state
075   */
076  @Override
077  public AccessToken refreshToken(NetworkSession networkSession) {
078    throw new BoxSDKError("Developer token has expired. Please provide a new one.");
079  }
080
081  public String retrieveAuthorizationHeader() {
082    return retrieveAuthorizationHeader(null);
083  }
084
085  @Override
086  public String retrieveAuthorizationHeader(NetworkSession networkSession) {
087    AccessToken token = this.retrieveToken(networkSession);
088    return String.join("", "Bearer ", token.getAccessToken());
089  }
090
091  /**
092   * Revoke an active Access Token, effectively logging a user out that has been previously
093   * authenticated.
094   */
095  public void revokeToken() {
096    revokeToken(null);
097  }
098
099  /**
100   * Revoke an active Access Token, effectively logging a user out that has been previously
101   * authenticated.
102   *
103   * @param networkSession An object to keep network session state
104   */
105  @Override
106  public void revokeToken(NetworkSession networkSession) {
107    AccessToken token = this.tokenStorage.get();
108    if (token == null) {
109      return;
110    }
111    AuthorizationManager authManager =
112        new AuthorizationManager.Builder()
113            .networkSession((!(networkSession == null) ? networkSession : new NetworkSession()))
114            .build();
115    authManager.revokeAccessToken(
116        new PostOAuth2Revoke.Builder()
117            .clientId(this.config.getClientId())
118            .clientSecret(this.config.getClientSecret())
119            .token(token.getAccessToken())
120            .build());
121    this.tokenStorage.clear();
122  }
123
124  /**
125   * Downscope access token to the provided scopes. Returning a new access token with the provided
126   * scopes, with the original access token unchanged.
127   *
128   * @param scopes The scope(s) to apply to the resulting token.
129   * @param resource The file or folder to get a downscoped token for. If None and shared_link None,
130   *     the resulting token will not be scoped down to just a single item. The resource should be a
131   *     full URL to an item, e.g. https://api.box.com/2.0/files/123456.
132   * @param sharedLink The shared link to get a downscoped token for. If None and item None, the
133   *     resulting token will not be scoped down to just a single item.
134   * @param networkSession An object to keep network session state
135   */
136  @Override
137  public AccessToken downscopeToken(
138      List<String> scopes, String resource, String sharedLink, NetworkSession networkSession) {
139    AccessToken token = this.retrieveToken(networkSession);
140    if (token == null || token.getAccessToken() == null) {
141      throw new BoxSDKError("No access token is available.");
142    }
143    AuthorizationManager authManager =
144        new AuthorizationManager.Builder()
145            .networkSession((!(networkSession == null) ? networkSession : new NetworkSession()))
146            .build();
147    AccessToken downscopedToken =
148        authManager.requestAccessToken(
149            new PostOAuth2Token.Builder(
150                    PostOAuth2TokenGrantTypeField.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE)
151                .subjectToken(token.getAccessToken())
152                .subjectTokenType(
153                    PostOAuth2TokenSubjectTokenTypeField
154                        .URN_IETF_PARAMS_OAUTH_TOKEN_TYPE_ACCESS_TOKEN)
155                .resource(resource)
156                .scope(String.join(" ", scopes))
157                .boxSharedLink(sharedLink)
158                .build());
159    return downscopedToken;
160  }
161
162  public TokenStorage getTokenStorage() {
163    return tokenStorage;
164  }
165
166  public static class Builder {
167
168    protected final String token;
169
170    protected DeveloperTokenConfig config;
171
172    public Builder(String token) {
173      this.token = token;
174    }
175
176    public Builder config(DeveloperTokenConfig config) {
177      this.config = config;
178      return this;
179    }
180
181    public BoxDeveloperTokenAuth build() {
182      if (this.config == null) {
183        this.config = new DeveloperTokenConfig();
184      }
185      return new BoxDeveloperTokenAuth(this);
186    }
187  }
188}