Authentication
Why one section covers both directions, what the three packages contain, how a token is obtained and reused, and whose authority it carries.
A microservice authenticates in two directions. It validates the tokens it is given, and it presents
tokens to the services it calls. Both are configured from one Authentication section here, because in
practice they name the same provider and are deployed together.
The outbound half asks a second question: whose authority the token carries. The client credentials grant answers "this service"; token exchange answers "whoever this service is serving". Both are available at once and are chosen per call site.
Packages
| Package | Contains |
|---|---|
ApricotFramework.Authentication.Abstractions | The contracts alone: what a caller asks, what comes back, how it fails. Zero dependencies. |
ApricotFramework.Authentication | The client credentials and token exchange grants. Zero dependencies. |
ApricotFramework.Authentication.AspNetCore | JWT bearer validation, configuration binding, registration. |
ApricotFramework.Authentication.ErrorDefinitions | Answers authentication failures as problem+json. |
Reference Abstractions from a client library — a gRPC, REST or messaging client — that needs a token presented but has no business knowing how one is obtained. It cannot reach the implementation, and it does not move when the implementation does.
Reference the core from the host that actually obtains tokens. It has no dependencies either —
HttpClient and System.Text.Json are both in the shared framework — so a console or worker process
can obtain tokens without referencing ASP.NET Core.
Obtaining a token
A token request needs an endpoint, and the endpoint comes from the provider's own metadata rather than from configuration. Two things about that document are checked before it is used:
- the
issuerit claims must be the authority that was asked for it, and - the
token_endpointit names must be on the same host.
Without the second check, a substituted or tampered metadata document names an endpoint of its own and the client secret is sent to whoever answers there. Both checks are why the authority is the only URL in configuration.
What is obtained is then reused. A token is cached until its stated expiry less a small margin, so one handed out is never about to expire in flight, and the discovered endpoint is cached for an hour. A cold cache under load makes exactly one token request: concurrent callers for the same credentials and scopes join the request already running rather than starting their own.
Note
The cache is process-local. Each instance of a service obtains its own tokens, which needs
no shared infrastructure and puts no credential anywhere another host can read. Registering an
ITokenCache before AddClientAuthentication replaces it.
Which failures are whose
A failure to obtain a token for an onward call is a fault of the service holding the credentials, never
of whoever called it. Answering 401 would tell the caller to re-authenticate, which cannot help, and
would record a service fault as a client error. TokenRequestException.Reason is what separates
the case where waiting helps from the case where a person has to change something — see
Error definitions.