@schemavaults/auth-client-sdk 0.17.3 → 0.18.7
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/README.md +35 -0
- package/dist/auth-client.d.ts +10 -2
- package/dist/auth-client.js +27 -4
- package/dist/auth-client.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/lib/exchange-auth-tokens.d.ts +16 -6
- package/dist/lib/exchange-auth-tokens.js +119 -97
- package/dist/lib/exchange-auth-tokens.js.map +1 -1
- package/dist/lib/handle-successful-authentication.d.ts +20 -6
- package/dist/lib/handle-successful-authentication.js +170 -131
- package/dist/lib/handle-successful-authentication.js.map +1 -1
- package/dist/lib/handle-successful-exchange-auth-tokens-response.d.ts +11 -7
- package/dist/lib/handle-successful-exchange-auth-tokens-response.js +19 -28
- package/dist/lib/handle-successful-exchange-auth-tokens-response.js.map +1 -1
- package/dist/lib/oidc/index.d.ts +9 -0
- package/dist/lib/oidc/index.js +7 -0
- package/dist/lib/oidc/index.js.map +1 -0
- package/dist/lib/oidc/is-insecure-transport-allowed.d.ts +8 -0
- package/dist/lib/oidc/is-insecure-transport-allowed.js +14 -0
- package/dist/lib/oidc/is-insecure-transport-allowed.js.map +1 -0
- package/dist/lib/oidc/normalize-oidc-issuer.d.ts +8 -0
- package/dist/lib/oidc/normalize-oidc-issuer.js +19 -0
- package/dist/lib/oidc/normalize-oidc-issuer.js.map +1 -0
- package/dist/lib/oidc/oidc-client-configuration.d.ts +43 -0
- package/dist/lib/oidc/oidc-client-configuration.js +68 -0
- package/dist/lib/oidc/oidc-client-configuration.js.map +1 -0
- package/dist/lib/oidc/oidc-token-error.d.ts +16 -0
- package/dist/lib/oidc/oidc-token-error.js +54 -0
- package/dist/lib/oidc/oidc-token-error.js.map +1 -0
- package/dist/lib/oidc/token-endpoint-response-to-tokens-record.d.ts +42 -0
- package/dist/lib/oidc/token-endpoint-response-to-tokens-record.js +72 -0
- package/dist/lib/oidc/token-endpoint-response-to-tokens-record.js.map +1 -0
- package/dist/lib/oidc/uid-from-oidc-sub-claim.d.ts +13 -0
- package/dist/lib/oidc/uid-from-oidc-sub-claim.js +32 -0
- package/dist/lib/oidc/uid-from-oidc-sub-claim.js.map +1 -0
- package/dist/lib/send-authenticate-request.js +7 -4
- package/dist/lib/send-authenticate-request.js.map +1 -1
- package/dist/types/ISchemaVaultsAuthClient.d.ts +2 -2
- package/dist/types/ISendAuthenticateRequestOptions.d.ts +1 -1
- package/package.json +4 -3
|
@@ -1,48 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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(
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
86
|
-
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
const classified = classifyOidcTokenError(e);
|
|
108
|
+
if (debug) {
|
|
109
|
+
console.error("[exchangeAuthTokens] Refresh grant failed: ", e);
|
|
87
110
|
}
|
|
88
|
-
if (
|
|
89
|
-
console.error(
|
|
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
|
-
|
|
92
|
-
//
|
|
93
|
-
|
|
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
|
|
118
|
+
throw new Error(`Token exchange failed: ${classified.message}`, {
|
|
119
|
+
cause: e,
|
|
120
|
+
});
|
|
102
121
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
return await handleSuccessfulExchangeAuthTokensResponse(tokens_response_data);
|
|
155
|
+
return await handleSuccessfulExchangeAuthTokensResponse(merged);
|
|
130
156
|
}
|
|
131
157
|
catch (e) {
|
|
132
158
|
if (debug) {
|
|
133
|
-
console.
|
|
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":"
|
|
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
|
|
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
|
|
22
|
-
*
|
|
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
|
|
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;
|