@elixpo/accounts 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## 1.0.1
4
+
5
+ - Add typed OAuth/OIDC discovery.
6
+ - Add S256 PKCE, state, nonce, and authorization callback helpers.
7
+ - Add authorization-code exchange, refresh rotation, and revocation.
8
+ - Add EdDSA JWKS-based access and ID token verification.
9
+ - Add sanitized typed errors for protocol, OAuth, network, and verification failures.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # `@elixpo/accounts`
2
+
3
+ Edge-safe OAuth 2.0 and OpenID Connect primitives for Elixpo Accounts.
4
+
5
+ The canonical SDK contract and release policy live in the
6
+ [integration reference](https://github.com/elixpo/accounts.elixpo/blob/main/docs/README.md).
7
+
8
+ Next.js and React adapters are tracked separately and are not exported yet.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @elixpo/accounts
14
+ ```
15
+
16
+ ## Start authorization
17
+
18
+ ```ts
19
+ import { createAccountsClient } from "@elixpo/accounts";
20
+
21
+ const accounts = createAccountsClient({
22
+ issuer: "https://accounts.elixpo.com",
23
+ clientId: process.env.ELIXPO_CLIENT_ID!,
24
+ redirectUri: "https://example.com/auth/callback",
25
+ audience: "example.com",
26
+ });
27
+
28
+ const { url, transaction } = await accounts.createAuthorizationRequest();
29
+ // Store transaction in an encrypted, httpOnly, same-site session, then redirect.
30
+ ```
31
+
32
+ ## Complete authorization
33
+
34
+ ```ts
35
+ import { parseAuthorizationCallback } from "@elixpo/accounts";
36
+
37
+ const { code } = parseAuthorizationCallback(
38
+ request.url,
39
+ transaction.state,
40
+ );
41
+ const tokens = await accounts.exchangeAuthorizationCode({
42
+ code,
43
+ codeVerifier: transaction.codeVerifier,
44
+ });
45
+ await accounts.verifyIdToken(tokens.idToken!, transaction.nonce);
46
+ ```
47
+
48
+ ## Refresh and revoke
49
+
50
+ ```ts
51
+ const rotated = await accounts.refresh(tokens.refreshToken);
52
+ // Atomically replace the stored token with rotated.refreshToken.
53
+ await accounts.revoke(rotated.refreshToken);
54
+ ```
55
+
56
+ ## Configuration boundaries
57
+
58
+ - Browser-safe: issuer, client ID, redirect URI, audience.
59
+ - Server-only: confidential client secret, refresh tokens, authorization
60
+ transactions, and all returned tokens.
61
+ - Hosted Elixpo pages collect passwords, OTPs, passkeys, and MFA responses.
62
+ Third-party applications must not collect Elixpo credentials.
63
+
64
+ The SDK is optional. Generic OAuth/OIDC clients can use
65
+ `/.well-known/oauth-authorization-server` and `/.well-known/openid-configuration`.
@@ -0,0 +1,12 @@
1
+ import type { AccountsConfiguration, AuthorizationServerMetadata, AuthorizationTransaction } from "./types.js";
2
+ export declare function parseAuthorizationCallback(callbackUrl: string | URL, expectedState: string): {
3
+ code: string;
4
+ };
5
+ export declare function createAuthorizationRequest(metadata: AuthorizationServerMetadata, configuration: Pick<AccountsConfiguration, "clientId" | "redirectUri" | "audience">, options?: {
6
+ scopes?: string[];
7
+ prompt?: "consent" | "login" | "select_account";
8
+ }): Promise<{
9
+ url: URL;
10
+ transaction: AuthorizationTransaction;
11
+ }>;
12
+ //# sourceMappingURL=authorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../../src/core/authorization.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACR,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,EAC3B,MAAM,YAAY,CAAC;AAgCpB,wBAAgB,0BAA0B,CACtC,WAAW,EAAE,MAAM,GAAG,GAAG,EACzB,aAAa,EAAE,MAAM,GACtB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAsBlB;AAkBD,wBAAsB,0BAA0B,CAC5C,QAAQ,EAAE,2BAA2B,EACrC,aAAa,EAAE,IAAI,CACf,qBAAqB,EACrB,UAAU,GAAG,aAAa,GAAG,UAAU,CAC1C,EACD,OAAO,GAAE;IACL,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,gBAAgB,CAAC;CAC9C,GACP,OAAO,CAAC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,WAAW,EAAE,wBAAwB,CAAA;CAAE,CAAC,CAgC9D"}
@@ -0,0 +1,75 @@
1
+ import { assertState, generateNonce, generatePkce, generateState, } from "./crypto.js";
2
+ import { AccountsError } from "./errors.js";
3
+ function validateRedirectUri(value) {
4
+ let redirect;
5
+ try {
6
+ redirect = new URL(value);
7
+ }
8
+ catch {
9
+ throw new AccountsError("configuration_error", "redirectUri must be an absolute URL");
10
+ }
11
+ const local = redirect.hostname === "localhost" || redirect.hostname === "127.0.0.1";
12
+ if (redirect.protocol !== "https:" &&
13
+ !(local && redirect.protocol === "http:")) {
14
+ throw new AccountsError("configuration_error", "redirectUri must use HTTPS outside localhost");
15
+ }
16
+ if (redirect.username || redirect.password || redirect.hash) {
17
+ throw new AccountsError("configuration_error", "redirectUri cannot contain credentials or a fragment");
18
+ }
19
+ return redirect.toString();
20
+ }
21
+ export function parseAuthorizationCallback(callbackUrl, expectedState) {
22
+ const url = callbackUrl instanceof URL ? callbackUrl : new URL(callbackUrl);
23
+ const returnedState = url.searchParams.get("state") || "";
24
+ assertState(expectedState, returnedState);
25
+ const error = url.searchParams.get("error");
26
+ if (error) {
27
+ throw new AccountsError("oauth_error", "Authorization request was rejected", {
28
+ oauthCode: error,
29
+ });
30
+ }
31
+ const code = url.searchParams.get("code");
32
+ if (!code) {
33
+ throw new AccountsError("protocol_error", "Authorization callback did not include a code");
34
+ }
35
+ return { code };
36
+ }
37
+ function validateScopes(scopes) {
38
+ const normalized = [
39
+ ...new Set(scopes.map((scope) => scope.trim()).filter(Boolean)),
40
+ ];
41
+ if (normalized.length === 0 ||
42
+ normalized.some((scope) => /\s/.test(scope))) {
43
+ throw new AccountsError("configuration_error", "At least one valid OAuth scope is required");
44
+ }
45
+ return normalized;
46
+ }
47
+ export async function createAuthorizationRequest(metadata, configuration, options = {}) {
48
+ if (!configuration.clientId.trim()) {
49
+ throw new AccountsError("configuration_error", "clientId is required");
50
+ }
51
+ const scopes = validateScopes(options.scopes ?? ["openid", "profile", "email"]);
52
+ const [{ codeVerifier, codeChallenge }, state, nonce] = await Promise.all([
53
+ generatePkce(),
54
+ Promise.resolve(generateState()),
55
+ Promise.resolve(generateNonce()),
56
+ ]);
57
+ const url = new URL(metadata.authorization_endpoint);
58
+ url.searchParams.set("response_type", "code");
59
+ url.searchParams.set("client_id", configuration.clientId);
60
+ url.searchParams.set("redirect_uri", validateRedirectUri(configuration.redirectUri));
61
+ url.searchParams.set("scope", scopes.join(" "));
62
+ url.searchParams.set("state", state);
63
+ url.searchParams.set("nonce", nonce);
64
+ url.searchParams.set("code_challenge", codeChallenge);
65
+ url.searchParams.set("code_challenge_method", "S256");
66
+ if (configuration.audience)
67
+ url.searchParams.set("audience", configuration.audience);
68
+ if (options.prompt)
69
+ url.searchParams.set("prompt", options.prompt);
70
+ return {
71
+ url,
72
+ transaction: { state, nonce, codeVerifier, createdAt: Date.now() },
73
+ };
74
+ }
75
+ //# sourceMappingURL=authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../src/core/authorization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { AccountsConfiguration, AuthorizationServerMetadata } from "./types.js";
2
+ export declare function createAccountsClient(configuration: AccountsConfiguration): {
3
+ metadata: () => Promise<AuthorizationServerMetadata>;
4
+ createAuthorizationRequest(options?: {
5
+ scopes?: string[];
6
+ prompt?: "consent" | "login" | "select_account";
7
+ }): Promise<{
8
+ url: URL;
9
+ transaction: import("./types.js").AuthorizationTransaction;
10
+ }>;
11
+ exchangeAuthorizationCode(input: {
12
+ code: string;
13
+ codeVerifier: string;
14
+ }): Promise<import("./types.js").TokenSet>;
15
+ refresh(refreshToken: string, scopes?: string[]): Promise<import("./types.js").TokenSet>;
16
+ revoke(token: string, tokenTypeHint?: "access_token" | "refresh_token"): Promise<void>;
17
+ verifyAccessToken(token: string): Promise<import("./types.js").VerifiedAccessToken>;
18
+ verifyIdToken(token: string, nonce?: string): Promise<import("./types.js").VerifiedIdToken>;
19
+ };
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACR,qBAAqB,EACrB,2BAA2B,EAC9B,MAAM,YAAY,CAAC;AAGpB,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,qBAAqB;;yCAStB;QACvC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,gBAAgB,CAAC;KACnD;;;;qCAOsC;QACnC,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;KACxB;0BAO2B,MAAM,WAAW,MAAM,EAAE;kBAS1C,MAAM,kBACE,cAAc,GAAG,eAAe;6BASpB,MAAM;yBAcV,MAAM,UAAU,MAAM;EASxD"}
@@ -0,0 +1,47 @@
1
+ import { createAuthorizationRequest } from "./authorization.js";
2
+ import { discoverAccounts } from "./discovery.js";
3
+ import { AccountsError } from "./errors.js";
4
+ import { exchangeAuthorizationCode, refreshTokens, revokeToken, } from "./tokens.js";
5
+ import { verifyAccessToken, verifyIdToken } from "./verify.js";
6
+ export function createAccountsClient(configuration) {
7
+ let metadataPromise;
8
+ const metadata = () => {
9
+ metadataPromise ??= discoverAccounts(configuration);
10
+ return metadataPromise;
11
+ };
12
+ return {
13
+ metadata,
14
+ async createAuthorizationRequest(options) {
15
+ return createAuthorizationRequest(await metadata(), configuration, options);
16
+ },
17
+ async exchangeAuthorizationCode(input) {
18
+ return exchangeAuthorizationCode(await metadata(), configuration, input);
19
+ },
20
+ async refresh(refreshToken, scopes) {
21
+ return refreshTokens(await metadata(), configuration, refreshToken, scopes);
22
+ },
23
+ async revoke(token, tokenTypeHint = "refresh_token") {
24
+ return revokeToken(await metadata(), configuration, token, tokenTypeHint);
25
+ },
26
+ async verifyAccessToken(token) {
27
+ if (!configuration.audience) {
28
+ throw new AccountsError("configuration_error", "audience is required to verify an access token");
29
+ }
30
+ return verifyAccessToken(token, await metadata(), {
31
+ audience: configuration.audience,
32
+ clientId: configuration.clientId,
33
+ fetch: configuration.fetch,
34
+ timeoutMs: configuration.timeoutMs,
35
+ });
36
+ },
37
+ async verifyIdToken(token, nonce) {
38
+ return verifyIdToken(token, await metadata(), {
39
+ clientId: configuration.clientId,
40
+ nonce,
41
+ fetch: configuration.fetch,
42
+ timeoutMs: configuration.timeoutMs,
43
+ });
44
+ },
45
+ };
46
+ }
47
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACH,yBAAyB,EACzB,aAAa,EACb,WAAW,GACd,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,UAAU,oBAAoB,CAAC,aAAoC;IACrE,IAAI,eAAiE,CAAC;IACtE,MAAM,QAAQ,GAAG,GAAG,EAAE;QAClB,eAAe,KAAK,gBAAgB,CAAC,aAAa,CAAC,CAAC;QACpD,OAAO,eAAe,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO;QACH,QAAQ;QACR,KAAK,CAAC,0BAA0B,CAAC,OAGhC;YACG,OAAO,0BAA0B,CAC7B,MAAM,QAAQ,EAAE,EAChB,aAAa,EACb,OAAO,CACV,CAAC;QACN,CAAC;QACD,KAAK,CAAC,yBAAyB,CAAC,KAG/B;YACG,OAAO,yBAAyB,CAC5B,MAAM,QAAQ,EAAE,EAChB,aAAa,EACb,KAAK,CACR,CAAC;QACN,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,YAAoB,EAAE,MAAiB;YACjD,OAAO,aAAa,CAChB,MAAM,QAAQ,EAAE,EAChB,aAAa,EACb,YAAY,EACZ,MAAM,CACT,CAAC;QACN,CAAC;QACD,KAAK,CAAC,MAAM,CACR,KAAa,EACb,gBAAkD,eAAe;YAEjE,OAAO,WAAW,CACd,MAAM,QAAQ,EAAE,EAChB,aAAa,EACb,KAAK,EACL,aAAa,CAChB,CAAC;QACN,CAAC;QACD,KAAK,CAAC,iBAAiB,CAAC,KAAa;YACjC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;gBAC1B,MAAM,IAAI,aAAa,CACnB,qBAAqB,EACrB,gDAAgD,CACnD,CAAC;YACN,CAAC;YACD,OAAO,iBAAiB,CAAC,KAAK,EAAE,MAAM,QAAQ,EAAE,EAAE;gBAC9C,QAAQ,EAAE,aAAa,CAAC,QAAQ;gBAChC,QAAQ,EAAE,aAAa,CAAC,QAAQ;gBAChC,KAAK,EAAE,aAAa,CAAC,KAAK;gBAC1B,SAAS,EAAE,aAAa,CAAC,SAAS;aACrC,CAAC,CAAC;QACP,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,KAAc;YAC7C,OAAO,aAAa,CAAC,KAAK,EAAE,MAAM,QAAQ,EAAE,EAAE;gBAC1C,QAAQ,EAAE,aAAa,CAAC,QAAQ;gBAChC,KAAK;gBACL,KAAK,EAAE,aAAa,CAAC,KAAK;gBAC1B,SAAS,EAAE,aAAa,CAAC,SAAS;aACrC,CAAC,CAAC;QACP,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare function randomValue(byteLength?: number): string;
2
+ export declare function generateState(): string;
3
+ export declare function generateNonce(): string;
4
+ export declare function generateCodeVerifier(): string;
5
+ export declare function deriveCodeChallenge(verifier: string): Promise<string>;
6
+ export declare function generatePkce(): Promise<{
7
+ codeVerifier: string;
8
+ codeChallenge: string;
9
+ codeChallengeMethod: "S256";
10
+ }>;
11
+ export declare function timingSafeEqual(left: string, right: string): boolean;
12
+ export declare function assertState(expected: string, actual: string): void;
13
+ export declare function assertNonce(expected: string, actual?: string): void;
14
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/core/crypto.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,UAAU,SAAK,GAAG,MAAM,CAQnD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY3E;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAOD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQpE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAIlE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAOnE"}
@@ -0,0 +1,58 @@
1
+ import { AccountsError } from "./errors.js";
2
+ const PKCE_VALUE = /^[A-Za-z0-9._~-]{43,128}$/;
3
+ function base64Url(bytes) {
4
+ return btoa(String.fromCharCode(...bytes))
5
+ .replace(/\+/g, "-")
6
+ .replace(/\//g, "_")
7
+ .replace(/=+$/, "");
8
+ }
9
+ export function randomValue(byteLength = 32) {
10
+ if (!Number.isInteger(byteLength) || byteLength < 16 || byteLength > 96) {
11
+ throw new AccountsError("configuration_error", "Random value length must be between 16 and 96 bytes");
12
+ }
13
+ return base64Url(crypto.getRandomValues(new Uint8Array(byteLength)));
14
+ }
15
+ export function generateState() {
16
+ return randomValue(32);
17
+ }
18
+ export function generateNonce() {
19
+ return randomValue(32);
20
+ }
21
+ export function generateCodeVerifier() {
22
+ return randomValue(32);
23
+ }
24
+ export async function deriveCodeChallenge(verifier) {
25
+ if (!PKCE_VALUE.test(verifier)) {
26
+ throw new AccountsError("configuration_error", "PKCE verifier must contain 43 to 128 unreserved characters");
27
+ }
28
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
29
+ return base64Url(new Uint8Array(digest));
30
+ }
31
+ export async function generatePkce() {
32
+ const codeVerifier = generateCodeVerifier();
33
+ return {
34
+ codeVerifier,
35
+ codeChallenge: await deriveCodeChallenge(codeVerifier),
36
+ codeChallengeMethod: "S256",
37
+ };
38
+ }
39
+ export function timingSafeEqual(left, right) {
40
+ const maxLength = Math.max(left.length, right.length);
41
+ let difference = left.length ^ right.length;
42
+ for (let index = 0; index < maxLength; index += 1) {
43
+ difference |=
44
+ (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
45
+ }
46
+ return difference === 0;
47
+ }
48
+ export function assertState(expected, actual) {
49
+ if (!timingSafeEqual(expected, actual)) {
50
+ throw new AccountsError("state_mismatch", "OAuth state did not match");
51
+ }
52
+ }
53
+ export function assertNonce(expected, actual) {
54
+ if (!actual || !timingSafeEqual(expected, actual)) {
55
+ throw new AccountsError("nonce_mismatch", "ID token nonce did not match");
56
+ }
57
+ }
58
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/core/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AuthorizationServerMetadata } from "./types.js";
2
+ export declare function normalizeIssuer(issuer: string): string;
3
+ export declare function discoverAccounts(options: {
4
+ issuer: string;
5
+ fetch?: typeof fetch;
6
+ timeoutMs?: number;
7
+ }): Promise<AuthorizationServerMetadata>;
8
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAU9D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA4BtD;AA6ED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAoDvC"}
@@ -0,0 +1,110 @@
1
+ import { AccountsError } from "./errors.js";
2
+ const REQUIRED_ENDPOINTS = [
3
+ "authorization_endpoint",
4
+ "token_endpoint",
5
+ "userinfo_endpoint",
6
+ "jwks_uri",
7
+ "revocation_endpoint",
8
+ ];
9
+ export function normalizeIssuer(issuer) {
10
+ let parsed;
11
+ try {
12
+ parsed = new URL(issuer);
13
+ }
14
+ catch {
15
+ throw new AccountsError("configuration_error", "Accounts issuer must be an absolute URL");
16
+ }
17
+ const isLocalhost = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
18
+ if (parsed.protocol !== "https:" &&
19
+ !(isLocalhost && parsed.protocol === "http:")) {
20
+ throw new AccountsError("configuration_error", "Accounts issuer must use HTTPS outside localhost");
21
+ }
22
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
23
+ throw new AccountsError("configuration_error", "Accounts issuer cannot contain credentials, query, or fragment");
24
+ }
25
+ return parsed.toString().replace(/\/$/, "");
26
+ }
27
+ function isStringArray(value) {
28
+ return (Array.isArray(value) && value.every((item) => typeof item === "string"));
29
+ }
30
+ function validateMetadata(value, expectedIssuer) {
31
+ if (!value || typeof value !== "object") {
32
+ throw new AccountsError("discovery_error", "Discovery response is not an object");
33
+ }
34
+ const metadata = value;
35
+ if (metadata.issuer !== expectedIssuer) {
36
+ throw new AccountsError("discovery_error", "Discovery issuer did not match configuration");
37
+ }
38
+ const issuerOrigin = new URL(expectedIssuer).origin;
39
+ for (const field of REQUIRED_ENDPOINTS) {
40
+ const endpoint = metadata[field];
41
+ if (typeof endpoint !== "string") {
42
+ throw new AccountsError("discovery_error", `Discovery metadata is missing ${field}`);
43
+ }
44
+ let parsed;
45
+ try {
46
+ parsed = new URL(endpoint);
47
+ }
48
+ catch {
49
+ throw new AccountsError("discovery_error", `Discovery metadata contains an invalid ${field}`);
50
+ }
51
+ if (parsed.origin !== issuerOrigin) {
52
+ throw new AccountsError("discovery_error", `Discovery ${field} must use the issuer origin`);
53
+ }
54
+ }
55
+ for (const field of [
56
+ "scopes_supported",
57
+ "grant_types_supported",
58
+ "response_types_supported",
59
+ "token_endpoint_auth_methods_supported",
60
+ "code_challenge_methods_supported",
61
+ ]) {
62
+ if (!isStringArray(metadata[field])) {
63
+ throw new AccountsError("discovery_error", `Discovery metadata contains an invalid ${field}`);
64
+ }
65
+ }
66
+ if (!metadata.code_challenge_methods_supported.includes("S256")) {
67
+ throw new AccountsError("discovery_error", "Authorization server does not support S256 PKCE");
68
+ }
69
+ return metadata;
70
+ }
71
+ export async function discoverAccounts(options) {
72
+ const issuer = normalizeIssuer(options.issuer);
73
+ const fetcher = options.fetch ?? globalThis.fetch;
74
+ if (!fetcher) {
75
+ throw new AccountsError("configuration_error", "No fetch implementation is available");
76
+ }
77
+ const timeoutMs = options.timeoutMs ?? 5_000;
78
+ const controller = new AbortController();
79
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
80
+ try {
81
+ const response = await fetcher(`${issuer}/.well-known/oauth-authorization-server`, {
82
+ headers: { Accept: "application/json" },
83
+ cache: "no-store",
84
+ redirect: "error",
85
+ signal: controller.signal,
86
+ });
87
+ if (!response.ok) {
88
+ throw new AccountsError("discovery_error", "Accounts discovery request failed", {
89
+ status: response.status,
90
+ retryable: response.status >= 500,
91
+ });
92
+ }
93
+ if (new URL(response.url || issuer).origin !== new URL(issuer).origin) {
94
+ throw new AccountsError("discovery_error", "Accounts discovery changed origin");
95
+ }
96
+ return validateMetadata(await response.json(), issuer);
97
+ }
98
+ catch (error) {
99
+ if (error instanceof AccountsError)
100
+ throw error;
101
+ throw new AccountsError("network_error", "Accounts discovery was unavailable", {
102
+ retryable: true,
103
+ cause: error,
104
+ });
105
+ }
106
+ finally {
107
+ clearTimeout(timeout);
108
+ }
109
+ }
110
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,kBAAkB,GAAG;IACvB,wBAAwB;IACxB,gBAAgB;IAChB,mBAAmB;IACnB,UAAU;IACV,qBAAqB;CACf,CAAC;AAEX,MAAM,UAAU,eAAe,CAAC,MAAc;IAC1C,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,IAAI,aAAa,CACnB,qBAAqB,EACrB,yCAAyC,CAC5C,CAAC;IACN,CAAC;IACD,MAAM,WAAW,GACb,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,CAAC;IACvE,IACI,MAAM,CAAC,QAAQ,KAAK,QAAQ;QAC5B,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,EAC/C,CAAC;QACC,MAAM,IAAI,aAAa,CACnB,qBAAqB,EACrB,kDAAkD,CACrD,CAAC;IACN,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACrE,MAAM,IAAI,aAAa,CACnB,qBAAqB,EACrB,gEAAgE,CACnE,CAAC;IACN,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACjC,OAAO,CACH,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAC1E,CAAC;AACN,CAAC;AAED,SAAS,gBAAgB,CACrB,KAAc,EACd,cAAsB;IAEtB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,qCAAqC,CACxC,CAAC;IACN,CAAC;IACD,MAAM,QAAQ,GAAG,KAAgC,CAAC;IAClD,IAAI,QAAQ,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACrC,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,8CAA8C,CACjD,CAAC;IACN,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;IACpD,KAAK,MAAM,KAAK,IAAI,kBAAkB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,iCAAiC,KAAK,EAAE,CAC3C,CAAC;QACN,CAAC;QACD,IAAI,MAAW,CAAC;QAChB,IAAI,CAAC;YACD,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACL,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,0CAA0C,KAAK,EAAE,CACpD,CAAC;QACN,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YACjC,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,aAAa,KAAK,6BAA6B,CAClD,CAAC;QACN,CAAC;IACL,CAAC;IACD,KAAK,MAAM,KAAK,IAAI;QAChB,kBAAkB;QAClB,uBAAuB;QACvB,0BAA0B;QAC1B,uCAAuC;QACvC,kCAAkC;KACrC,EAAE,CAAC;QACA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,0CAA0C,KAAK,EAAE,CACpD,CAAC;QACN,CAAC;IACL,CAAC;IACD,IACI,CAAE,QAAQ,CAAC,gCAA6C,CAAC,QAAQ,CAC7D,MAAM,CACT,EACH,CAAC;QACC,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,iDAAiD,CACpD,CAAC;IACN,CAAC;IACD,OAAO,QAAkD,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAItC;IACG,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,aAAa,CACnB,qBAAqB,EACrB,sCAAsC,CACzC,CAAC;IACN,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAC1B,GAAG,MAAM,yCAAyC,EAClD;YACI,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACvC,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC5B,CACJ,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,mCAAmC,EACnC;gBACI,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,SAAS,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG;aACpC,CACJ,CAAC;QACN,CAAC;QACD,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,MAAM,CAAC,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;YACpE,MAAM,IAAI,aAAa,CACnB,iBAAiB,EACjB,mCAAmC,CACtC,CAAC;QACN,CAAC;QACD,OAAO,gBAAgB,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,aAAa;YAAE,MAAM,KAAK,CAAC;QAChD,MAAM,IAAI,aAAa,CACnB,eAAe,EACf,oCAAoC,EACpC;YACI,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,KAAK;SACf,CACJ,CAAC;IACN,CAAC;YAAS,CAAC;QACP,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { OAuthErrorCode } from "./types.js";
2
+ export type AccountsErrorCode = "configuration_error" | "discovery_error" | "network_error" | "oauth_error" | "protocol_error" | "state_mismatch" | "nonce_mismatch" | "token_verification_error";
3
+ export declare class AccountsError extends Error {
4
+ readonly code: AccountsErrorCode;
5
+ readonly oauthCode?: OAuthErrorCode;
6
+ readonly retryable: boolean;
7
+ readonly status?: number;
8
+ constructor(code: AccountsErrorCode, message: string, options?: {
9
+ oauthCode?: OAuthErrorCode;
10
+ retryable?: boolean;
11
+ status?: number;
12
+ cause?: unknown;
13
+ });
14
+ }
15
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,iBAAiB,GACvB,qBAAqB,GACrB,iBAAiB,GACjB,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,0BAA0B,CAAC;AAEjC,qBAAa,aAAc,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAGrB,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QACL,SAAS,CAAC,EAAE,cAAc,CAAC;QAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACd;CASb"}
@@ -0,0 +1,15 @@
1
+ export class AccountsError extends Error {
2
+ code;
3
+ oauthCode;
4
+ retryable;
5
+ status;
6
+ constructor(code, message, options = {}) {
7
+ super(message, { cause: options.cause });
8
+ this.name = "AccountsError";
9
+ this.code = code;
10
+ this.oauthCode = options.oauthCode;
11
+ this.retryable = options.retryable ?? false;
12
+ this.status = options.status;
13
+ }
14
+ }
15
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC3B,IAAI,CAAoB;IACxB,SAAS,CAAkB;IAC3B,SAAS,CAAU;IACnB,MAAM,CAAU;IAEzB,YACI,IAAuB,EACvB,OAAe,EACf,UAKI,EAAE;QAEN,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACjC,CAAC;CACJ"}
@@ -0,0 +1,9 @@
1
+ export * from "./authorization.js";
2
+ export * from "./client.js";
3
+ export * from "./crypto.js";
4
+ export * from "./discovery.js";
5
+ export * from "./errors.js";
6
+ export * from "./tokens.js";
7
+ export * from "./types.js";
8
+ export * from "./verify.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ export * from "./authorization.js";
2
+ export * from "./client.js";
3
+ export * from "./crypto.js";
4
+ export * from "./discovery.js";
5
+ export * from "./errors.js";
6
+ export * from "./tokens.js";
7
+ export * from "./types.js";
8
+ export * from "./verify.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AccountsConfiguration, AuthorizationServerMetadata, TokenSet } from "./types.js";
2
+ export declare function exchangeAuthorizationCode(metadata: AuthorizationServerMetadata, configuration: AccountsConfiguration, input: {
3
+ code: string;
4
+ codeVerifier: string;
5
+ }): Promise<TokenSet>;
6
+ export declare function refreshTokens(metadata: AuthorizationServerMetadata, configuration: AccountsConfiguration, refreshToken: string, scopes?: string[]): Promise<TokenSet>;
7
+ export declare function revokeToken(metadata: AuthorizationServerMetadata, configuration: AccountsConfiguration, token: string, tokenTypeHint?: "access_token" | "refresh_token"): Promise<void>;
8
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,qBAAqB,EACrB,2BAA2B,EAE3B,QAAQ,EACX,MAAM,YAAY,CAAC;AA2GpB,wBAAsB,yBAAyB,CAC3C,QAAQ,EAAE,2BAA2B,EACrC,aAAa,EAAE,qBAAqB,EACpC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,QAAQ,CAAC,CAenB;AAED,wBAAsB,aAAa,CAC/B,QAAQ,EAAE,2BAA2B,EACrC,aAAa,EAAE,qBAAqB,EACpC,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,QAAQ,CAAC,CAcnB;AAED,wBAAsB,WAAW,CAC7B,QAAQ,EAAE,2BAA2B,EACrC,aAAa,EAAE,qBAAqB,EACpC,KAAK,EAAE,MAAM,EACb,aAAa,GAAE,cAAc,GAAG,eAAiC,GAClE,OAAO,CAAC,IAAI,CAAC,CAWf"}
@@ -0,0 +1,102 @@
1
+ import { AccountsError } from "./errors.js";
2
+ function parseTokenSet(value) {
3
+ if (typeof value.access_token !== "string" ||
4
+ typeof value.refresh_token !== "string" ||
5
+ value.token_type !== "Bearer" ||
6
+ typeof value.expires_in !== "number" ||
7
+ typeof value.scope !== "string") {
8
+ throw new AccountsError("protocol_error", "Token endpoint returned an invalid response");
9
+ }
10
+ return {
11
+ accessToken: value.access_token,
12
+ refreshToken: value.refresh_token,
13
+ ...(typeof value.id_token === "string"
14
+ ? { idToken: value.id_token }
15
+ : {}),
16
+ tokenType: "Bearer",
17
+ expiresIn: value.expires_in,
18
+ scope: value.scope.split(/\s+/).filter(Boolean),
19
+ };
20
+ }
21
+ async function postForm(endpoint, values, options) {
22
+ const fetcher = options.fetch ?? globalThis.fetch;
23
+ const controller = new AbortController();
24
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 5_000);
25
+ try {
26
+ const body = new URLSearchParams();
27
+ for (const [key, value] of Object.entries(values)) {
28
+ if (value !== undefined)
29
+ body.set(key, value);
30
+ }
31
+ const response = await fetcher(endpoint, {
32
+ method: "POST",
33
+ headers: {
34
+ Accept: "application/json",
35
+ "Content-Type": "application/x-www-form-urlencoded",
36
+ },
37
+ body,
38
+ cache: "no-store",
39
+ redirect: "error",
40
+ signal: controller.signal,
41
+ });
42
+ let payload;
43
+ try {
44
+ payload = (await response.json());
45
+ }
46
+ catch (error) {
47
+ throw new AccountsError("protocol_error", "OAuth endpoint returned invalid JSON", {
48
+ status: response.status,
49
+ cause: error,
50
+ });
51
+ }
52
+ if (!response.ok || typeof payload.error === "string") {
53
+ throw new AccountsError("oauth_error", "OAuth request was rejected", {
54
+ oauthCode: typeof payload.error === "string"
55
+ ? payload.error
56
+ : "server_error",
57
+ retryable: response.status >= 500,
58
+ status: response.status,
59
+ });
60
+ }
61
+ return payload;
62
+ }
63
+ catch (error) {
64
+ if (error instanceof AccountsError)
65
+ throw error;
66
+ throw new AccountsError("network_error", "OAuth endpoint was unavailable", {
67
+ retryable: true,
68
+ cause: error,
69
+ });
70
+ }
71
+ finally {
72
+ clearTimeout(timeout);
73
+ }
74
+ }
75
+ export async function exchangeAuthorizationCode(metadata, configuration, input) {
76
+ return parseTokenSet(await postForm(metadata.token_endpoint, {
77
+ grant_type: "authorization_code",
78
+ code: input.code,
79
+ code_verifier: input.codeVerifier,
80
+ client_id: configuration.clientId,
81
+ client_secret: configuration.clientSecret,
82
+ redirect_uri: configuration.redirectUri,
83
+ }, configuration));
84
+ }
85
+ export async function refreshTokens(metadata, configuration, refreshToken, scopes) {
86
+ return parseTokenSet(await postForm(metadata.token_endpoint, {
87
+ grant_type: "refresh_token",
88
+ refresh_token: refreshToken,
89
+ client_id: configuration.clientId,
90
+ client_secret: configuration.clientSecret,
91
+ scope: scopes?.join(" "),
92
+ }, configuration));
93
+ }
94
+ export async function revokeToken(metadata, configuration, token, tokenTypeHint = "refresh_token") {
95
+ await postForm(metadata.revocation_endpoint, {
96
+ token,
97
+ token_type_hint: tokenTypeHint,
98
+ client_id: configuration.clientId,
99
+ client_secret: configuration.clientSecret,
100
+ }, configuration);
101
+ }
102
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ export type OAuthErrorCode = "access_denied" | "authorization_pending" | "expired_token" | "invalid_client" | "invalid_grant" | "invalid_request" | "invalid_scope" | "server_error" | "slow_down" | "temporarily_unavailable" | "unsupported_grant_type" | "unsupported_response_type";
2
+ export interface AuthorizationServerMetadata {
3
+ issuer: string;
4
+ authorization_endpoint: string;
5
+ token_endpoint: string;
6
+ userinfo_endpoint: string;
7
+ jwks_uri: string;
8
+ device_authorization_endpoint?: string;
9
+ revocation_endpoint: string;
10
+ scopes_supported: string[];
11
+ grant_types_supported: string[];
12
+ response_types_supported: string[];
13
+ token_endpoint_auth_methods_supported: string[];
14
+ revocation_endpoint_auth_methods_supported?: string[];
15
+ code_challenge_methods_supported: string[];
16
+ subject_types_supported?: string[];
17
+ id_token_signing_alg_values_supported?: string[];
18
+ claims_supported?: string[];
19
+ elixpo_contract_version?: string;
20
+ elixpo_min_compatible_sdk_version?: string;
21
+ }
22
+ export interface AccountsConfiguration {
23
+ issuer: string;
24
+ clientId: string;
25
+ clientSecret?: string;
26
+ redirectUri: string;
27
+ audience?: string;
28
+ fetch?: typeof fetch;
29
+ timeoutMs?: number;
30
+ }
31
+ export interface AuthorizationTransaction {
32
+ state: string;
33
+ nonce: string;
34
+ codeVerifier: string;
35
+ createdAt: number;
36
+ }
37
+ export interface TokenSet {
38
+ accessToken: string;
39
+ refreshToken: string;
40
+ idToken?: string;
41
+ tokenType: "Bearer";
42
+ expiresIn: number;
43
+ scope: string[];
44
+ }
45
+ export interface VerifiedAccessToken {
46
+ tokenType: "access";
47
+ subject: string;
48
+ issuer: string;
49
+ audience: string[];
50
+ clientId: string;
51
+ expiresAt: number;
52
+ issuedAt: number;
53
+ scopes: string[];
54
+ sessionId?: string;
55
+ email?: string;
56
+ }
57
+ export interface VerifiedIdToken {
58
+ tokenType: "id";
59
+ subject: string;
60
+ issuer: string;
61
+ audience: string[];
62
+ expiresAt: number;
63
+ issuedAt: number;
64
+ nonce?: string;
65
+ email?: string;
66
+ emailVerified?: boolean;
67
+ name?: string;
68
+ preferredUsername?: string;
69
+ }
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACpB,eAAe,GACf,uBAAuB,GACvB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,cAAc,GACd,WAAW,GACX,yBAAyB,GACzB,wBAAwB,GACxB,2BAA2B,CAAC;AAElC,MAAM,WAAW,2BAA2B;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,qCAAqC,EAAE,MAAM,EAAE,CAAC;IAChD,0CAA0C,CAAC,EAAE,MAAM,EAAE,CAAC;IACtD,gCAAgC,EAAE,MAAM,EAAE,CAAC;IAC3C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,qCAAqC,CAAC,EAAE,MAAM,EAAE,CAAC;IACjD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iCAAiC,CAAC,EAAE,MAAM,CAAC;CAC9C;AAED,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,QAAQ,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,QAAQ,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import type { AuthorizationServerMetadata, VerifiedAccessToken, VerifiedIdToken } from "./types.js";
2
+ export declare function verifyAccessToken(token: string, metadata: AuthorizationServerMetadata, options: {
3
+ audience: string;
4
+ clientId?: string;
5
+ fetch?: typeof fetch;
6
+ timeoutMs?: number;
7
+ clockTolerance?: number;
8
+ }): Promise<VerifiedAccessToken>;
9
+ export declare function verifyIdToken(token: string, metadata: AuthorizationServerMetadata, options: {
10
+ clientId: string;
11
+ nonce?: string;
12
+ fetch?: typeof fetch;
13
+ timeoutMs?: number;
14
+ clockTolerance?: number;
15
+ }): Promise<VerifiedIdToken>;
16
+ export declare function clearJwksCache(): void;
17
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/core/verify.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACR,2BAA2B,EAC3B,mBAAmB,EACnB,eAAe,EAClB,MAAM,YAAY,CAAC;AAgJpB,wBAAsB,iBAAiB,CACnC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,2BAA2B,EACrC,OAAO,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,GACF,OAAO,CAAC,mBAAmB,CAAC,CA8B9B;AAED,wBAAsB,aAAa,CAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,2BAA2B,EACrC,OAAO,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,GACF,OAAO,CAAC,eAAe,CAAC,CAiC1B;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
@@ -0,0 +1,157 @@
1
+ import { createLocalJWKSet, decodeProtectedHeader, errors as joseErrors, jwtVerify, } from "jose";
2
+ import { assertNonce } from "./crypto.js";
3
+ import { AccountsError } from "./errors.js";
4
+ const jwksCache = new Map();
5
+ function audiences(payload) {
6
+ if (typeof payload.aud === "string")
7
+ return [payload.aud];
8
+ if (Array.isArray(payload.aud))
9
+ return payload.aud;
10
+ return [];
11
+ }
12
+ async function loadJwks(metadata, options, force = false) {
13
+ const cached = jwksCache.get(metadata.jwks_uri);
14
+ if (!force && cached && cached.expiresAt > Date.now())
15
+ return cached.jwks;
16
+ const fetcher = options.fetch ?? globalThis.fetch;
17
+ const controller = new AbortController();
18
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 5_000);
19
+ try {
20
+ const response = await fetcher(metadata.jwks_uri, {
21
+ headers: { Accept: "application/json" },
22
+ cache: "no-store",
23
+ redirect: "error",
24
+ signal: controller.signal,
25
+ });
26
+ if (!response.ok) {
27
+ throw new AccountsError("token_verification_error", "JWKS request failed", {
28
+ status: response.status,
29
+ retryable: response.status >= 500,
30
+ });
31
+ }
32
+ const value = (await response.json());
33
+ if (!Array.isArray(value.keys) || value.keys.length === 0) {
34
+ throw new AccountsError("token_verification_error", "JWKS response did not contain signing keys");
35
+ }
36
+ const valid = value.keys.every((key) => key &&
37
+ typeof key === "object" &&
38
+ key.kty === "OKP" &&
39
+ key.crv === "Ed25519" &&
40
+ key.alg === "EdDSA" &&
41
+ typeof key.kid === "string" &&
42
+ !key.d);
43
+ if (!valid) {
44
+ throw new AccountsError("token_verification_error", "JWKS response contained an unsupported key");
45
+ }
46
+ const jwks = value;
47
+ jwksCache.set(metadata.jwks_uri, {
48
+ jwks,
49
+ expiresAt: Date.now() + 5 * 60_000,
50
+ });
51
+ return jwks;
52
+ }
53
+ catch (error) {
54
+ if (error instanceof AccountsError)
55
+ throw error;
56
+ throw new AccountsError("network_error", "JWKS endpoint was unavailable", {
57
+ retryable: true,
58
+ cause: error,
59
+ });
60
+ }
61
+ finally {
62
+ clearTimeout(timeout);
63
+ }
64
+ }
65
+ async function verify(token, metadata, audience, options) {
66
+ let header;
67
+ try {
68
+ header = decodeProtectedHeader(token);
69
+ }
70
+ catch (error) {
71
+ throw new AccountsError("token_verification_error", "Token header is invalid", { cause: error });
72
+ }
73
+ if (header.alg !== "EdDSA" || typeof header.kid !== "string") {
74
+ throw new AccountsError("token_verification_error", "Token uses an unsupported signing key or algorithm");
75
+ }
76
+ for (let attempt = 0; attempt < 2; attempt += 1) {
77
+ try {
78
+ const jwks = await loadJwks(metadata, options, attempt === 1);
79
+ const result = await jwtVerify(token, createLocalJWKSet(jwks), {
80
+ algorithms: ["EdDSA"],
81
+ audience,
82
+ issuer: metadata.issuer,
83
+ clockTolerance: options.clockTolerance ?? 5,
84
+ });
85
+ return result.payload;
86
+ }
87
+ catch (error) {
88
+ if (attempt === 0 &&
89
+ error instanceof joseErrors.JWKSNoMatchingKey) {
90
+ continue;
91
+ }
92
+ if (error instanceof AccountsError)
93
+ throw error;
94
+ throw new AccountsError("token_verification_error", "Token verification failed", { cause: error });
95
+ }
96
+ }
97
+ throw new AccountsError("token_verification_error", "Token signing key was not found");
98
+ }
99
+ export async function verifyAccessToken(token, metadata, options) {
100
+ const payload = await verify(token, metadata, options.audience, options);
101
+ if (payload.type !== "access" ||
102
+ typeof payload.sub !== "string" ||
103
+ typeof payload.iss !== "string" ||
104
+ typeof payload.exp !== "number" ||
105
+ typeof payload.iat !== "number" ||
106
+ typeof payload.client_id !== "string" ||
107
+ !Array.isArray(payload.scopes) ||
108
+ !payload.scopes.every((scope) => typeof scope === "string") ||
109
+ (options.clientId && payload.client_id !== options.clientId)) {
110
+ throw new AccountsError("token_verification_error", "Access token claims are invalid");
111
+ }
112
+ return {
113
+ tokenType: "access",
114
+ subject: payload.sub,
115
+ issuer: payload.iss,
116
+ audience: audiences(payload),
117
+ clientId: payload.client_id,
118
+ expiresAt: payload.exp,
119
+ issuedAt: payload.iat,
120
+ scopes: payload.scopes,
121
+ ...(typeof payload.sid === "string" ? { sessionId: payload.sid } : {}),
122
+ ...(typeof payload.email === "string" ? { email: payload.email } : {}),
123
+ };
124
+ }
125
+ export async function verifyIdToken(token, metadata, options) {
126
+ const payload = await verify(token, metadata, options.clientId, options);
127
+ if (payload.type !== "id" ||
128
+ typeof payload.sub !== "string" ||
129
+ typeof payload.iss !== "string" ||
130
+ typeof payload.exp !== "number" ||
131
+ typeof payload.iat !== "number") {
132
+ throw new AccountsError("token_verification_error", "ID token claims are invalid");
133
+ }
134
+ if (options.nonce)
135
+ assertNonce(options.nonce, payload.nonce);
136
+ return {
137
+ tokenType: "id",
138
+ subject: payload.sub,
139
+ issuer: payload.iss,
140
+ audience: audiences(payload),
141
+ expiresAt: payload.exp,
142
+ issuedAt: payload.iat,
143
+ ...(typeof payload.nonce === "string" ? { nonce: payload.nonce } : {}),
144
+ ...(typeof payload.email === "string" ? { email: payload.email } : {}),
145
+ ...(typeof payload.email_verified === "boolean"
146
+ ? { emailVerified: payload.email_verified }
147
+ : {}),
148
+ ...(typeof payload.name === "string" ? { name: payload.name } : {}),
149
+ ...(typeof payload.preferred_username === "string"
150
+ ? { preferredUsername: payload.preferred_username }
151
+ : {}),
152
+ };
153
+ }
154
+ export function clearJwksCache() {
155
+ jwksCache.clear();
156
+ }
157
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/core/verify.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@elixpo/accounts",
3
+ "version": "1.0.1",
4
+ "description": "Standards-first OAuth and OpenID Connect SDK for Elixpo Accounts",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/elixpo/accounts.elixpo.git",
10
+ "directory": "packages/accounts"
11
+ },
12
+ "homepage": "https://accounts.elixpo.com/docs/lixaccounts",
13
+ "bugs": "https://github.com/elixpo/accounts.elixpo/issues",
14
+ "sideEffects": false,
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "CHANGELOG.md"
19
+ ],
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/core/index.d.ts",
23
+ "import": "./dist/core/index.js",
24
+ "default": "./dist/core/index.js"
25
+ },
26
+ "./core": {
27
+ "types": "./dist/core/index.d.ts",
28
+ "import": "./dist/core/index.js",
29
+ "default": "./dist/core/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "main": "./dist/core/index.js",
34
+ "types": "./dist/core/index.d.ts",
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.build.json",
40
+ "clean": "rm -rf dist",
41
+ "pack:check": "npm run build && npm pack --dry-run"
42
+ },
43
+ "dependencies": {
44
+ "jose": "^5.9.6"
45
+ },
46
+ "devDependencies": {
47
+ "typescript": "^5"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public",
51
+ "provenance": true
52
+ }
53
+ }