@@ -51,6 +51,7 @@ public class ConfidentialClient implements OAuth2Client {
5151 private long jwsIssuedAt ;
5252 private long accessTokenExpireTime ;
5353 private AccessToken accessToken ;
54+ private final long accessTokenExpiryOffsetMillis ;
5455
5556 /**
5657 * Creates a new ConfidentialClient. When setting up the OAuth 2.0 client, this constructor reaches out to
@@ -66,7 +67,7 @@ public class ConfidentialClient implements OAuth2Client {
6667 public ConfidentialClient (final String configPath )
6768 throws AuthServerMetadataContentException , AuthServerMetadataException ,
6869 ConfigurationException {
69- this (new Configuration (configPath ));
70+ this (new Configuration (configPath ), RequestOptions . builder (). build (), Constants . DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
7071 }
7172
7273 /**
@@ -84,7 +85,19 @@ public ConfidentialClient(final String configPath)
8485 public ConfidentialClient (final String configPath , RequestOptions requestOptions )
8586 throws AuthServerMetadataContentException , AuthServerMetadataException ,
8687 ConfigurationException {
87- this (new Configuration (configPath ), requestOptions );
88+ this (new Configuration (configPath ), requestOptions , Constants .DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
89+ }
90+
91+ /**
92+ * Creates a new ConfidentialClient with a custom proactive expiry offset.
93+ * @param configPath path to config file
94+ * @param requestOptions request options (proxy/ssl)
95+ * @param accessTokenExpiryOffsetMillis milliseconds subtracted from server expiry (non-negative)
96+ */
97+ public ConfidentialClient (final String configPath , RequestOptions requestOptions , long accessTokenExpiryOffsetMillis )
98+ throws AuthServerMetadataContentException , AuthServerMetadataException ,
99+ ConfigurationException {
100+ this (new Configuration (configPath ), requestOptions , accessTokenExpiryOffsetMillis );
88101 }
89102
90103 /**
@@ -99,7 +112,7 @@ public ConfidentialClient(final String configPath, RequestOptions requestOptions
99112 */
100113 public ConfidentialClient (final Configuration config )
101114 throws AuthServerMetadataContentException , AuthServerMetadataException {
102- this (config , RequestOptions .builder ().build ());
115+ this (config , RequestOptions .builder ().build (), Constants . DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
103116 }
104117
105118 /**
@@ -115,11 +128,22 @@ public ConfidentialClient(final Configuration config)
115128 */
116129 public ConfidentialClient (final Configuration config , RequestOptions requestOptions )
117130 throws AuthServerMetadataContentException , AuthServerMetadataException {
131+ this (config , requestOptions , Constants .DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
132+ }
133+
134+ /**
135+ * Core constructor with configurable access token proactive expiry offset.
136+ * @param config configuration
137+ * @param requestOptions request options
138+ * @param accessTokenExpiryOffsetMillis milliseconds to subtract from token lifetime when computing internal expiry
139+ */
140+ public ConfidentialClient (final Configuration config , RequestOptions requestOptions , long accessTokenExpiryOffsetMillis )
141+ throws AuthServerMetadataContentException , AuthServerMetadataException {
118142 Objects .requireNonNull (config , "Configuration object must not be null" );
119143 this .config = config ;
120144 LOGGER .debug ("Finished initialising configuration" );
121145 this .requestOptions = requestOptions == null ? RequestOptions .builder ().build () : requestOptions ;
122-
146+ this . accessTokenExpiryOffsetMillis = accessTokenExpiryOffsetMillis ;
123147 this .requestProviderMetadata ();
124148 }
125149
@@ -139,7 +163,7 @@ protected ConfidentialClient(final String configPath, final TokenRequestBuilder
139163 throws AuthServerMetadataContentException ,
140164 AuthServerMetadataException ,
141165 ConfigurationException {
142- this (new Configuration (configPath ));
166+ this (new Configuration (configPath ), RequestOptions . builder (). build (), Constants . DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
143167 this .tokenRequestBuilder = tokReqBuilder .uri (this .providerMetadata .getTokenEndpointURI ());
144168 }
145169
@@ -157,7 +181,7 @@ protected ConfidentialClient(final String configPath, final TokenRequestBuilder
157181 protected ConfidentialClient (final Configuration config , final TokenRequestBuilder tokReqBuilder )
158182 throws AuthServerMetadataContentException ,
159183 AuthServerMetadataException {
160- this (config );
184+ this (config , RequestOptions . builder (). build (), Constants . DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
161185 this .tokenRequestBuilder = tokReqBuilder .uri (this .providerMetadata .getTokenEndpointURI ());
162186 }
163187
@@ -176,7 +200,7 @@ protected ConfidentialClient(final Configuration config, final TokenRequestBuild
176200 protected ConfidentialClient (final Configuration config , final TokenRequestBuilder tokReqBuilder , RequestOptions requestOptions )
177201 throws AuthServerMetadataContentException ,
178202 AuthServerMetadataException {
179- this (config , requestOptions );
203+ this (config , requestOptions , Constants . DEFAULT_ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS );
180204 this .tokenRequestBuilder = tokReqBuilder .uri (this .providerMetadata .getTokenEndpointURI ());
181205 }
182206
@@ -283,7 +307,7 @@ private String fetchAccessToken() throws AccessTokenException, SigningJwsExcepti
283307 if (tokenRes .indicatesSuccess ()) {
284308 this .accessToken = tokenRes .toSuccessResponse ().getTokens ().getAccessToken ();
285309 this .accessTokenExpireTime =
286- this .jwsIssuedAt + TimeUnit .SECONDS .toMillis (this .accessToken .getLifetime ()) - Constants . ACCESS_TOKEN_EXPIRY_OFFSET_MILLIS ;
310+ this .jwsIssuedAt + TimeUnit .SECONDS .toMillis (this .accessToken .getLifetime ()) - this . accessTokenExpiryOffsetMillis ;
287311 LOGGER .info ("Fetched access token which expires in: {} seconds (buffered)" , this .accessToken .getLifetime ());
288312 return this .accessToken .toString ();
289313 }
0 commit comments