Class FederatedAssertionTokenSource
- All Implemented Interfaces:
TokenSource,AutoCloseable
ANKASecure is still the relying party; where the token comes from is the provider's business
The PLATFORM holds no client registration and no credential at any external authorization
server: server-side, the only thing it ever fetches from one is a JWKS, to verify a signature.
That has not changed. What changed is that the WORKLOAD's own credential can now be presented by
this SDK on the workload's behalf - ClientCredentialsExternalTokenProvider performs the
client-credentials grant against the workload's own issuer with the workload's own client secret,
and never with anything of ANKASecure's.
This source cannot tell the difference and deliberately does not try. It asks an
ExternalTokenProvider for a token and carries it across one hop; whether that provider
read the token from a file, ran a command, was handed it, or minted it is the provider's own
business. That is why the SDK still ships no vendor code: what a fetching provider knows about an
authorization server it reads from that server's own discovery document.
The token is opaque, all the way through
Nothing here reads it. Its issuer is not checked, its audience is not compared, its expiry is not consulted, no JWKS is fetched. Every one of those is the relying party's decision and the relying party is the server: it resolves the issuer, verifies the signature against trust material it admitted, and matches the subject to an actor binding. A client that pre-judged would be reimplementing a decision it does not own and would leak, through the shape of its local failures, which of the server's checks would have failed.
The consequence is worth stating plainly: a rejection arrives as one opaque
401 invalid_client, identical for a wrong issuer, an unbound subject, a disabled issuer,
a bad signature and an expired token. That is the server's design, not an omission here - the
costs of the credential kinds are equalised so a caller cannot time-probe which kind a given
client_id uses. What the SDK CAN report precisely is a failure to obtain the external
token in the first place, and it does, as ExternalTokenException.
Asked for on every mint, and discarded at the provider on a refusal
This source caches no external token of its own. It asks the provider on every mint, so a provider that re-reads an out-of-band file sees the current contents, and a provider that caches a token it minted answers from its own cache under its own stated lifetime.
The second case needs one thing this class must supply, because nothing else can. A provider
that caches decides freshness against the CLIENT's clock and a skew, and the platform's refusal is
one opaque 401 invalid_client that names no cause - so a client clock behind the issuer's
would hold a server-dead token for the rest of its stated lifetime, twenty-four hours on some
defaults, and re-present it on every attempt with nothing anywhere reporting why. So a 401
calls ExternalTokenProvider.invalidate() before the refusal is rethrown, and the caller's
existing single retry then arrives with a freshly obtained token. The bound is structural: one
re-fetch per failed mint, never a loop.
-
Constructor Summary
ConstructorsConstructorDescriptionFederatedAssertionTokenSource(co.ankatech.ankasecure.openapi.client.AnkaSecureOpenApiClient client, String clientId, ExternalTokenProvider provider) -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()Closes the provider, then this source.voidDiscards this source's ANKASecure token AND anything the provider cached.Names the credential kind this source presents.provider()Where this source reads its external token.toString()Names the actor and the SOURCE of the token, never the token.Methods inherited from class co.ankatech.ankasecure.sdk.auth.CachingTokenSource
accessToken, cachedExpiry, currentTokenExpiry, hasCachedToken
-
Constructor Details
-
FederatedAssertionTokenSource
public FederatedAssertionTokenSource(co.ankatech.ankasecure.openapi.client.AnkaSecureOpenApiClient client, String clientId, ExternalTokenProvider provider) - Parameters:
client- the transport to mint againstclientId- the ANKASecure actor UUID this external identity is bound to. Required even though the assertion names a subject: the platform resolves the actor before it parses anything the caller supplied.provider- where the external token comes from- Throws:
NullPointerException- if any argument isnull
-
-
Method Details
-
mechanism
Description copied from interface:TokenSourceNames the credential kind this source presents. Diagnostic only; nothing branches on it.- Returns:
- the mechanism; never
null
-
provider
Where this source reads its external token. Exposed for diagnostics and for the containment check that asserts the source in force is the configured one.- Returns:
- the provider; never
null
-
invalidate
public void invalidate()Discards this source's ANKASecure token AND anything the provider cached.Both, because a caller invalidating after an external secret was rotated would otherwise get a fresh ANKASecure mint built from the same stale external token, which is the failure it was trying to clear.
- Specified by:
invalidatein interfaceTokenSource- Overrides:
invalidatein classCachingTokenSource
-
close
public void close()Closes the provider, then this source.The provider retains credential material of its own - an external client secret, a token it minted with it - and after
AuthenticatedSdk.close()nothing else would ever reach it, so both would survive in the heap for the life of the JVM.In a
try/finallyrather than in sequence: a provider whoseclose()threw would otherwise skip the bearer-token clear, and the session would end with the transport still holding a live credential.- Specified by:
closein interfaceAutoCloseable- Specified by:
closein interfaceTokenSource- Overrides:
closein classCachingTokenSource
-
toString
Names the actor and the SOURCE of the token, never the token.
-