• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

box / box-java-sdk / #5076

07 Oct 2025 12:35PM UTC coverage: 37.132% (+0.007%) from 37.125%
#5076

push

github

web-flow
test: Change `Event.additionalDetails` field assertion in events test (box/box-codegen#858) (#1491)

18454 of 49699 relevant lines covered (37.13%)

0.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.14
/src/main/java/com/box/sdkgen/box/jwtauth/BoxJWTAuth.java
1
package com.box.sdkgen.box.jwtauth;
2

3
import static com.box.sdkgen.internal.utils.UtilsManager.createJwtAssertion;
4
import static com.box.sdkgen.internal.utils.UtilsManager.entryOf;
5
import static com.box.sdkgen.internal.utils.UtilsManager.getEpochTimeInSeconds;
6
import static com.box.sdkgen.internal.utils.UtilsManager.getUuid;
7
import static com.box.sdkgen.internal.utils.UtilsManager.isBrowser;
8
import static com.box.sdkgen.internal.utils.UtilsManager.mapOf;
9

10
import com.box.sdkgen.box.errors.BoxSDKError;
11
import com.box.sdkgen.box.tokenstorage.InMemoryTokenStorage;
12
import com.box.sdkgen.box.tokenstorage.TokenStorage;
13
import com.box.sdkgen.internal.utils.JwtKey;
14
import com.box.sdkgen.internal.utils.JwtSignOptions;
15
import com.box.sdkgen.managers.authorization.AuthorizationManager;
16
import com.box.sdkgen.networking.auth.Authentication;
17
import com.box.sdkgen.networking.network.NetworkSession;
18
import com.box.sdkgen.schemas.accesstoken.AccessToken;
19
import com.box.sdkgen.schemas.postoauth2revoke.PostOAuth2Revoke;
20
import com.box.sdkgen.schemas.postoauth2token.PostOAuth2Token;
21
import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenGrantTypeField;
22
import com.box.sdkgen.schemas.postoauth2token.PostOAuth2TokenSubjectTokenTypeField;
23
import java.util.List;
24
import java.util.Map;
25

26
public class BoxJWTAuth implements Authentication {
27

28
  /** An object containing all JWT configuration to use for authentication */
29
  public final JWTConfig config;
30

31
  /**
32
   * An object responsible for storing token. If no custom implementation provided, the token will
33
   * be stored in memory.
34
   */
35
  public final TokenStorage tokenStorage;
36

37
  /**
38
   * The ID of the user or enterprise to authenticate as. If not provided, defaults to the
39
   * enterprise ID if set, otherwise defaults to the user ID.
40
   */
41
  public String subjectId;
42

43
  /** The type of the subject ID provided. Must be either 'user' or 'enterprise'. */
44
  public String subjectType;
45

46
  public BoxJWTAuth(JWTConfig config) {
1✔
47
    this.config = config;
1✔
48
    this.tokenStorage = this.config.getTokenStorage();
1✔
49
    this.subjectId =
1✔
50
        (!(this.config.getEnterpriseId() == null)
1✔
51
            ? this.config.getEnterpriseId()
1✔
52
            : this.config.getUserId());
1✔
53
    this.subjectType = (!(this.config.getEnterpriseId() == null) ? "enterprise" : "user");
1✔
54
  }
1✔
55

56
  /** Get new access token using JWT auth. */
57
  public AccessToken refreshToken() {
58
    return refreshToken(null);
×
59
  }
60

61
  /**
62
   * Get new access token using JWT auth.
63
   *
64
   * @param networkSession An object to keep network session state
65
   */
66
  @Override
67
  public AccessToken refreshToken(NetworkSession networkSession) {
68
    if (isBrowser()) {
1✔
69
      throw new BoxSDKError("JWT auth is not supported in browser environment.");
×
70
    }
71
    Map<String, Object> claims =
1✔
72
        mapOf(
1✔
73
            entryOf("exp", getEpochTimeInSeconds() + 30),
1✔
74
            entryOf("box_sub_type", this.subjectType));
1✔
75
    JwtSignOptions jwtOptions =
1✔
76
        new JwtSignOptions(
77
            this.config.getAlgorithm(),
1✔
78
            "https://api.box.com/oauth2/token",
79
            this.config.getClientId(),
1✔
80
            this.subjectId,
81
            getUuid(),
1✔
82
            this.config.getJwtKeyId(),
1✔
83
            this.config.getPrivateKeyDecryptor());
1✔
84
    JwtKey jwtKey = new JwtKey(this.config.getPrivateKey(), this.config.getPrivateKeyPassphrase());
1✔
85
    String assertion = createJwtAssertion(claims, jwtKey, jwtOptions);
1✔
86
    AuthorizationManager authManager =
1✔
87
        new AuthorizationManager.Builder()
88
            .networkSession((!(networkSession == null) ? networkSession : new NetworkSession()))
1✔
89
            .build();
1✔
90
    AccessToken token =
1✔
91
        authManager.requestAccessToken(
1✔
92
            new PostOAuth2Token.Builder(
93
                    PostOAuth2TokenGrantTypeField.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_JWT_BEARER)
94
                .assertion(assertion)
1✔
95
                .clientId(this.config.getClientId())
1✔
96
                .clientSecret(this.config.getClientSecret())
1✔
97
                .build());
1✔
98
    this.tokenStorage.store(token);
1✔
99
    return token;
1✔
100
  }
101

102
  /**
103
   * Get the current access token. If the current access token is expired or not found, this method
104
   * will attempt to refresh the token.
105
   */
106
  public AccessToken retrieveToken() {
107
    return retrieveToken(null);
1✔
108
  }
109

110
  /**
111
   * Get the current access token. If the current access token is expired or not found, this method
112
   * will attempt to refresh the token.
113
   *
114
   * @param networkSession An object to keep network session state
115
   */
116
  @Override
117
  public AccessToken retrieveToken(NetworkSession networkSession) {
118
    AccessToken oldToken = this.tokenStorage.get();
1✔
119
    if (oldToken == null) {
1✔
120
      AccessToken newToken = this.refreshToken(networkSession);
1✔
121
      return newToken;
1✔
122
    }
123
    return oldToken;
1✔
124
  }
125

126
  public String retrieveAuthorizationHeader() {
127
    return retrieveAuthorizationHeader(null);
×
128
  }
129

130
  @Override
131
  public String retrieveAuthorizationHeader(NetworkSession networkSession) {
132
    AccessToken token = this.retrieveToken(networkSession);
1✔
133
    return String.join("", "Bearer ", token.getAccessToken());
1✔
134
  }
135

136
  /**
137
   * Create a new BoxJWTAuth instance that uses the provided user ID as the subject of the JWT
138
   * assertion. May be one of this application's created App User. Depending on the configured User
139
   * Access Level, may also be any other App User or Managed User in the enterprise.
140
   * &lt;https://developer.box.com/en/guides/applications/&gt;
141
   * &lt;https://developer.box.com/en/guides/authentication/select/&gt;
142
   *
143
   * @param userId The id of the user to authenticate
144
   */
145
  public BoxJWTAuth withUserSubject(String userId) {
146
    return withUserSubject(userId, new InMemoryTokenStorage());
1✔
147
  }
148

149
  /**
150
   * Create a new BoxJWTAuth instance that uses the provided user ID as the subject of the JWT
151
   * assertion. May be one of this application's created App User. Depending on the configured User
152
   * Access Level, may also be any other App User or Managed User in the enterprise.
153
   * &lt;https://developer.box.com/en/guides/applications/&gt;
154
   * &lt;https://developer.box.com/en/guides/authentication/select/&gt;
155
   *
156
   * @param userId The id of the user to authenticate
157
   * @param tokenStorage Object responsible for storing token in newly created BoxJWTAuth. If no
158
   *     custom implementation provided, the token will be stored in memory.
159
   */
160
  public BoxJWTAuth withUserSubject(String userId, TokenStorage tokenStorage) {
161
    JWTConfig newConfig =
1✔
162
        new JWTConfig.Builder(
163
                this.config.getClientId(),
1✔
164
                this.config.getClientSecret(),
1✔
165
                this.config.getJwtKeyId(),
1✔
166
                this.config.getPrivateKey(),
1✔
167
                this.config.getPrivateKeyPassphrase())
1✔
168
            .enterpriseId(null)
1✔
169
            .userId(userId)
1✔
170
            .tokenStorage(tokenStorage)
1✔
171
            .build();
1✔
172
    BoxJWTAuth newAuth = new BoxJWTAuth(newConfig);
1✔
173
    return newAuth;
1✔
174
  }
175

176
  /**
177
   * Create a new BoxJWTAuth instance that uses the provided enterprise ID as the subject of the JWT
178
   * assertion.
179
   *
180
   * @param enterpriseId The id of the enterprise to authenticate
181
   */
182
  public BoxJWTAuth withEnterpriseSubject(String enterpriseId) {
183
    return withEnterpriseSubject(enterpriseId, new InMemoryTokenStorage());
1✔
184
  }
185

186
  /**
187
   * Create a new BoxJWTAuth instance that uses the provided enterprise ID as the subject of the JWT
188
   * assertion.
189
   *
190
   * @param enterpriseId The id of the enterprise to authenticate
191
   * @param tokenStorage Object responsible for storing token in newly created BoxJWTAuth. If no
192
   *     custom implementation provided, the token will be stored in memory.
193
   */
194
  public BoxJWTAuth withEnterpriseSubject(String enterpriseId, TokenStorage tokenStorage) {
195
    JWTConfig newConfig =
1✔
196
        new JWTConfig.Builder(
197
                this.config.getClientId(),
1✔
198
                this.config.getClientSecret(),
1✔
199
                this.config.getJwtKeyId(),
1✔
200
                this.config.getPrivateKey(),
1✔
201
                this.config.getPrivateKeyPassphrase())
1✔
202
            .enterpriseId(enterpriseId)
1✔
203
            .userId(null)
1✔
204
            .tokenStorage(tokenStorage)
1✔
205
            .build();
1✔
206
    BoxJWTAuth newAuth = new BoxJWTAuth(newConfig);
1✔
207
    return newAuth;
1✔
208
  }
209

210
  /**
211
   * Downscope access token to the provided scopes. Returning a new access token with the provided
212
   * scopes, with the original access token unchanged.
213
   *
214
   * @param scopes The scope(s) to apply to the resulting token.
215
   * @param resource The file or folder to get a downscoped token for. If None and shared_link None,
216
   *     the resulting token will not be scoped down to just a single item. The resource should be a
217
   *     full URL to an item, e.g. https://api.box.com/2.0/files/123456.
218
   * @param sharedLink The shared link to get a downscoped token for. If None and item None, the
219
   *     resulting token will not be scoped down to just a single item.
220
   * @param networkSession An object to keep network session state
221
   */
222
  @Override
223
  public AccessToken downscopeToken(
224
      List<String> scopes, String resource, String sharedLink, NetworkSession networkSession) {
225
    AccessToken token = this.retrieveToken(networkSession);
1✔
226
    if (token == null) {
1✔
227
      throw new BoxSDKError(
×
228
          "No access token is available. Make an API call to retrieve a token before calling this method.");
229
    }
230
    AuthorizationManager authManager =
1✔
231
        new AuthorizationManager.Builder()
232
            .networkSession((!(networkSession == null) ? networkSession : new NetworkSession()))
1✔
233
            .build();
1✔
234
    AccessToken downscopedToken =
1✔
235
        authManager.requestAccessToken(
1✔
236
            new PostOAuth2Token.Builder(
237
                    PostOAuth2TokenGrantTypeField.URN_IETF_PARAMS_OAUTH_GRANT_TYPE_TOKEN_EXCHANGE)
238
                .subjectToken(token.getAccessToken())
1✔
239
                .subjectTokenType(
1✔
240
                    PostOAuth2TokenSubjectTokenTypeField
241
                        .URN_IETF_PARAMS_OAUTH_TOKEN_TYPE_ACCESS_TOKEN)
242
                .resource(resource)
1✔
243
                .scope(String.join(" ", scopes))
1✔
244
                .boxSharedLink(sharedLink)
1✔
245
                .build());
1✔
246
    return downscopedToken;
1✔
247
  }
248

249
  /** Revoke the current access token and remove it from token storage. */
250
  public void revokeToken() {
251
    revokeToken(null);
1✔
252
  }
1✔
253

254
  /**
255
   * Revoke the current access token and remove it from token storage.
256
   *
257
   * @param networkSession An object to keep network session state
258
   */
259
  @Override
260
  public void revokeToken(NetworkSession networkSession) {
261
    AccessToken oldToken = this.tokenStorage.get();
1✔
262
    if (oldToken == null) {
1✔
263
      return;
×
264
    }
265
    AuthorizationManager authManager =
1✔
266
        new AuthorizationManager.Builder()
267
            .networkSession((!(networkSession == null) ? networkSession : new NetworkSession()))
1✔
268
            .build();
1✔
269
    authManager.revokeAccessToken(
1✔
270
        new PostOAuth2Revoke.Builder()
271
            .clientId(this.config.getClientId())
1✔
272
            .clientSecret(this.config.getClientSecret())
1✔
273
            .token(oldToken.getAccessToken())
1✔
274
            .build());
1✔
275
    this.tokenStorage.clear();
1✔
276
  }
1✔
277

278
  public JWTConfig getConfig() {
279
    return config;
×
280
  }
281

282
  public TokenStorage getTokenStorage() {
283
    return tokenStorage;
×
284
  }
285
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc