@btravstack/oauth-client
@btravstack/oauth-client
Classes
TokenIssuerUnavailable
Defined in: packages/oauth-client/src/token-source.ts:55
The authorization server could not be asked: discovery failed, the network did, or it answered with a server error. Transient, so a later call asks again — a failure is never cached.
Extends
TaggedErrorInstance<"TokenIssuerUnavailable", {cause:unknown;issuer:string; }>
Constructors
Constructor
new TokenIssuerUnavailable(args): TokenIssuerUnavailable;Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("TokenIssuerUnavailable")<{
readonly issuer: string;
readonly cause: unknown;
}>.constructorProperties
| Property | Modifier | Type | Inherited from | Defined in |
|---|---|---|---|---|
_tag | readonly | "TokenIssuerUnavailable" | TaggedError("TokenIssuerUnavailable")._tag | node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363 |
cause | public | unknown | TokenRefused.cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
issuer | readonly | string | TaggedError("TokenIssuerUnavailable").issuer | packages/oauth-client/src/token-source.ts:56 |
message | public | string | TaggedError("TokenIssuerUnavailable").message | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075 |
name | public | string | TaggedError("TokenIssuerUnavailable").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
stack? | public | string | TaggedError("TokenIssuerUnavailable").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
TokenRefused
Defined in: packages/oauth-client/src/token-source.ts:44
The authorization server answered, and the answer was no — an OAuth error (invalid_client, invalid_scope, invalid_request, unauthorized_client…). A configuration or a registration is wrong, so asking again will not help.
It carries the server's error code and description, and never the client secret.
Extends
TaggedErrorInstance<"TokenRefused", {audience:string;description:string|undefined;error:string; }>
Constructors
Constructor
new TokenRefused(args): TokenRefused;Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("TokenRefused")<{
readonly audience: string;
readonly error: string;
readonly description: string | undefined;
}>.constructorProperties
| Property | Modifier | Type | Inherited from | Defined in |
|---|---|---|---|---|
_tag | readonly | "TokenRefused" | TaggedError("TokenRefused")._tag | node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363 |
audience | readonly | string | TaggedError("TokenRefused").audience | packages/oauth-client/src/token-source.ts:45 |
cause? | public | unknown | TaggedError("TokenRefused").cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
description | readonly | string | undefined | TaggedError("TokenRefused").description | packages/oauth-client/src/token-source.ts:47 |
error | readonly | string | TaggedError("TokenRefused").error | packages/oauth-client/src/token-source.ts:46 |
message | public | string | TaggedError("TokenRefused").message | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075 |
name | public | string | TaggedError("TokenRefused").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
stack? | public | string | TaggedError("TokenRefused").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
TokenSource
Defined in: packages/oauth-client/src/token-source.ts:71
The port an application depends on to call another service as itself or for a subject: a bearer token for an audience. oauthClient() provides it over the client credentials grant or RFC 8693 exchange; staticTokenSource is the in-process stand-in.
Extends
PortInstance<"TokenSource",TokenSourceService>
Constructors
Constructor
new TokenSource(): TokenSource;Defined in: packages/di/dist/index.d.mts:16
Returns
Inherited from
Port("TokenSource")<TokenSourceService>.constructorProperties
| Property | Modifier | Type | Inherited from | Defined in |
|---|---|---|---|---|
[ID] | readonly | "TokenSource" | Port("TokenSource").[ID] | packages/di/dist/index.d.mts:12 |
[SERVICE] | readonly | TokenSourceService | Port("TokenSource").[SERVICE] | packages/di/dist/index.d.mts:13 |
portId | readonly | "TokenSource" | Port("TokenSource").portId | packages/di/dist/index.d.mts:17 |
Type Aliases
AccessToken
type AccessToken = object;Defined in: packages/oauth-client/src/token-source.ts:32
A token to present, as Authorization: Bearer <bearer>.
No expiry rides it: keeping a token until shortly before it expires is the source's job, and a caller that held the expiry would be a caller about to cache it a second time.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
bearer | readonly | string | packages/oauth-client/src/token-source.ts:33 |
OAuthClientOptions
type OAuthClientOptions = object;Defined in: packages/oauth-client/src/client.ts:48
What oauthClient is handed. Each of the first three pins the variable named beside it.
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
allowInsecureIssuer? | readonly | boolean | Talk to an http: issuer that is NOT on a loopback host. Default false, and a ConfigInvalid at boot without it: the client secret and every token cross the wire in the open. An option rather than a variable, because its silent change is a security regression. | packages/oauth-client/src/client.ts:61 |
clientId? | readonly | string | Pins OAUTH_CLIENT_ID. | packages/oauth-client/src/client.ts:52 |
clientSecret? | readonly | string | Pins OAUTH_CLIENT_SECRET. A deployment sets the variable, from a Secret. | packages/oauth-client/src/client.ts:54 |
clock? | readonly | Clock | What a token's lifetime is measured against (default: the kernel's systemClock). | packages/oauth-client/src/client.ts:63 |
issuer? | readonly | string | Pins OAUTH_ISSUER — the authorization server, as its discovery document names itself. | packages/oauth-client/src/client.ts:50 |
TokenRequest
type TokenRequest = object;Defined in: packages/oauth-client/src/token-source.ts:12
What a token is asked for: the service it will be presented to, and optionally the scopes it must carry (space-delimited, as OAuth spells them).
On behalf of a subject, supply its token and the RFC 8693 token type. The service still authenticates with its client credentials. An issuer using explicit delegation also takes the acting service's token in actor.
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
audience | readonly | string | The callee, as its authorization server names it: the aud the token is minted for. | packages/oauth-client/src/token-source.ts:14 |
onBehalfOf? | readonly | object | A subject credential to exchange; the issuer must authorize delegation and mint the act claim. | packages/oauth-client/src/token-source.ts:17 |
onBehalfOf.actor? | readonly | object | The acting service's credential, where the issuer requires RFC 8693 actor_token. | packages/oauth-client/src/token-source.ts:21 |
onBehalfOf.actor.token | readonly | string | - | packages/oauth-client/src/token-source.ts:21 |
onBehalfOf.actor.tokenType | readonly | string | - | packages/oauth-client/src/token-source.ts:21 |
onBehalfOf.token | readonly | string | - | packages/oauth-client/src/token-source.ts:18 |
onBehalfOf.tokenType | readonly | string | - | packages/oauth-client/src/token-source.ts:19 |
scope? | readonly | string | - | packages/oauth-client/src/token-source.ts:15 |
TokenSourceService
type TokenSourceService = object;Defined in: packages/oauth-client/src/token-source.ts:60
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
token | readonly | (request) => AsyncResult<AccessToken, | TokenRefused | TokenIssuerUnavailable> | packages/oauth-client/src/token-source.ts:61 |
Functions
oauthClient()
function oauthClient<O>(options?): Module<TokenSource | HealthChecks, ConfigInvalid, EnvReading<
| Unpinned<O, "issuer", "OAUTH_ISSUER">
| Unpinned<O, "clientId", "OAUTH_CLIENT_ID">
| Unpinned<O, "clientSecret", "OAUTH_CLIENT_SECRET">,
| MaybePinned<O, "issuer", "OAUTH_ISSUER">
| MaybePinned<O, "clientId", "OAUTH_CLIENT_ID">
| MaybePinned<O, "clientSecret", "OAUTH_CLIENT_SECRET">>>;Defined in: packages/oauth-client/src/client.ts:292
TokenSource over an OAuth 2.0 authorization server: client credentials for the service itself, or RFC 8693 token exchange for a subject.
Module("Gateway")({ imports: [oauthClient()], provides: [ordersClient] });- Configured from
OAUTH_ISSUER,OAUTH_CLIENT_IDandOAUTH_CLIENT_SECRET, each pinned by its option, validated as the graph is built. A cleartext issuer off loopback is aConfigInvalidunlessallowInsecureIssueris pinned. - Discovery is lazy: the first token asks for the issuer's metadata, and a failed discovery is asked again by the next. An authorization server down at deploy fails the calls that need a token, not the boot.
- A token is kept per audience, scope and subject/actor credentials until a minute before it expires (half its lifetime, if that is shorter), and callers asking for the same one while it is being fetched share that one request. A failure is never kept. The source keeps at most 1024 tokens, evicting the oldest insertion at capacity and removing stale entries when accessed. The complete request is snapshotted at entry, so caller mutation cannot change the credential or grant associated with its cache key.
- Every fetch is reported to
Observers(component: "oauth-client"); a token served from memory reports nothing. - It contributes the
oauth-clienthealth check, failing while the newest-started fetch of any audience/scope pair failed — a rotated secret and an unreachable issuer both show there, where a reachability probe would see only the second.
Type Parameters
| Type Parameter | Default type |
|---|---|
O extends OAuthClientOptions | Record<never, never> |
Parameters
| Parameter | Type |
|---|---|
options | O & OptionsAs<O, OAuthClientOptions> |
Returns
Module<TokenSource | HealthChecks, ConfigInvalid, EnvReading< | Unpinned<O, "issuer", "OAUTH_ISSUER"> | Unpinned<O, "clientId", "OAUTH_CLIENT_ID"> | Unpinned<O, "clientSecret", "OAUTH_CLIENT_SECRET">, | MaybePinned<O, "issuer", "OAUTH_ISSUER"> | MaybePinned<O, "clientId", "OAUTH_CLIENT_ID"> | MaybePinned<O, "clientSecret", "OAUTH_CLIENT_SECRET">>>
staticTokenSource()
function staticTokenSource(bearer): Provider<TokenSource, never, never> & object;Defined in: packages/oauth-client/src/token-source.ts:78
The in-process adapter: the same bearer for every request, and it cannot fail. The shape @btravstack/testing's overridden takes, so a spec swaps the real source under the real root.
Parameters
| Parameter | Type |
|---|---|
bearer | string |
Returns
Provider<TokenSource, never, never> & object