@schemavaults/auth-client-sdk 0.17.2 → 0.18.6

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.
Files changed (44) hide show
  1. package/README.md +35 -0
  2. package/dist/auth-client.d.ts +9 -1
  3. package/dist/auth-client.js +22 -3
  4. package/dist/auth-client.js.map +1 -1
  5. package/dist/generated/version.d.ts +1 -1
  6. package/dist/generated/version.js +1 -1
  7. package/dist/lib/acquire-access-token.js +1 -1
  8. package/dist/lib/acquire-access-token.js.map +1 -1
  9. package/dist/lib/credentials-schema/credentials-schema.d.ts +5 -26
  10. package/dist/lib/exchange-auth-tokens.d.ts +16 -6
  11. package/dist/lib/exchange-auth-tokens.js +119 -97
  12. package/dist/lib/exchange-auth-tokens.js.map +1 -1
  13. package/dist/lib/handle-successful-authentication.d.ts +20 -6
  14. package/dist/lib/handle-successful-authentication.js +170 -131
  15. package/dist/lib/handle-successful-authentication.js.map +1 -1
  16. package/dist/lib/handle-successful-exchange-auth-tokens-response.d.ts +11 -7
  17. package/dist/lib/handle-successful-exchange-auth-tokens-response.js +19 -28
  18. package/dist/lib/handle-successful-exchange-auth-tokens-response.js.map +1 -1
  19. package/dist/lib/mfa/regenerate-recovery-codes.js +1 -1
  20. package/dist/lib/mfa/regenerate-recovery-codes.js.map +1 -1
  21. package/dist/lib/oidc/index.d.ts +9 -0
  22. package/dist/lib/oidc/index.js +7 -0
  23. package/dist/lib/oidc/index.js.map +1 -0
  24. package/dist/lib/oidc/is-insecure-transport-allowed.d.ts +8 -0
  25. package/dist/lib/oidc/is-insecure-transport-allowed.js +14 -0
  26. package/dist/lib/oidc/is-insecure-transport-allowed.js.map +1 -0
  27. package/dist/lib/oidc/normalize-oidc-issuer.d.ts +8 -0
  28. package/dist/lib/oidc/normalize-oidc-issuer.js +19 -0
  29. package/dist/lib/oidc/normalize-oidc-issuer.js.map +1 -0
  30. package/dist/lib/oidc/oidc-client-configuration.d.ts +43 -0
  31. package/dist/lib/oidc/oidc-client-configuration.js +68 -0
  32. package/dist/lib/oidc/oidc-client-configuration.js.map +1 -0
  33. package/dist/lib/oidc/oidc-token-error.d.ts +16 -0
  34. package/dist/lib/oidc/oidc-token-error.js +54 -0
  35. package/dist/lib/oidc/oidc-token-error.js.map +1 -0
  36. package/dist/lib/oidc/token-endpoint-response-to-tokens-record.d.ts +42 -0
  37. package/dist/lib/oidc/token-endpoint-response-to-tokens-record.js +72 -0
  38. package/dist/lib/oidc/token-endpoint-response-to-tokens-record.js.map +1 -0
  39. package/dist/lib/oidc/uid-from-oidc-sub-claim.d.ts +13 -0
  40. package/dist/lib/oidc/uid-from-oidc-sub-claim.js +32 -0
  41. package/dist/lib/oidc/uid-from-oidc-sub-claim.js.map +1 -0
  42. package/dist/lib/send-authenticate-request.js +1 -1
  43. package/dist/types/ISchemaVaultsAuthClient.d.ts +1 -1
  44. package/package.json +5 -4
@@ -1,48 +1,36 @@
1
- import { createRefreshTokenPOSTBodySchema, createRequestTokensResultSchema, } from "@schemavaults/auth-common";
2
- import { z } from "zod";
3
- export async function exchangeAuthTokens({ refreshToken, audience, debug, environment, auth_server_uri, auth_server_app_id, client_app_id, adapter, handleSuccessfulExchangeAuthTokensResponse, logout, }) {
1
+ // exchange-auth-tokens.ts
2
+ //
3
+ // Redeems a refresh token at the auth server's standard OIDC token
4
+ // endpoint (/api/oidc/token, grant_type=refresh_token) via
5
+ // `openid-client`. The endpoint mints ONE access token per request
6
+ // (RFC 8707 `resource`), so a multi-audience exchange is a sequence of
7
+ // refresh grants — each rotating the refresh token, so each subsequent
8
+ // grant presents the token the previous one returned.
9
+ import * as oidc from "openid-client";
10
+ import { OIDC_USERINFO_AUDIENCE_ID, } from "@schemavaults/app-definitions";
11
+ import { OIDC_TOKEN_REFRESH_TOKEN_DELIVERY_PARAM, OIDC_TOKEN_RESOURCE_PARAM, } from "@schemavaults/auth-common";
12
+ import { classifyOidcTokenError, createOidcClientConfiguration, normalizeOidcIssuer, tokenEndpointResponseToTokensRecord, } from "./oidc";
13
+ function normalizeAudiences(audience) {
14
+ if (Array.isArray(audience)) {
15
+ return audience.filter((a) => typeof a === "string" && a.length > 0);
16
+ }
17
+ return typeof audience === "string" && audience.length > 0 ? [audience] : [];
18
+ }
19
+ export async function exchangeAuthTokens({ refreshToken, audience, debug, environment, auth_server_uri, client_app_id, adapter, fetchUserData, handleSuccessfulExchangeAuthTokensResponse, logout, }) {
4
20
  if (debug) {
5
21
  console.log("[SchemaVaultsAuthClient] Attempting to send request to exchange refresh token for access token...");
6
22
  }
7
- const exchange_refresh_token_endpoint = new URL(`/api/auth/token/refresh_token/${client_app_id}`, auth_server_uri);
8
- // An empty audience list is a rotation-only request: the server always
9
- // rotates the refresh token, so the exchange still yields a fresh
10
- // refresh token (and updated user data) even when no access tokens are
11
- // requested.
12
- const refreshTokenPOSTBodySchema = createRefreshTokenPOSTBodySchema(z, environment, { auth_server_url: auth_server_uri, auth_server_app_id });
13
- // Exchange the authorization code for an access token
14
- let request_body;
15
- try {
16
- const parsed = await refreshTokenPOSTBodySchema.safeParseAsync({
17
- grant_type: "refresh_token",
18
- client_app_id,
19
- audience: audience,
20
- });
21
- if (!parsed.success) {
22
- console.error(parsed.error);
23
- throw new Error("Failed to parse tokens from exchange auth tokens POST request!");
24
- }
25
- request_body = parsed.data;
26
- }
27
- catch (e) {
28
- if (debug) {
29
- console.error("Failed to prepare request body for authorization grant request: ", e);
30
- }
31
- throw new Error("Failed to prepare request body for authorization grant request");
32
- }
33
- const exchangeAuthTokensReqHeaders = {
34
- "Content-Type": "application/json",
35
- };
36
23
  if (!refreshToken) {
37
24
  throw new Error("Did not receive a refresh token to exchange for access token!");
38
25
  }
26
+ // ---- Which refresh token, and how is it presented? -----------------
27
+ let useHttpOnlyCookie;
39
28
  if (typeof refreshToken === "object" && refreshToken.type === "refresh") {
40
29
  if (typeof refreshToken.token !== "string" ||
41
30
  refreshToken.token.length === 0) {
42
31
  throw new TypeError("Expected 'token' to be a non-empty string!");
43
32
  }
44
- exchangeAuthTokensReqHeaders["Authorization"] =
45
- `Bearer ${refreshToken.token}`;
33
+ useHttpOnlyCookie = false;
46
34
  }
47
35
  else if (typeof refreshToken === "string" &&
48
36
  refreshToken === "AS_HTTP_ONLY_COOKIE") {
@@ -52,91 +40,125 @@ export async function exchangeAuthTokens({ refreshToken, audience, debug, enviro
52
40
  if (!adapter.doesSupportHttpOnlyRefreshToken()) {
53
41
  throw new Error("Adapter does not support HTTP-only refresh tokens! Adapter method 'doesSupportHttpOnlyRefreshToken' returned falsy result!");
54
42
  }
43
+ useHttpOnlyCookie = true;
55
44
  }
56
45
  else {
57
46
  throw new Error("Did not receive a valid refresh token (or valid method of acquiring refresh token)");
58
47
  }
59
- if (debug) {
60
- console.log("[SchemaVaultsAuthClient::exchangeAuthTokens()] " +
61
- `Sending POST request to "${exchange_refresh_token_endpoint.toString()}" with body & headers:`, request_body, exchangeAuthTokensReqHeaders);
48
+ // ---- Resolve the user id for the token record ----------------------
49
+ // The refresh grant response carries no id_token (OIDC Core §12.2), so
50
+ // the subject comes from the cached user data — or, on a cold cache,
51
+ // from the auth server's whoami endpoint (authenticated with the
52
+ // refresh token we are about to rotate).
53
+ let uid = adapter.getUserData()?.uid;
54
+ if (!uid) {
55
+ const user = await fetchUserData();
56
+ if (!user) {
57
+ await logout();
58
+ throw new Error("Session expired: the auth server no longer recognizes this session");
59
+ }
60
+ uid = user.uid;
62
61
  }
63
- let tokens_response_data;
64
- try {
62
+ // ---- The grant(s) --------------------------------------------------
63
+ const config = createOidcClientConfiguration({
64
+ auth_server_url: auth_server_uri,
65
+ client_app_id,
66
+ environment,
67
+ adapter,
68
+ });
69
+ const issuer = normalizeOidcIssuer(auth_server_uri);
70
+ // An empty audience list is a rotation-only request: one grant with no
71
+ // `resource` (its access token is for the reserved userinfo audience).
72
+ const audiences = normalizeAudiences(audience);
73
+ const grants = audiences.length > 0 ? audiences : [null];
74
+ const access = {};
75
+ let current = refreshToken;
76
+ let last_record;
77
+ for (const resource of grants) {
78
+ const parameters = new URLSearchParams();
79
+ if (resource) {
80
+ parameters.set(OIDC_TOKEN_RESOURCE_PARAM, resource);
81
+ }
82
+ if (useHttpOnlyCookie) {
83
+ parameters.set(OIDC_TOKEN_REFRESH_TOKEN_DELIVERY_PARAM, "http_only_cookie");
84
+ }
65
85
  if (debug) {
66
- console.log(`POST => ${exchange_refresh_token_endpoint}`);
86
+ console.log("[SchemaVaultsAuthClient::exchangeAuthTokens()] " +
87
+ `Sending refresh grant to "${config.serverMetadata().token_endpoint}" with parameters:`, Object.fromEntries(parameters.entries()), useHttpOnlyCookie
88
+ ? "(refresh token presented via HTTP-only cookie)"
89
+ : "(refresh token presented inline)");
67
90
  }
68
- const response = await adapter.fetch(exchange_refresh_token_endpoint.toString(), {
69
- body: JSON.stringify(request_body),
70
- method: "POST",
71
- headers: exchangeAuthTokensReqHeaders,
72
- credentials: "include",
73
- });
74
- if (!response || typeof response !== "object" || response.status !== 200) {
75
- let serverMessage = "unknown error";
76
- try {
77
- const errorBody = await response.json();
78
- if (errorBody &&
79
- typeof errorBody === "object" &&
80
- "message" in errorBody &&
81
- typeof errorBody.message === "string") {
82
- serverMessage = errorBody.message;
91
+ let response;
92
+ try {
93
+ if (useHttpOnlyCookie) {
94
+ // The refresh token lives in the auth server's HTTP-only cookie,
95
+ // which the adapter's fetch sends with the request; the form
96
+ // therefore carries no `refresh_token` parameter.
97
+ response = await oidc.genericGrantRequest(config, "refresh_token", parameters);
98
+ }
99
+ else {
100
+ if (typeof current !== "object") {
101
+ throw new Error("Refresh token rotation switched to cookie delivery mid-exchange");
83
102
  }
103
+ response = await oidc.refreshTokenGrant(config, current.token, parameters);
84
104
  }
85
- catch {
86
- // Response body may not be valid JSON
105
+ }
106
+ catch (e) {
107
+ const classified = classifyOidcTokenError(e);
108
+ if (debug) {
109
+ console.error("[exchangeAuthTokens] Refresh grant failed: ", e);
87
110
  }
88
- if (response.status === 403 || response.status === 401) {
89
- console.error(`${response.status} error response from exchange token attempt, client is not logged in! Server: ${serverMessage}`);
111
+ if (classified.session_lost) {
112
+ console.error(`Refresh grant rejected by the auth server (${classified.message}); client is no longer logged in.`);
90
113
  await logout();
91
- const sessionExpiredMsg = `Session expired (HTTP ${response.status}): ${serverMessage}`;
92
- // Guard: downstream error handlers (acquire-access-token.ts, etc.) detect session
93
- // expiry by checking if the error message includes "expired". If the message format
94
- // is ever refactored and that keyword is accidentally removed, the entire expired-session
95
- // detection chain breaks silently. This check ensures the contract is always upheld.
96
- if (!sessionExpiredMsg.toLowerCase().includes("expired")) {
97
- throw new Error("Session expired");
98
- }
99
- throw new Error(sessionExpiredMsg);
114
+ // Downstream handlers (acquire-access-token.ts, etc.) detect an
115
+ // unrecoverable session by the "expired" keyword in the message.
116
+ throw new Error("Refresh token has expired!", { cause: e });
100
117
  }
101
- throw new Error(`Token exchange failed (HTTP ${response.status}): ${serverMessage}`);
118
+ throw new Error(`Token exchange failed: ${classified.message}`, {
119
+ cause: e,
120
+ });
102
121
  }
103
- const parsed_tokens_result = await createRequestTokensResultSchema(z, environment, { auth_server_url: auth_server_uri, auth_server_app_id }).safeParseAsync(await response.json());
104
- if (!parsed_tokens_result.success) {
105
- console.error("Failed to parse tokens response from server: ", parsed_tokens_result.error);
106
- throw new Error("Failed to parse tokens response from server!");
122
+ let record;
123
+ try {
124
+ record = tokenEndpointResponseToTokensRecord({
125
+ response,
126
+ audience: resource ?? OIDC_USERINFO_AUDIENCE_ID,
127
+ uid,
128
+ auth_server_url: issuer,
129
+ });
107
130
  }
108
- tokens_response_data = parsed_tokens_result.data;
109
- }
110
- catch (e) {
111
- if (debug) {
112
- console.error("[exchangeAuthTokens] FETCH FAILED: ", e);
131
+ catch (e) {
132
+ console.error("Failed to parse tokens response from server: ", e);
133
+ throw new Error("Failed to parse tokens response from server!", {
134
+ cause: e,
135
+ });
113
136
  }
114
- if (e instanceof Error) {
115
- const eMsg = e.message.toLowerCase();
116
- if (eMsg.includes("expired") ||
117
- eMsg.includes("jwtexpired") ||
118
- eMsg.includes("err_jwt_expired")) {
119
- console.error("Refresh token appears to have expired!");
120
- throw new Error("Refresh token has expired!");
121
- }
137
+ Object.assign(access, record.access ?? {});
138
+ if (typeof record.refresh === "object") {
139
+ // Rotation: the next grant must present the replacement token.
140
+ current = record.refresh;
122
141
  }
123
- throw e instanceof Error
124
- ? e
125
- : new Error("Failed to exchange refresh token for access token");
142
+ last_record = record;
126
143
  }
144
+ if (!last_record) {
145
+ throw new Error("No refresh grant was performed");
146
+ }
147
+ const merged = {
148
+ access,
149
+ refresh: last_record.refresh,
150
+ ...(typeof last_record.refresh_token_expiry === "number"
151
+ ? { refresh_token_expiry: last_record.refresh_token_expiry }
152
+ : {}),
153
+ };
127
154
  try {
128
- // Parse tokens from response JSON body
129
- return await handleSuccessfulExchangeAuthTokensResponse(tokens_response_data);
155
+ return await handleSuccessfulExchangeAuthTokensResponse(merged);
130
156
  }
131
157
  catch (e) {
132
158
  if (debug) {
133
- console.log("typeof e === ", typeof e);
134
- if (e instanceof Error) {
135
- console.error("Parse tokens error message: ", e.message);
136
- }
137
- console.error("Failed to parse authentication tokens from exchange tokens POST request: ", e);
159
+ console.error("Failed to store authentication tokens from refresh grant: ", e);
138
160
  }
139
- throw new Error("Failed to parse authentication tokens from exchange tokens POST request!");
161
+ throw new Error("Failed to parse authentication tokens from exchange tokens POST request!", { cause: e });
140
162
  }
141
163
  }
142
164
  export default exchangeAuthTokens;
@@ -1 +1 @@
1
- {"version":3,"file":"exchange-auth-tokens.js","sourceRoot":"","sources":["../../src/lib/exchange-auth-tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exchange-auth-tokens.js","sourceRoot":"","sources":["../../src/lib/exchange-auth-tokens.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
- import { type AccessToken, type RefreshToken, type UserData } from "@schemavaults/auth-common";
2
- import type { ApiServerId, AppId, SchemaVaultsAppEnvironment } from "@schemavaults/app-definitions";
1
+ import { type AccessToken, type RefreshToken, type SuccessfullyGeneratedTokensRecord, type UserData } from "@schemavaults/auth-common";
2
+ import { type ApiServerId, type AppId, type SchemaVaultsAppEnvironment } from "@schemavaults/app-definitions";
3
3
  import type { ISchemaVaultsAuthClientAdapter } from "../types/ISchemaVaultsAuthClientAdapter";
4
4
  export interface IHandleSuccessfulAuthenticationOpts {
5
5
  authorization_code: string;
6
6
  challenge_time: number;
7
7
  code_verifier?: string;
8
8
  received_state: string | null | undefined;
9
+ received_iss: string | null | undefined;
9
10
  expected_nonce: string | null | undefined;
10
11
  redirect_uri: string | null;
11
12
  loadCodeVerifier: (challenge_time: number) => string | null;
@@ -18,15 +19,28 @@ export interface IHandleSuccessfulAuthenticationOpts {
18
19
  auth_server_url: string;
19
20
  /**
20
21
  * The auth server deployment's own app id (white-label deployments use a
21
- * custom value). Injected into audience schema validation because browser
22
- * bundles can't resolve the SCHEMAVAULTS_AUTH_SERVER_APP_ID env var.
22
+ * custom value; the client resolves it from its constructor option or
23
+ * the platform default). The id_token `sub` claim is namespaced by it.
23
24
  */
24
- auth_server_app_id?: AppId;
25
+ auth_server_app_id: AppId;
25
26
  defaultTokenAudiences: string | string[];
26
27
  storeRefreshToken: (refreshToken: RefreshToken) => void;
27
28
  storeUserData: (userData: UserData) => void;
28
29
  storeMultipleAccessTokens: (accessTokens: Record<ApiServerId, AccessToken | "AS_HTTP_ONLY_COOKIE">) => void;
30
+ /**
31
+ * Redeems the (just stored) refresh token for access tokens of further
32
+ * audiences. The token endpoint issues one access token per request,
33
+ * so default audiences beyond the first are acquired here through
34
+ * refresh grants right after the code grant.
35
+ */
36
+ exchangeAuthTokens: (refreshToken: RefreshToken | "AS_HTTP_ONLY_COOKIE", audience: string | string[]) => Promise<SuccessfullyGeneratedTokensRecord>;
37
+ /**
38
+ * Loads the signed-in user's data from the auth server (whoami) using
39
+ * the stored refresh token. The OIDC token response carries identity
40
+ * claims only; the platform's full `UserData` comes from here.
41
+ */
42
+ fetchUserData: () => Promise<UserData | null>;
29
43
  triggerAuthStateChanged: () => void;
30
44
  }
31
- export declare function handleSuccessfulAuthentication({ authorization_code, challenge_time, code_verifier, received_state, expected_nonce, redirect_uri, loadCodeVerifier, loadOAuth2State, loadOidcNonce, debug, environment, adapter, auth_server_url, auth_server_app_id, client_app_id, defaultTokenAudiences, storeRefreshToken, storeUserData, storeMultipleAccessTokens, triggerAuthStateChanged, }: IHandleSuccessfulAuthenticationOpts): Promise<void>;
45
+ export declare function handleSuccessfulAuthentication({ authorization_code, challenge_time, code_verifier, received_state, received_iss, expected_nonce, redirect_uri, loadCodeVerifier, loadOAuth2State, loadOidcNonce, debug, environment, adapter, auth_server_url, auth_server_app_id, client_app_id, defaultTokenAudiences, storeRefreshToken, storeUserData, storeMultipleAccessTokens, exchangeAuthTokens, fetchUserData, triggerAuthStateChanged, }: IHandleSuccessfulAuthenticationOpts): Promise<void>;
32
46
  export default handleSuccessfulAuthentication;