@dreadkn1ght123/auth-core 0.2.0

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 ADDED
@@ -0,0 +1,50 @@
1
+ # @dreadkn1ght123/auth-core
2
+
3
+ Framework-neutral server-side VVP OpenID Connect foundations, built on
4
+ `openid-client` v6. It provides discovery, Authorization Code + PKCE, callback,
5
+ refresh and RP-initiated logout primitives, claim/role normalization, safe
6
+ redirect handling, safe error classification, and pluggable session storage.
7
+
8
+ `MemorySessionStore` is deliberately limited to development and test. Supply a
9
+ durable/shared `SessionStore` in production. Keep callback verifiers, session
10
+ identifiers and all tokens in HTTP-only server-managed storage/cookies; never
11
+ send `ServerSession.tokens` to a browser or logger.
12
+
13
+ This SDK supports confidential server-side clients only: `clientSecret` is
14
+ mandatory in every environment and is always sent with `ClientSecretBasic`.
15
+ Production also requires `publicOrigin`; callback and post-logout defaults are
16
+ derived as `<publicOrigin>/auth/callback` and
17
+ `<publicOrigin>/auth/signed-out`. Explicit overrides must remain HTTPS,
18
+ same-origin, and match configured routes.
19
+
20
+ The default requested scopes are `openid profile email vvp-identity`. Custom
21
+ scope lists must retain both `openid` and `vvp-identity` so applications
22
+ receive the VVP identity-claim contract.
23
+
24
+ JWT access tokens are independently verified against the discovered provider
25
+ JWKS, including issuer, lifetime, signature, and configured `aud`/Keycloak
26
+ `azp` policy. Both defaults require the client ID: `aud` must include
27
+ `clientId` and `azp` must equal it. Configure `accessTokenAudiences` and
28
+ `accessTokenAuthorizedParties` explicitly when a deployment uses different
29
+ token mappings. Configure every Keycloak client with an audience mapper that
30
+ adds its client ID to access-token `aud`. Opaque tokens require an injected
31
+ `AccessTokenValidator` backed by a trusted introspection strategy.
32
+
33
+ ## Safe diagnostics
34
+
35
+ `AuthError` carries a stable `code`, callback `stage`, `reason`, strictly typed
36
+ `details`, and an optional `cause`. Use `safeAuthErrorDetails(error)` and
37
+ `classifyAuthError(error)` at logging boundaries. They recursively recognize
38
+ supported `openid-client`, `oauth4webapi`, and `jose` error families but return
39
+ only allowlisted machine fields such as library/code, HTTP status, and failed
40
+ claim. They never copy an exception message, response body, headers, full URL,
41
+ query string, `error_description`, tokens, or raw claims.
42
+
43
+ An unknown library error intentionally produces an `unknown` reason plus any
44
+ safe details that can be recognized. Do not spread the original error or
45
+ `details` into an HTTP response.
46
+
47
+ For Keycloak setup and expected safe claim shapes, use
48
+ [`../../docs/keycloak-client-template.md`](../../docs/keycloak-client-template.md).
49
+ Migration from `0.1.x` to the aligned `0.2.0` packages is documented in
50
+ [`../../UPGRADE.md`](../../UPGRADE.md).
@@ -0,0 +1,18 @@
1
+ import type { AuthConfig } from "@dreadkn1ght123/auth-types";
2
+ import { type JWTPayload, type JWTVerifyGetKey } from "jose";
3
+ export interface AccessTokenValidator {
4
+ /**
5
+ * Return only claims obtained after validating the token. Implementations
6
+ * may support opaque tokens through introspection; unverified decoding is
7
+ * never a valid implementation.
8
+ */
9
+ validate(accessToken: string): Promise<Readonly<Record<string, unknown>>>;
10
+ }
11
+ export declare class KeycloakJwtAccessTokenValidator implements AccessTokenValidator {
12
+ #private;
13
+ constructor(config: AuthConfig, jwksUri: URL, options?: {
14
+ keyResolver?: JWTVerifyGetKey;
15
+ });
16
+ validate(accessToken: string): Promise<JWTPayload>;
17
+ }
18
+ //# sourceMappingURL=access-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-token.d.ts","sourceRoot":"","sources":["../src/access-token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,eAAe,EACrB,MAAM,MAAM,CAAC;AAGd,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3E;AAED,qBAAa,+BAAgC,YAAW,oBAAoB;;gBAKxE,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,GAAG,EACZ,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,eAAe,CAAA;KAAO;IAM3C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAkDzD"}
@@ -0,0 +1,49 @@
1
+ import { createRemoteJWKSet, jwtVerify, } from "jose";
2
+ import { AuthError, classifyAuthError } from "./errors.js";
3
+ export class KeycloakJwtAccessTokenValidator {
4
+ #config;
5
+ #jwks;
6
+ constructor(config, jwksUri, options = {}) {
7
+ this.#config = config;
8
+ this.#jwks = options.keyResolver ?? createRemoteJWKSet(jwksUri);
9
+ }
10
+ async validate(accessToken) {
11
+ if (accessToken.split(".").length !== 3) {
12
+ throw new AuthError("ACCESS_TOKEN_INVALID", "Opaque access token requires a configured validation strategy", {
13
+ stage: "access_token_validation",
14
+ reason: "access_token_not_jwt",
15
+ });
16
+ }
17
+ try {
18
+ const { payload } = await jwtVerify(accessToken, this.#jwks, {
19
+ issuer: this.#config.issuer.href.replace(/\/$/, ""),
20
+ ...(this.#config.accessTokenAudiences.length > 0
21
+ ? { audience: [...this.#config.accessTokenAudiences] }
22
+ : {}),
23
+ requiredClaims: ["exp", "iss", "sub"],
24
+ });
25
+ if (this.#config.accessTokenAuthorizedParties.length > 0 &&
26
+ (typeof payload["azp"] !== "string" ||
27
+ !this.#config.accessTokenAuthorizedParties.includes(payload["azp"]))) {
28
+ throw new AuthError("ACCESS_TOKEN_INVALID", "Access token authorized party is not allowed", {
29
+ stage: "access_token_validation",
30
+ reason: "authorized_party_mismatch",
31
+ details: { claim: "azp" },
32
+ });
33
+ }
34
+ return payload;
35
+ }
36
+ catch (cause) {
37
+ if (cause instanceof AuthError)
38
+ throw cause;
39
+ const classified = classifyAuthError(cause);
40
+ throw new AuthError("ACCESS_TOKEN_INVALID", "Access token signature or claims validation failed", {
41
+ cause,
42
+ stage: "access_token_validation",
43
+ reason: classified.reason,
44
+ details: classified.details,
45
+ });
46
+ }
47
+ }
48
+ }
49
+ //# sourceMappingURL=access-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-token.js","sourceRoot":"","sources":["../src/access-token.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,SAAS,GAGV,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAW3D,MAAM,OAAO,+BAA+B;IACjC,OAAO,CAAa;IACpB,KAAK,CAAkB;IAEhC,YACE,MAAkB,EAClB,OAAY,EACZ,UAA6C,EAAE;QAE/C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,SAAS,CACjB,sBAAsB,EACtB,+DAA+D,EAC/D;gBACE,KAAK,EAAE,yBAAyB;gBAChC,MAAM,EAAE,sBAAsB;aAC/B,CACF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE;gBAC3D,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;gBACnD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC;oBAC9C,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;oBACtD,CAAC,CAAC,EAAE,CAAC;gBACP,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;aACtC,CAAC,CAAC;YACH,IACE,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,MAAM,GAAG,CAAC;gBACpD,CAAC,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,QAAQ;oBACjC,CAAC,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EACtE,CAAC;gBACD,MAAM,IAAI,SAAS,CACjB,sBAAsB,EACtB,8CAA8C,EAC9C;oBACE,KAAK,EAAE,yBAAyB;oBAChC,MAAM,EAAE,2BAA2B;oBACnC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;iBAC1B,CACF,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,SAAS;gBAAE,MAAM,KAAK,CAAC;YAC5C,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,SAAS,CACjB,sBAAsB,EACtB,oDAAoD,EACpD;gBACE,KAAK;gBACL,KAAK,EAAE,yBAAyB;gBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,UAAU,CAAC,OAAO;aAC5B,CACF,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import { type Actor, type VvpClaims } from "@dreadkn1ght123/auth-types";
2
+ export declare function normalizeRoles(value: unknown): readonly string[];
3
+ export declare function actorFromClaims(claims: Readonly<Record<string, unknown>>): Actor;
4
+ export declare function isVvpClaims(claims: unknown): claims is VvpClaims;
5
+ export declare function hasRealmRole(actor: Actor | undefined, role: string): boolean;
6
+ export declare function hasClientRole(actor: Actor | undefined, role: string, clientId: string): boolean;
7
+ export declare function hasAnyClientRole(actor: Actor | undefined, roles: readonly string[], clientId: string): boolean;
8
+ /** Binds helpers to the configured client so callers need not duplicate its ID. */
9
+ export declare function createClientRoleHelpers(clientId: string): {
10
+ hasClientRole: (actor: Actor | undefined, role: string) => boolean;
11
+ hasAnyClientRole: (actor: Actor | undefined, roles: readonly string[]) => boolean;
12
+ roles: (actor: Actor | undefined) => readonly string[];
13
+ };
14
+ //# sourceMappingURL=claims.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,SAAS,EACf,MAAM,4BAA4B,CAAC;AAKpC,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAQhE;AAuBD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,KAAK,CAyDP;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,SAAS,CAOhE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAET;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAET;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM;2BAM7B,KAAK,GAAG,SAAS,QAAQ,MAAM;8BAE5B,KAAK,GAAG,SAAS,SAAS,SAAS,MAAM,EAAE;mBAEtD,KAAK,GAAG,SAAS,KAAG,SAAS,MAAM,EAAE;EAGvD"}
package/dist/claims.js ADDED
@@ -0,0 +1,110 @@
1
+ import {} from "@dreadkn1ght123/auth-types";
2
+ import { AuthError } from "./errors.js";
3
+ const ROLE_PATTERN = /^[a-z0-9][a-z0-9._:-]{0,127}$/;
4
+ export function normalizeRoles(value) {
5
+ if (!Array.isArray(value))
6
+ return [];
7
+ return [...new Set(value
8
+ .filter((role) => typeof role === "string")
9
+ .map((role) => role.trim().toLowerCase())
10
+ .filter((role) => ROLE_PATTERN.test(role)))].sort();
11
+ }
12
+ function requiredString(claims, name) {
13
+ const value = claims[name];
14
+ if (typeof value !== "string" || !value.trim()) {
15
+ throw new AuthError("CLAIMS_INVALID", `Required claim ${name} is missing`, {
16
+ stage: "actor_claims_mapping",
17
+ reason: "required_claim_missing",
18
+ safeDetails: name === "sub"
19
+ ? { failedClaim: "sub", claimFailureReason: "missing" }
20
+ : {},
21
+ });
22
+ }
23
+ return value.trim();
24
+ }
25
+ function optionalString(value) {
26
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
27
+ }
28
+ export function actorFromClaims(claims) {
29
+ const realmAccess = claims["realm_access"] && typeof claims["realm_access"] === "object"
30
+ ? claims["realm_access"]
31
+ : {};
32
+ const resourceAccess = claims["resource_access"] && typeof claims["resource_access"] === "object"
33
+ ? claims["resource_access"]
34
+ : {};
35
+ const clientRoles = {};
36
+ for (const [clientId, access] of Object.entries(resourceAccess)) {
37
+ if (access && typeof access === "object") {
38
+ clientRoles[clientId] = normalizeRoles(access["roles"]);
39
+ }
40
+ }
41
+ return {
42
+ sub: requiredString(claims, "sub"),
43
+ ...(optionalString(claims["vvp_actor_id"])
44
+ ? { vvpActorId: optionalString(claims["vvp_actor_id"]) }
45
+ : {}),
46
+ ...(optionalString(claims["actor_type"])
47
+ ? { actorType: optionalString(claims["actor_type"]) }
48
+ : {}),
49
+ ...(optionalString(claims["organization_id"])
50
+ ? { organizationId: optionalString(claims["organization_id"]) }
51
+ : {}),
52
+ ...(optionalString(claims["employee_id"])
53
+ ? { employeeId: optionalString(claims["employee_id"]) }
54
+ : {}),
55
+ ...(optionalString(claims["department_id"])
56
+ ? { departmentId: optionalString(claims["department_id"]) }
57
+ : {}),
58
+ ...(optionalString(claims["email"])
59
+ ? { email: optionalString(claims["email"]) }
60
+ : {}),
61
+ ...(typeof claims["email_verified"] === "boolean"
62
+ ? { emailVerified: claims["email_verified"] }
63
+ : {}),
64
+ ...(optionalString(claims["preferred_username"])
65
+ ? { username: optionalString(claims["preferred_username"]) }
66
+ : {}),
67
+ ...(optionalString(claims["name"])
68
+ ? { name: optionalString(claims["name"]) }
69
+ : {}),
70
+ ...(optionalString(claims["given_name"])
71
+ ? { givenName: optionalString(claims["given_name"]) }
72
+ : {}),
73
+ ...(optionalString(claims["family_name"])
74
+ ? { familyName: optionalString(claims["family_name"]) }
75
+ : {}),
76
+ realmRoles: normalizeRoles(realmAccess["roles"]),
77
+ clientRoles,
78
+ };
79
+ }
80
+ export function isVvpClaims(claims) {
81
+ try {
82
+ actorFromClaims(claims);
83
+ return true;
84
+ }
85
+ catch {
86
+ return false;
87
+ }
88
+ }
89
+ export function hasRealmRole(actor, role) {
90
+ return actor?.realmRoles.includes(role.trim().toLowerCase()) ?? false;
91
+ }
92
+ export function hasClientRole(actor, role, clientId) {
93
+ return actor?.clientRoles[clientId]?.includes(role.trim().toLowerCase()) ?? false;
94
+ }
95
+ export function hasAnyClientRole(actor, roles, clientId) {
96
+ return roles.some((role) => hasClientRole(actor, role, clientId));
97
+ }
98
+ /** Binds helpers to the configured client so callers need not duplicate its ID. */
99
+ export function createClientRoleHelpers(clientId) {
100
+ const normalizedClientId = clientId.trim();
101
+ if (!normalizedClientId) {
102
+ throw new AuthError("CONFIG_INVALID", "clientId must not be empty");
103
+ }
104
+ return {
105
+ hasClientRole: (actor, role) => hasClientRole(actor, role, normalizedClientId),
106
+ hasAnyClientRole: (actor, roles) => hasAnyClientRole(actor, roles, normalizedClientId),
107
+ roles: (actor) => actor?.clientRoles[normalizedClientId] ?? [],
108
+ };
109
+ }
110
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AuthConfig, AuthConfigInput, AuthRouteSettings, AuthRouteSettingsInput, AuthRoutesOption } from "@dreadkn1ght123/auth-types";
2
+ export declare function normalizeAuthRoutes(input?: AuthRouteSettingsInput): AuthRouteSettings;
3
+ /**
4
+ * Combines nested core configuration and the adapter-level `{ routes }` shape.
5
+ * Supplying both is supported only when they normalize to the same routes, so
6
+ * a top-level adapter option can never silently override security settings.
7
+ */
8
+ export declare function withAuthRoutes(input: AuthConfigInput, routeOptions?: AuthRoutesOption | AuthRouteSettingsInput): AuthConfigInput;
9
+ export declare function validateConfig(configInput: AuthConfigInput, routeOptions?: AuthRoutesOption | AuthRouteSettingsInput): AuthConfig;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAIjB,MAAM,4BAA4B,CAAC;AA6BpC,wBAAgB,mBAAmB,CACjC,KAAK,GAAE,sBAA2B,GACjC,iBAAiB,CAiCnB;AAuFD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,YAAY,CAAC,EAAE,gBAAgB,GAAG,sBAAsB,GACvD,eAAe,CAmBjB;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,eAAe,EAC5B,YAAY,CAAC,EAAE,gBAAgB,GAAG,sBAAsB,GACvD,UAAU,CAsJZ"}
package/dist/config.js ADDED
@@ -0,0 +1,229 @@
1
+ import { AuthError } from "./errors.js";
2
+ const DEFAULT_SCOPES = ["openid", "profile", "email", "vvp-identity"];
3
+ const DEFAULT_TTL_SECONDS = 8 * 60 * 60;
4
+ const PATH_PATTERN = /^\/(?:[A-Za-z0-9._~-]+\/?)*$/;
5
+ function path(value, field) {
6
+ const normalized = value.trim();
7
+ if (!PATH_PATTERN.test(normalized) || normalized.includes("//")) {
8
+ throw new AuthError("CONFIG_INVALID", `${field} must be an absolute local path without query or fragment`);
9
+ }
10
+ return normalized.length > 1 ? normalized.replace(/\/+$/, "") : normalized;
11
+ }
12
+ function route(basePath, value, fallback, field) {
13
+ if (!value)
14
+ return `${basePath === "/" ? "" : basePath}/${fallback}`;
15
+ const supplied = path(value.startsWith("/") ? value : `/${value}`, field);
16
+ if (supplied === basePath || supplied.startsWith(`${basePath}/`))
17
+ return supplied;
18
+ return path(`${basePath === "/" ? "" : basePath}${supplied}`, field);
19
+ }
20
+ function containsPath(parent, child) {
21
+ return parent === "/" || child === parent || child.startsWith(`${parent}/`);
22
+ }
23
+ export function normalizeAuthRoutes(input = {}) {
24
+ const basePath = path(input.basePath ?? "/auth", "routes.basePath");
25
+ const callbackPath = route(basePath, input.callbackPath, "callback", "routes.callbackPath");
26
+ const cookiePath = path(input.cookiePath ?? basePath, "routes.cookiePath");
27
+ if (!containsPath(cookiePath, callbackPath)) {
28
+ throw new AuthError("CONFIG_INVALID", "routes.cookiePath must contain routes.callbackPath");
29
+ }
30
+ const result = {
31
+ basePath,
32
+ startPath: route(basePath, input.startPath, "start", "routes.startPath"),
33
+ loginPath: route(basePath, input.loginPath, "login", "routes.loginPath"),
34
+ callbackPath,
35
+ logoutPath: route(basePath, input.logoutPath, "logout", "routes.logoutPath"),
36
+ signedOutPath: route(basePath, input.signedOutPath, "signed-out", "routes.signedOutPath"),
37
+ errorPath: route(basePath, input.errorPath, "error", "routes.errorPath"),
38
+ sessionPath: route(basePath, input.sessionPath, "me", "routes.sessionPath"),
39
+ cookiePath,
40
+ };
41
+ const endpointPaths = [
42
+ result.startPath, result.loginPath, result.callbackPath, result.logoutPath,
43
+ result.signedOutPath, result.errorPath, result.sessionPath,
44
+ ];
45
+ if (new Set(endpointPaths).size !== endpointPaths.length) {
46
+ throw new AuthError("CONFIG_INVALID", "Authentication route paths must be unique");
47
+ }
48
+ return result;
49
+ }
50
+ function required(value, field) {
51
+ const normalized = value.trim();
52
+ if (!normalized) {
53
+ throw new AuthError("CONFIG_INVALID", `${field} must not be empty`);
54
+ }
55
+ return normalized;
56
+ }
57
+ function parseHttpUrl(value, field) {
58
+ let url;
59
+ try {
60
+ url = new URL(value);
61
+ }
62
+ catch {
63
+ throw new AuthError("CONFIG_INVALID", `${field} must be an absolute URL`);
64
+ }
65
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
66
+ throw new AuthError("CONFIG_INVALID", `${field} must use HTTP or HTTPS`);
67
+ }
68
+ if (url.username || url.password || url.hash) {
69
+ throw new AuthError("CONFIG_INVALID", `${field} must not contain credentials or a fragment`);
70
+ }
71
+ return url;
72
+ }
73
+ function assertTransport(url, field, environment) {
74
+ if (environment === "production" && url.protocol !== "https:") {
75
+ throw new AuthError("CONFIG_INVALID", `${field} must use HTTPS in production`);
76
+ }
77
+ if (url.protocol === "http:" &&
78
+ url.hostname !== "localhost" &&
79
+ url.hostname !== "127.0.0.1" &&
80
+ url.hostname !== "::1") {
81
+ throw new AuthError("CONFIG_INVALID", `${field} may use HTTP only for a loopback host`);
82
+ }
83
+ }
84
+ function parseOrigin(value, field, environment) {
85
+ const url = parseHttpUrl(value, field);
86
+ assertTransport(url, field, environment);
87
+ if (url.pathname !== "/" || url.search) {
88
+ throw new AuthError("CONFIG_INVALID", `${field} must be an origin without path, query, or fragment`);
89
+ }
90
+ return new URL(url.origin);
91
+ }
92
+ function uiText(value, fallback, field) {
93
+ return value === undefined ? fallback : required(value, field);
94
+ }
95
+ function normalizeAuthUi(input = {}) {
96
+ const locale = input.locale ?? "ru";
97
+ if (locale !== "ru" && locale !== "en") {
98
+ throw new AuthError("CONFIG_INVALID", "ui.locale must be ru or en");
99
+ }
100
+ return {
101
+ locale,
102
+ productName: uiText(input.productName, "VVP", "ui.productName"),
103
+ ...(input.logoUrl === undefined
104
+ ? {}
105
+ : { logoUrl: path(input.logoUrl, "ui.logoUrl") }),
106
+ supportText: uiText(input.supportText, locale === "ru"
107
+ ? "Обратитесь к администратору системы"
108
+ : "Contact your system administrator", "ui.supportText"),
109
+ };
110
+ }
111
+ /**
112
+ * Combines nested core configuration and the adapter-level `{ routes }` shape.
113
+ * Supplying both is supported only when they normalize to the same routes, so
114
+ * a top-level adapter option can never silently override security settings.
115
+ */
116
+ export function withAuthRoutes(input, routeOptions) {
117
+ let routes;
118
+ if (routeOptions && "routes" in routeOptions) {
119
+ routes = routeOptions.routes;
120
+ }
121
+ else {
122
+ routes = routeOptions;
123
+ }
124
+ if (!routes)
125
+ return input;
126
+ if (input.routes) {
127
+ const configured = normalizeAuthRoutes(input.routes);
128
+ const supplied = normalizeAuthRoutes(routes);
129
+ if (JSON.stringify(configured) !== JSON.stringify(supplied)) {
130
+ throw new AuthError("CONFIG_INVALID", "Top-level routes and config.routes must match when both are supplied");
131
+ }
132
+ }
133
+ return { ...input, routes };
134
+ }
135
+ export function validateConfig(configInput, routeOptions) {
136
+ const input = withAuthRoutes(configInput, routeOptions);
137
+ const environment = input.environment ?? "production";
138
+ const issuer = parseHttpUrl(required(input.issuer, "issuer"), "issuer");
139
+ assertTransport(issuer, "issuer", environment);
140
+ const routes = normalizeAuthRoutes(input.routes);
141
+ if (environment === "production" && !input.publicOrigin) {
142
+ throw new AuthError("CONFIG_INVALID", "publicOrigin is required in production");
143
+ }
144
+ const publicOrigin = input.publicOrigin
145
+ ? parseOrigin(input.publicOrigin, "publicOrigin", environment)
146
+ : undefined;
147
+ if (!input.redirectUri && !publicOrigin) {
148
+ throw new AuthError("CONFIG_INVALID", "redirectUri is required when publicOrigin is omitted");
149
+ }
150
+ const redirectUri = input.redirectUri
151
+ ? parseHttpUrl(input.redirectUri, "redirectUri")
152
+ : new URL(routes.callbackPath, publicOrigin);
153
+ const postLogoutRedirectUri = input.postLogoutRedirectUri
154
+ ? parseHttpUrl(input.postLogoutRedirectUri, "postLogoutRedirectUri")
155
+ : publicOrigin
156
+ ? new URL(routes.signedOutPath, publicOrigin)
157
+ : undefined;
158
+ assertTransport(redirectUri, "redirectUri", environment);
159
+ if (postLogoutRedirectUri) {
160
+ assertTransport(postLogoutRedirectUri, "postLogoutRedirectUri", environment);
161
+ }
162
+ if (publicOrigin && redirectUri.origin !== publicOrigin.origin) {
163
+ throw new AuthError("CONFIG_INVALID", "redirectUri must have the same origin as publicOrigin");
164
+ }
165
+ if (publicOrigin && postLogoutRedirectUri &&
166
+ postLogoutRedirectUri.origin !== publicOrigin.origin) {
167
+ throw new AuthError("CONFIG_INVALID", "postLogoutRedirectUri must have the same origin as publicOrigin");
168
+ }
169
+ const scopes = [...new Set(input.scopes ?? DEFAULT_SCOPES)].map((scope) => required(scope, "scope"));
170
+ if (!scopes.includes("openid") || !scopes.includes("vvp-identity")) {
171
+ throw new AuthError("CONFIG_INVALID", "scopes must include openid and vvp-identity");
172
+ }
173
+ const sessionTtlSeconds = input.sessionTtlSeconds ?? DEFAULT_TTL_SECONDS;
174
+ if (!Number.isSafeInteger(sessionTtlSeconds) || sessionTtlSeconds <= 0) {
175
+ throw new AuthError("CONFIG_INVALID", "sessionTtlSeconds must be a positive integer");
176
+ }
177
+ const allowedReturnToOrigins = [...new Set((input.allowedReturnToOrigins ?? []).map((origin) => {
178
+ const url = parseHttpUrl(origin, "allowedReturnToOrigins");
179
+ assertTransport(url, "allowedReturnToOrigins", environment);
180
+ if (url.origin !== url.href.replace(/\/$/, "")) {
181
+ throw new AuthError("CONFIG_INVALID", "allowedReturnToOrigins entries must be origins without paths");
182
+ }
183
+ return url.origin;
184
+ }))];
185
+ const accessTokenAudiences = [...new Set((input.accessTokenAudiences ?? [input.clientId]).map((audience) => required(audience, "accessTokenAudiences")))];
186
+ const accessTokenAuthorizedParties = [...new Set((input.accessTokenAuthorizedParties ?? [input.clientId]).map((party) => required(party, "accessTokenAuthorizedParties")))];
187
+ if ((input.accessTokenAudiences !== undefined &&
188
+ input.accessTokenAudiences.length === 0) ||
189
+ (input.accessTokenAuthorizedParties !== undefined &&
190
+ input.accessTokenAuthorizedParties.length === 0)) {
191
+ throw new AuthError("CONFIG_INVALID", "access-token audience and authorized-party arrays must not be empty");
192
+ }
193
+ if (accessTokenAudiences.length === 0 &&
194
+ accessTokenAuthorizedParties.length === 0) {
195
+ throw new AuthError("CONFIG_INVALID", "At least one access-token audience or authorized-party rule is required");
196
+ }
197
+ const clientAuthenticationMethod = input.clientAuthenticationMethod ?? "client_secret_basic";
198
+ if ((input.routes || environment === "production") &&
199
+ redirectUri.pathname !== routes.callbackPath) {
200
+ throw new AuthError("CONFIG_INVALID", "redirectUri pathname must match routes.callbackPath");
201
+ }
202
+ if (postLogoutRedirectUri &&
203
+ (publicOrigin || input.routes || environment === "production") &&
204
+ (postLogoutRedirectUri.pathname !== routes.signedOutPath ||
205
+ postLogoutRedirectUri.search)) {
206
+ throw new AuthError("CONFIG_INVALID", "postLogoutRedirectUri must exactly target routes.signedOutPath");
207
+ }
208
+ if (environment === "production" && !postLogoutRedirectUri) {
209
+ throw new AuthError("CONFIG_INVALID", "postLogoutRedirectUri is required in production");
210
+ }
211
+ return {
212
+ issuer,
213
+ clientId: required(input.clientId, "clientId"),
214
+ clientSecret: required(input.clientSecret, "clientSecret"),
215
+ ...(publicOrigin ? { publicOrigin } : {}),
216
+ redirectUri,
217
+ ...(postLogoutRedirectUri ? { postLogoutRedirectUri } : {}),
218
+ scopes,
219
+ environment,
220
+ sessionTtlSeconds,
221
+ allowedReturnToOrigins,
222
+ accessTokenAudiences,
223
+ accessTokenAuthorizedParties,
224
+ routes,
225
+ ui: normalizeAuthUi(input.ui),
226
+ clientAuthenticationMethod,
227
+ };
228
+ }
229
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { AuthErrorCode, AuthDiagnosticReason, AuthDiagnosticStage, SafeAuthErrorDetails, SafeAuthErrorFields } from "@dreadkn1ght123/auth-types";
2
+ export interface AuthErrorOptions {
3
+ cause?: unknown;
4
+ stage?: AuthDiagnosticStage;
5
+ reason?: AuthDiagnosticReason;
6
+ details?: Readonly<SafeAuthErrorDetails>;
7
+ safeDetails?: Readonly<SafeAuthErrorDetails>;
8
+ }
9
+ /** Extracts only audited scalar fields from supported error families. */
10
+ export declare function safeAuthErrorDetails(error: unknown): Readonly<SafeAuthErrorDetails>;
11
+ export declare function classifyAuthError(error: unknown): {
12
+ reason: AuthDiagnosticReason;
13
+ details: Readonly<SafeAuthErrorDetails>;
14
+ };
15
+ export declare function toSafeAuthErrorFields(error: unknown, correlationId?: string): Readonly<SafeAuthErrorFields>;
16
+ export declare class AuthError extends Error {
17
+ readonly code: AuthErrorCode;
18
+ readonly stage: AuthDiagnosticStage;
19
+ readonly reason: AuthDiagnosticReason;
20
+ readonly details: Readonly<SafeAuthErrorDetails>;
21
+ readonly safeDetails: Readonly<SafeAuthErrorDetails>;
22
+ readonly cause?: unknown;
23
+ constructor(code: AuthErrorCode, message: string, options?: AuthErrorOptions);
24
+ }
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;CAC9C;AAiDD,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAkDnF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG;IACjD,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;CACzC,CA+BA;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,aAAa,CAAC,EAAE,MAAM,GACrB,QAAQ,CAAC,mBAAmB,CAAC,CAc/B;AAED,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACjD,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACrD,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;CAcjF"}