@@ -13,7 +13,7 @@ public interface TokenProvider {
1313 Token getToken ();
1414
1515 /** Token represents an access_token + refresh_token pair. */
16- public record Token (String accessToken , String refreshToken , Instant createdAt , long expiresIn ) {
16+ public record Token (String accessToken , String refreshToken , Instant createdAt , long expiresIn , long expiryDelta ) {
1717 /**
1818 * Returns {@code true} if remaining lifetime of the token is greater than 0.
1919 * Tokens created with {@link #expireNever} are always valid.
@@ -22,8 +22,21 @@ public boolean isValid() {
2222 if (expiresIn == -1 ) {
2323 return true ;
2424 }
25- // TODO: adjust for expireDelta
26- return Instant .now ().isAfter (createdAt .plusSeconds (expiresIn ));
25+ return Instant .now ().isBefore (createdAt .plusSeconds (expiresIn - expiryDelta ));
26+ }
27+
28+ /**
29+ * Set early expiry for the Token.
30+ *
31+ * <p>
32+ * A Token with {@link #expiresIn} of 10s and {@link #expiryDelta} of 3s
33+ * will be invalid 7s after being created.
34+ *
35+ * @param expiryDelta Early expiry in seconds.
36+ * @return A Token identical to the source one, but with a different expiry.
37+ */
38+ public Token withExpiryDelta (long expiryDelta ) {
39+ return new Token (accessToken , refreshToken , createdAt , expiresIn , expiryDelta );
2740 }
2841
2942 /**
@@ -36,11 +49,13 @@ public boolean isValid() {
3649 * @return A new Token.
3750 */
3851 public static Token expireAfter (String accessToken , String refreshToken , long expiresIn ) {
39- return new Token (accessToken , refreshToken , Instant .now (), expiresIn );
52+ return new Token (accessToken , refreshToken , Instant .now (), expiresIn , 0 );
4053 }
4154
4255 /**
4356 * Create a token that does not have a refresh_token.
57+ * For example, a token obtained via a Client Credentials grant
58+ * can only be renewed using that grant type.
4459 *
4560 * @param accessToken Access token.
4661 * @param expiresIn Remaining token lifetime in seconds.
@@ -62,6 +77,20 @@ public static Token expireNever(String accessToken) {
6277 }
6378 }
6479
80+ /**
81+ * Refreshing the token slightly ahead of time will help prevent
82+ * phony unauthorized access errors.
83+ *
84+ * This value is currently not configuratble and should be seen
85+ * as an internal implementation detail.
86+ */
87+ static long DEFAULT_EARLY_EXPIRY = 30 ;
88+
89+ /**
90+ * Authorize using a token that never expires and doesn't need to be refreshed.
91+ *
92+ * @param apiKey Access token.
93+ */
6594 public static TokenProvider staticToken (String accessToken ) {
6695 final var token = Token .expireNever (accessToken );
6796 return () -> token ;
@@ -83,7 +112,7 @@ public static TokenProvider staticToken(String accessToken) {
83112 public static TokenProvider bearerToken (OidcConfig oidc , String accessToken , String refreshToken , long expiresIn ) {
84113 final var token = Token .expireAfter (accessToken , refreshToken , expiresIn );
85114 final var provider = NimbusTokenProvider .refreshToken (oidc , token );
86- return reuse (token , provider );
115+ return reuse (token , provider , DEFAULT_EARLY_EXPIRY );
87116 }
88117
89118 /**
@@ -99,7 +128,7 @@ public static TokenProvider bearerToken(OidcConfig oidc, String accessToken, Str
99128 */
100129 public static TokenProvider resourceOwnerPassword (OidcConfig oidc , String username , String password ) {
101130 final var passwordGrant = NimbusTokenProvider .resourceOwnerPassword (oidc , username , password );
102- return reuse (null , exchange (oidc , passwordGrant ));
131+ return reuse (null , exchange (oidc , passwordGrant ), DEFAULT_EARLY_EXPIRY );
103132 }
104133
105134 /**
@@ -115,7 +144,7 @@ public static TokenProvider resourceOwnerPassword(OidcConfig oidc, String userna
115144 */
116145 public static TokenProvider clientCredentials (OidcConfig oidc , String clientId , String clientSecret ) {
117146 final var provider = NimbusTokenProvider .clientCredentials (oidc , clientId , clientSecret );
118- return reuse (null , provider );
147+ return reuse (null , provider , DEFAULT_EARLY_EXPIRY );
119148 }
120149
121150 /**
@@ -133,6 +162,14 @@ static TokenProvider reuse(Token t, TokenProvider tp) {
133162 return ReuseTokenProvider .wrap (t , tp );
134163 }
135164
165+ /**
166+ * Obtain a TokenProvider which reuses tokens obtained
167+ * from another TokenProvider until they expire.
168+ */
169+ static TokenProvider reuse (Token t , TokenProvider tp , long expiryDelta ) {
170+ return ReuseTokenProvider .wrap (t , tp , expiryDelta );
171+ }
172+
136173 public record ProviderMetadata (URI tokenEndpoint ) {
137174 }
138175
0 commit comments