@hyper.authio/server 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -34,8 +34,9 @@ interface AuthioUserClaimSettings {
34
34
  groupClaims?: readonly string[];
35
35
  }
36
36
  /**
37
- * The caller of an API, read from a validated access token or an introspection answer: identity, every form of
38
- * permission Authio issues, and the raw claims for anything else.
37
+ * The caller of an API, read from a validated access token, an introspection answer, or both (the token's claims and
38
+ * those of the answer the token does not carry, as `activeCheck` reads it): identity, every form of permission Authio
39
+ * issues, and the raw claims for anything else.
39
40
  */
40
41
  declare class AuthioUser {
41
42
  /** `sub`: the person's id, or the credential's for a machine caller. */
@@ -121,7 +122,10 @@ declare class AuthioUser {
121
122
  readonly credentialType: string | undefined;
122
123
  /** `credential_id`. */
123
124
  readonly credentialId: string | undefined;
124
- /** Every claim, as the token or the introspection answer carried it. */
125
+ /**
126
+ * Every claim, as the token or the introspection answer carried it (with `activeCheck`, the token's, plus the
127
+ * answer's the token does not carry).
128
+ */
125
129
  readonly claims: Readonly<Record<string, unknown>>;
126
130
  /** The access token the user was read from. Not enumerable, so it stays out of logs and JSON. */
127
131
  readonly token: string | undefined;
@@ -339,10 +343,15 @@ declare function toProblemDetails(error: AuthioBearerError | AuthioForbiddenErro
339
343
  /**
340
344
  * Whether and how Authio's introspection endpoint takes part in validating a token.
341
345
  *
342
- * - `none`: the JWT is validated locally (signature, issuer, audience, lifetime). Fastest; a revoked token stays
343
- * valid until it expires.
344
- * - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`).
345
- * - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key.
346
+ * - `none`: the JWT is validated locally (signature, issuer, audience, lifetime) and the caller is read from it alone.
347
+ * Fastest; a revoked token stays valid until it expires. A lightweight access token carries no roles, permissions,
348
+ * plan, profile or email, so it needs one of the modes below.
349
+ * - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`). The caller is read
350
+ * from the token, and the introspection answer adds the claims the token does not carry: the answer has every claim
351
+ * of the complete token, so a lightweight access token's roles and permissions are read too. A claim the token
352
+ * carries keeps the token's value, which its signature vouches for, whatever the answer says.
353
+ * - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key. The
354
+ * caller is read from the answer.
346
355
  */
347
356
  type AuthioIntrospectionMode = "none" | "activeCheck" | "introspectionOnly";
348
357
  /**
package/dist/index.d.ts CHANGED
@@ -34,8 +34,9 @@ interface AuthioUserClaimSettings {
34
34
  groupClaims?: readonly string[];
35
35
  }
36
36
  /**
37
- * The caller of an API, read from a validated access token or an introspection answer: identity, every form of
38
- * permission Authio issues, and the raw claims for anything else.
37
+ * The caller of an API, read from a validated access token, an introspection answer, or both (the token's claims and
38
+ * those of the answer the token does not carry, as `activeCheck` reads it): identity, every form of permission Authio
39
+ * issues, and the raw claims for anything else.
39
40
  */
40
41
  declare class AuthioUser {
41
42
  /** `sub`: the person's id, or the credential's for a machine caller. */
@@ -121,7 +122,10 @@ declare class AuthioUser {
121
122
  readonly credentialType: string | undefined;
122
123
  /** `credential_id`. */
123
124
  readonly credentialId: string | undefined;
124
- /** Every claim, as the token or the introspection answer carried it. */
125
+ /**
126
+ * Every claim, as the token or the introspection answer carried it (with `activeCheck`, the token's, plus the
127
+ * answer's the token does not carry).
128
+ */
125
129
  readonly claims: Readonly<Record<string, unknown>>;
126
130
  /** The access token the user was read from. Not enumerable, so it stays out of logs and JSON. */
127
131
  readonly token: string | undefined;
@@ -339,10 +343,15 @@ declare function toProblemDetails(error: AuthioBearerError | AuthioForbiddenErro
339
343
  /**
340
344
  * Whether and how Authio's introspection endpoint takes part in validating a token.
341
345
  *
342
- * - `none`: the JWT is validated locally (signature, issuer, audience, lifetime). Fastest; a revoked token stays
343
- * valid until it expires.
344
- * - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`).
345
- * - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key.
346
+ * - `none`: the JWT is validated locally (signature, issuer, audience, lifetime) and the caller is read from it alone.
347
+ * Fastest; a revoked token stays valid until it expires. A lightweight access token carries no roles, permissions,
348
+ * plan, profile or email, so it needs one of the modes below.
349
+ * - `activeCheck`: validated locally, then confirmed active by introspection (cached per `jti`). The caller is read
350
+ * from the token, and the introspection answer adds the claims the token does not carry: the answer has every claim
351
+ * of the complete token, so a lightweight access token's roles and permissions are read too. A claim the token
352
+ * carries keeps the token's value, which its signature vouches for, whatever the answer says.
353
+ * - `introspectionOnly`: introspection alone, for opaque (reference) tokens, or encrypted ones without the key. The
354
+ * caller is read from the answer.
346
355
  */
347
356
  type AuthioIntrospectionMode = "none" | "activeCheck" | "introspectionOnly";
348
357
  /**
package/dist/index.js CHANGED
@@ -87,7 +87,10 @@ var AuthioUser = class _AuthioUser {
87
87
  credentialType;
88
88
  /** `credential_id`. */
89
89
  credentialId;
90
- /** Every claim, as the token or the introspection answer carried it. */
90
+ /**
91
+ * Every claim, as the token or the introspection answer carried it (with `activeCheck`, the token's, plus the
92
+ * answer's the token does not carry).
93
+ */
91
94
  claims;
92
95
  flatRoles;
93
96
  /**
@@ -655,8 +658,9 @@ function createAuthioVerifier(options) {
655
658
  const type = typeof payload.typ === "string" ? payload.typ : void 0;
656
659
  if (rejectNonAccessTokens && type !== void 0 && type.toLowerCase() !== "bearer")
657
660
  throw new AuthioBearerError(`Only access tokens are accepted; this token's typ is '${type}'.`, { reason: "not_access_token" });
658
- if (introspection === "activeCheck") await confirmActive(token, payload, signal);
659
- return new AuthioUser(payload, claimSettings, token);
661
+ if (introspection !== "activeCheck") return new AuthioUser(payload, claimSettings, token);
662
+ const answer = await confirmActive(token, payload, signal);
663
+ return new AuthioUser({ ...claimsOfIntrospection(answer), ...payload }, claimSettings, token);
660
664
  };
661
665
  const confirmActive = async (token, payload, signal) => {
662
666
  const key = payload.jti ? `jti:${payload.jti}` : await keyForToken(token);
@@ -668,6 +672,7 @@ function createAuthioVerifier(options) {
668
672
  throw new AuthioBearerError(AuthioBearerErrorDescriptions.Unconfirmed, { cause: error, reason: "unconfirmed" });
669
673
  }
670
674
  if (!result) throw new AuthioBearerError(AuthioBearerErrorDescriptions.Inactive, { reason: "inactive" });
675
+ return result;
671
676
  };
672
677
  const verifyByIntrospection = async (token, signal) => {
673
678
  let result;