Class CachingTokenSource
- All Implemented Interfaces:
TokenSource,AutoCloseable
- Direct Known Subclasses:
FederatedAssertionTokenSource,NativeSecretTokenSource,PrivateKeyJwtTokenSource
TokenSource, so the three
mechanisms differ in exactly one method and cannot drift apart in the parts that are not about
the credential at all.
Four guarantees, taken from a cache the platform already runs
These are the guarantees OAuthTokenCache in ankasecure-integration-support
provides on the server side. They are re-implemented rather than imported because the SDK is a
standalone client-layer artifact with no internal dependencies, and acquiring one to reuse
seventy lines would put the whole integration tier on a customer's classpath.
- Reuse within validity - a cached token outside the refresh window is returned without touching the token endpoint.
- Refresh-before-expiry skew - a token within sixty seconds of expiry is treated as already expired. The caller's clock and the server's clock are not the same clock, and the token still has to survive the flight time of the operation it was fetched for. Sixty seconds is the platform's own number: the same window the server-side cache uses and the same skew the actor-proof verifier admits.
- Single-flight - one thread mints and the rest observe its result, so a thousand threads waking to an expired token produce one token request, not a thousand.
- No poison on failure - a failed mint leaves any previously cached token exactly as it was. A transient outage must not turn a working session into a broken one.
Tokens live only in this object's memory. They are never logged, never written to disk, never
placed in an exception message, and are zeroized as far as the JVM permits on
invalidate() and close().
Minting binds
Every path that produces a token also binds it to the transport, and accessToken()
re-binds even on a cache hit. Binding is therefore idempotent and the transport cannot be left
holding a token this source has already discarded.
-
Method Summary
Modifier and TypeMethodDescriptionfinal StringReturns a token that is valid now, minting one if none is cached or the cached one is inside the refresh window, and binding whatever it returns to the transport.final InstantThe instant the currently cached token expires.voidclose()Discards the cached token.final InstantWhen the token currently in force expires, if this source knows.final booleanWhether a token is currently cached.voidDiscards the cached token and unbinds it from the transport.Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface co.ankatech.ankasecure.sdk.auth.TokenSource
mechanism
-
Method Details
-
accessToken
Description copied from interface:TokenSourceReturns a token that is valid now, minting one if none is cached or the cached one is inside the refresh window, and binding whatever it returns to the transport.Concurrent callers of a stale source do not stampede the token endpoint: exactly one mints and the rest observe its result.
- Specified by:
accessTokenin interfaceTokenSource- Returns:
- the ANKASecure access token; never
nulland never blank - Throws:
AnkaSecureSdkException- if a token cannot be obtained. A failure leaves any previously cached token untouched rather than poisoning the cache with the failure.
-
invalidate
public void invalidate()Discards the cached token and unbinds it from the transport.Not
final, and the reason is a defect it used to have. A source whose credential is itself produced by something that caches - the federated one, whose provider may hold an external token under that issuer's stated lifetime - needs invalidation to reach through to it. While this method was sealed it could not, so a caller invalidating after an external secret was rotated got a fresh ANKASecure mint built from the same stale external token, which is exactly the failure they were clearing. An override extends the reach; it must still callsuper.invalidate(), because the unbinding below is the part no subclass may skip.- Specified by:
invalidatein interfaceTokenSource
-
close
public void close()Discards the cached token. Subclasses holding a credential for re-minting override this, release it, and callsuper.close().It performs the discard directly rather than by calling
invalidate(). Once that method became overridable, routing close through it re-entered the override - so closing a federated source told its provider twice that its token was dead, the second time after the provider had already been closed. Closing releases; invalidating is a caller saying a credential went stale. They are different statements and only one of them belongs in a shutdown path.- Specified by:
closein interfaceAutoCloseable- Specified by:
closein interfaceTokenSource
-
currentTokenExpiry
Description copied from interface:TokenSourceWhen the token currently in force expires, if this source knows.Known for any source that minted its own token, because the issuer states the lifetime in the same response that carried it. Absent for a token the caller supplied from elsewhere - that one arrived with no accompanying statement, and this SDK does not read a token's claims to find out.
- Specified by:
currentTokenExpiryin interfaceTokenSource- Returns:
- the expiry, or
nullwhen nothing is cached or the lifetime is not known
-
cachedExpiry
The instant the currently cached token expires.- Returns:
- the expiry, or
nullwhen nothing is cached
-
hasCachedToken
public final boolean hasCachedToken()Whether a token is currently cached. Reveals no token value.- Returns:
truewhen a token is held
-