@reckona/mreact-auth 0.0.97 → 0.0.98
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 +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +36 -8
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ export async function loader({ request }) {
|
|
|
48
48
|
- `requireRole()` and `requirePermission()` redirect or reject when the policy is not met.
|
|
49
49
|
- `tryRequireRole()` and `tryRequirePermission()` return a boolean policy result.
|
|
50
50
|
- `getSessionClaims()` reads session claims on both server and client hand-off paths.
|
|
51
|
+
- `runWithAuthRequest()` creates an explicit request-local claims scope for custom server handlers that call auth helpers outside the app router request lifecycle.
|
|
51
52
|
|
|
52
53
|
## Router Integration
|
|
53
54
|
|
|
@@ -59,3 +60,5 @@ By default, the hand-off includes only authorization claims: `roles` and
|
|
|
59
60
|
`permissions`. Use `configureAuth({ serializeClaims })` to expose additional
|
|
60
61
|
browser-safe fields, such as a public user id. Do not return server-only values
|
|
61
62
|
such as refresh tokens or provider secrets from the serializer.
|
|
63
|
+
|
|
64
|
+
Custom server code that calls `getCurrentSession()`, `refreshSession()`, or `revokeCurrentSession()` and then reads `getSessionClaims()` outside `renderAppRequest()` should wrap that request's work in `runWithAuthRequest()`. Server calls without an active request scope return `undefined` rather than falling back to a shared module-global claims value.
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface AuthSessionClaims {
|
|
|
7
7
|
permissions?: readonly string[] | undefined;
|
|
8
8
|
roles?: readonly string[] | undefined;
|
|
9
9
|
}
|
|
10
|
-
export interface AuthGuardOptions {
|
|
10
|
+
export interface AuthGuardOptions extends SessionCookieOptions {
|
|
11
11
|
forbiddenTo?: string | undefined;
|
|
12
12
|
mode?: AuthRequirementMode | undefined;
|
|
13
13
|
redirectTo?: string | undefined;
|
|
@@ -38,6 +38,7 @@ export type TryAuthResult<TData> = {
|
|
|
38
38
|
reason: "missing-permission" | "missing-role" | "missing-session";
|
|
39
39
|
};
|
|
40
40
|
export declare function configureAuth(config: AuthConfig): void;
|
|
41
|
+
export declare function runWithAuthRequest<T>(fn: () => T | Promise<T>): Promise<Awaited<T>>;
|
|
41
42
|
export declare function getCurrentSession<TData>(request: Request, store: SessionStore<TData>, options?: SessionCookieOptions): Promise<SessionRecord<TData> | undefined>;
|
|
42
43
|
export declare function requireSession<TData>(request: Request, store: SessionStore<TData>, options?: AuthGuardOptions): Promise<SessionRecord<TData>>;
|
|
43
44
|
export declare function requireRole<TData extends AuthSessionClaims>(request: Request, store: SessionStore<TData>, role: AuthRequirement, options?: AuthGuardOptions): Promise<SessionRecord<TData>>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,cAAc,IAAI,oBAAoB,EACtC,UAAU,EACV,aAAa,IAAI,mBAAmB,EACpC,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,oBAAoB,IAAI,cAAc,EACtC,UAAU,EACV,mBAAmB,IAAI,aAAa,GACrC,CAAC;AACF,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;AAElE,eAAO,MAAM,+BAA+B,0BAA0B,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5C,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,13 +16,17 @@ export function configureAuth(config) {
|
|
|
16
16
|
serializeClaims: config.serializeClaims ?? authConfig.serializeClaims,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
export async function runWithAuthRequest(fn) {
|
|
20
|
+
const storage = await authRequestStorage();
|
|
21
|
+
return await storage.run({}, fn);
|
|
22
|
+
}
|
|
19
23
|
export async function getCurrentSession(request, store, options = {}) {
|
|
20
24
|
const session = await getSession(request, store, options);
|
|
21
25
|
setSessionClaims(session?.data);
|
|
22
26
|
return session;
|
|
23
27
|
}
|
|
24
28
|
export async function requireSession(request, store, options = {}) {
|
|
25
|
-
const session = await getCurrentSession(request, store);
|
|
29
|
+
const session = await getCurrentSession(request, store, options);
|
|
26
30
|
if (session === undefined) {
|
|
27
31
|
redirect(authRedirectTo(options), { status: 303 });
|
|
28
32
|
}
|
|
@@ -91,7 +95,8 @@ export function getSessionClaims() {
|
|
|
91
95
|
return requestClaims;
|
|
92
96
|
}
|
|
93
97
|
if (typeof document === "undefined") {
|
|
94
|
-
|
|
98
|
+
warnMissingAuthRequestScope();
|
|
99
|
+
return undefined;
|
|
95
100
|
}
|
|
96
101
|
if (state.browserClaims === undefined) {
|
|
97
102
|
state.browserClaims = readClaimsFromDocument();
|
|
@@ -151,8 +156,22 @@ function setSessionClaims(data) {
|
|
|
151
156
|
requestState.claims = claims;
|
|
152
157
|
return;
|
|
153
158
|
}
|
|
159
|
+
if (typeof document === "undefined") {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
154
162
|
state.currentClaims = claims;
|
|
155
163
|
}
|
|
164
|
+
async function authRequestStorage() {
|
|
165
|
+
const state = authRuntimeState();
|
|
166
|
+
if (state.storage === undefined) {
|
|
167
|
+
const { AsyncLocalStorage } = await import("node:async_hooks");
|
|
168
|
+
state.storage = new AsyncLocalStorage();
|
|
169
|
+
}
|
|
170
|
+
return state.storage;
|
|
171
|
+
}
|
|
172
|
+
function warnMissingAuthRequestScope() {
|
|
173
|
+
console.warn("mreact auth session claims were read on the server without an active auth request scope. Wrap custom server work in runWithAuthRequest().");
|
|
174
|
+
}
|
|
156
175
|
function readClaimsFromDocument() {
|
|
157
176
|
const node = document.getElementById(__MREACT_AUTH_SESSION_SCRIPT_ID);
|
|
158
177
|
if (node?.textContent === undefined || node.textContent === "") {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createMemorySessionStore,\n createSession,\n destroySession as destroyRouterSession,\n getSession,\n rotateSession as rotateRouterSession,\n type SessionCookieOptions,\n type SessionRecord,\n type SessionStore,\n} from \"@reckona/mreact-router/session\";\nimport { getGlobalRuntimeState } from \"@reckona/mreact-reactive-core/runtime-state\";\nimport { redirect } from \"@reckona/mreact-router\";\n\nexport {\n createMemorySessionStore,\n createSession,\n destroyRouterSession as destroySession,\n getSession,\n rotateRouterSession as rotateSession,\n};\nexport type { SessionCookieOptions, SessionRecord, SessionStore };\n\nexport const __MREACT_AUTH_SESSION_SCRIPT_ID = \"__mreact_auth_session\";\n\nexport interface AuthSessionClaims {\n [claim: string]: unknown;\n permissions?: readonly string[] | undefined;\n roles?: readonly string[] | undefined;\n}\n\nexport interface AuthGuardOptions {\n forbiddenTo?: string | undefined;\n mode?: AuthRequirementMode | undefined;\n redirectTo?: string | undefined;\n}\n\nexport interface AuthConfig {\n forbiddenTo?: string | undefined;\n redirectTo?: string | undefined;\n serializeClaims?: AuthClaimsSerializer | undefined;\n}\n\ninterface ResolvedAuthConfig {\n forbiddenTo: string;\n redirectTo: string;\n serializeClaims: AuthClaimsSerializer;\n}\n\nexport type AuthRequirement = string | readonly string[];\nexport type AuthRequirementMode = \"all\" | \"any\";\nexport type AuthClaimsSerializer = (data: unknown) => AuthSessionClaims | undefined;\n\nexport interface AuthorizationPolicy {\n permissions?: readonly string[] | undefined;\n roles?: readonly string[] | undefined;\n}\n\nexport type AuthorizationResult =\n | {\n authorized: true;\n }\n | {\n authorized: false;\n reason: \"missing-permission\" | \"missing-role\";\n };\n\nexport type TryAuthResult<TData> =\n | {\n authorized: true;\n session: SessionRecord<TData>;\n }\n | {\n authorized: false;\n reason: \"missing-permission\" | \"missing-role\" | \"missing-session\";\n };\n\nconst authRuntimeStateKey = \"__mreactAuthRuntimeState\";\n\ninterface AuthRuntimeRequestState {\n claims?: AuthSessionClaims | undefined;\n}\n\ninterface AuthRuntimeState {\n browserClaims?: AuthSessionClaims | undefined;\n currentClaims?: AuthSessionClaims | undefined;\n storage?:\n | {\n getStore(): AuthRuntimeRequestState | undefined;\n }\n | undefined;\n}\n\nlet authConfig: ResolvedAuthConfig = {\n forbiddenTo: \"/forbidden\",\n redirectTo: \"/login\",\n serializeClaims: defaultSerializeSessionClaims,\n};\n\nexport function configureAuth(config: AuthConfig): void {\n authConfig = {\n forbiddenTo: config.forbiddenTo ?? authConfig.forbiddenTo,\n redirectTo: config.redirectTo ?? authConfig.redirectTo,\n serializeClaims: config.serializeClaims ?? authConfig.serializeClaims,\n };\n}\n\nexport async function getCurrentSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const session = await getSession(request, store, options);\n\n setSessionClaims(session?.data);\n\n return session;\n}\n\nexport async function requireSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await getCurrentSession(request, store);\n\n if (session === undefined) {\n redirect(authRedirectTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function requireRole<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n role: AuthRequirement,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await requireSession(request, store, options);\n const result = authorizeRequirement(session.data.roles, role, \"missing-role\", options.mode);\n\n if (!result.authorized) {\n redirect(authForbiddenTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function requirePermission<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n permission: AuthRequirement,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await requireSession(request, store, options);\n const result = authorizeRequirement(\n session.data.permissions,\n permission,\n \"missing-permission\",\n options.mode,\n );\n\n if (!result.authorized) {\n redirect(authForbiddenTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function tryRequireRole<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n role: AuthRequirement,\n options: Pick<AuthGuardOptions, \"mode\"> = {},\n): Promise<TryAuthResult<TData>> {\n const session = await getCurrentSession(request, store);\n\n if (session === undefined) {\n return { authorized: false, reason: \"missing-session\" };\n }\n\n const result = authorizeRequirement(session.data.roles, role, \"missing-role\", options.mode);\n\n return result.authorized ? { authorized: true, session } : result;\n}\n\nexport async function tryRequirePermission<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n permission: AuthRequirement,\n options: Pick<AuthGuardOptions, \"mode\"> = {},\n): Promise<TryAuthResult<TData>> {\n const session = await getCurrentSession(request, store);\n\n if (session === undefined) {\n return { authorized: false, reason: \"missing-session\" };\n }\n\n const result = authorizeRequirement(\n session.data.permissions,\n permission,\n \"missing-permission\",\n options.mode,\n );\n\n return result.authorized ? { authorized: true, session } : result;\n}\n\nexport function authorizeSession<TData extends AuthSessionClaims>(\n data: TData,\n policy: AuthorizationPolicy,\n): AuthorizationResult {\n if (!hasAll(data.roles, policy.roles)) {\n return {\n authorized: false,\n reason: \"missing-role\",\n };\n }\n\n if (!hasAll(data.permissions, policy.permissions)) {\n return {\n authorized: false,\n reason: \"missing-permission\",\n };\n }\n\n return { authorized: true };\n}\n\nexport async function refreshSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const session = await rotateRouterSession(request, response, store, options);\n\n setSessionClaims(session?.data);\n\n return session;\n}\n\nexport async function revokeCurrentSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<void> {\n await destroyRouterSession(request, response, store, options);\n setSessionClaims(undefined);\n}\n\nexport function getSessionClaims<TData extends AuthSessionClaims = AuthSessionClaims>():\n | TData\n | undefined {\n const state = authRuntimeState();\n const requestClaims = state.storage?.getStore()?.claims;\n\n if (requestClaims !== undefined) {\n return requestClaims as TData;\n }\n\n if (typeof document === \"undefined\") {\n return state.currentClaims as TData | undefined;\n }\n\n if (state.browserClaims === undefined) {\n state.browserClaims = readClaimsFromDocument();\n }\n\n return state.browserClaims as TData | undefined;\n}\n\nexport function __resetAuthForTesting(): void {\n authConfig = {\n forbiddenTo: \"/forbidden\",\n redirectTo: \"/login\",\n serializeClaims: defaultSerializeSessionClaims,\n };\n const state = authRuntimeState();\n state.browserClaims = undefined;\n state.currentClaims = undefined;\n const requestState = state.storage?.getStore();\n if (requestState !== undefined) {\n requestState.claims = undefined;\n }\n}\n\nfunction authorizeRequirement(\n available: readonly string[] | undefined,\n requirement: AuthRequirement,\n reason: \"missing-permission\" | \"missing-role\",\n mode: AuthRequirementMode = \"any\",\n): AuthorizationResult {\n const required = Array.isArray(requirement) ? requirement : [requirement];\n const authorized = mode === \"all\" ? hasAll(available, required) : hasAny(available, required);\n\n return authorized ? { authorized: true } : { authorized: false, reason };\n}\n\nfunction authRedirectTo(options: AuthGuardOptions): string {\n return options.redirectTo ?? authConfig.redirectTo;\n}\n\nfunction authForbiddenTo(options: AuthGuardOptions): string {\n return options.forbiddenTo ?? authConfig.forbiddenTo;\n}\n\nfunction hasAll(\n available: readonly string[] | undefined,\n required: readonly string[] | undefined,\n): boolean {\n if (required === undefined || required.length === 0) {\n return true;\n }\n\n if (available === undefined || available.length === 0) {\n return false;\n }\n\n const values = new Set(available);\n\n return required.every((value) => values.has(value));\n}\n\nfunction hasAny(\n available: readonly string[] | undefined,\n required: readonly string[] | undefined,\n): boolean {\n if (required === undefined || required.length === 0) {\n return true;\n }\n\n if (available === undefined || available.length === 0) {\n return false;\n }\n\n const values = new Set(available);\n\n return required.some((value) => values.has(value));\n}\n\nfunction setSessionClaims(data: unknown): void {\n const claims = normalizeSessionClaims(authConfig.serializeClaims(data));\n const state = authRuntimeState();\n const requestState = state.storage?.getStore();\n\n if (requestState !== undefined) {\n requestState.claims = claims;\n return;\n }\n\n state.currentClaims = claims;\n}\n\nfunction readClaimsFromDocument(): AuthSessionClaims | undefined {\n const node = document.getElementById(__MREACT_AUTH_SESSION_SCRIPT_ID);\n\n if (node?.textContent === undefined || node.textContent === \"\") {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(node.textContent) as unknown;\n return normalizeSessionClaims(parsed);\n } catch {\n return undefined;\n }\n}\n\nfunction defaultSerializeSessionClaims(data: unknown): AuthSessionClaims | undefined {\n if (typeof data !== \"object\" || data === null) {\n return undefined;\n }\n\n const claims = data as AuthSessionClaims;\n const roles = normalizeStringArray(claims.roles);\n const permissions = normalizeStringArray(claims.permissions);\n\n if (\n (claims.roles !== undefined && roles === undefined) ||\n (claims.permissions !== undefined && permissions === undefined)\n ) {\n return undefined;\n }\n\n const safeClaims: AuthSessionClaims = {};\n\n if (permissions !== undefined) {\n safeClaims.permissions = permissions;\n }\n\n if (roles !== undefined) {\n safeClaims.roles = roles;\n }\n\n return Object.keys(safeClaims).length === 0 ? undefined : safeClaims;\n}\n\nfunction normalizeSessionClaims(value: unknown): AuthSessionClaims | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n\n const claims = value as AuthSessionClaims;\n const roles = normalizeStringArray(claims.roles);\n const permissions = normalizeStringArray(claims.permissions);\n\n if (\n (claims.roles !== undefined && roles === undefined) ||\n (claims.permissions !== undefined && permissions === undefined)\n ) {\n return undefined;\n }\n\n return {\n ...claims,\n ...(permissions === undefined ? {} : { permissions }),\n ...(roles === undefined ? {} : { roles }),\n };\n}\n\nfunction normalizeStringArray(value: unknown): readonly string[] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return Array.isArray(value) && value.every((item) => typeof item === \"string\")\n ? value\n : undefined;\n}\n\nfunction authRuntimeState(): AuthRuntimeState {\n return getGlobalRuntimeState(authRuntimeStateKey, () => ({}));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createMemorySessionStore,\n createSession,\n destroySession as destroyRouterSession,\n getSession,\n rotateSession as rotateRouterSession,\n type SessionCookieOptions,\n type SessionRecord,\n type SessionStore,\n} from \"@reckona/mreact-router/session\";\nimport { getGlobalRuntimeState } from \"@reckona/mreact-reactive-core/runtime-state\";\nimport { redirect } from \"@reckona/mreact-router\";\n\nexport {\n createMemorySessionStore,\n createSession,\n destroyRouterSession as destroySession,\n getSession,\n rotateRouterSession as rotateSession,\n};\nexport type { SessionCookieOptions, SessionRecord, SessionStore };\n\nexport const __MREACT_AUTH_SESSION_SCRIPT_ID = \"__mreact_auth_session\";\n\nexport interface AuthSessionClaims {\n [claim: string]: unknown;\n permissions?: readonly string[] | undefined;\n roles?: readonly string[] | undefined;\n}\n\nexport interface AuthGuardOptions extends SessionCookieOptions {\n forbiddenTo?: string | undefined;\n mode?: AuthRequirementMode | undefined;\n redirectTo?: string | undefined;\n}\n\nexport interface AuthConfig {\n forbiddenTo?: string | undefined;\n redirectTo?: string | undefined;\n serializeClaims?: AuthClaimsSerializer | undefined;\n}\n\ninterface ResolvedAuthConfig {\n forbiddenTo: string;\n redirectTo: string;\n serializeClaims: AuthClaimsSerializer;\n}\n\nexport type AuthRequirement = string | readonly string[];\nexport type AuthRequirementMode = \"all\" | \"any\";\nexport type AuthClaimsSerializer = (data: unknown) => AuthSessionClaims | undefined;\n\nexport interface AuthorizationPolicy {\n permissions?: readonly string[] | undefined;\n roles?: readonly string[] | undefined;\n}\n\nexport type AuthorizationResult =\n | {\n authorized: true;\n }\n | {\n authorized: false;\n reason: \"missing-permission\" | \"missing-role\";\n };\n\nexport type TryAuthResult<TData> =\n | {\n authorized: true;\n session: SessionRecord<TData>;\n }\n | {\n authorized: false;\n reason: \"missing-permission\" | \"missing-role\" | \"missing-session\";\n };\n\nconst authRuntimeStateKey = \"__mreactAuthRuntimeState\";\n\ninterface AuthRuntimeRequestState {\n claims?: AuthSessionClaims | undefined;\n}\n\ninterface AuthRequestStorage {\n getStore(): AuthRuntimeRequestState | undefined;\n run<T>(store: AuthRuntimeRequestState, callback: () => T): T;\n}\n\ninterface AuthRuntimeState {\n browserClaims?: AuthSessionClaims | undefined;\n currentClaims?: AuthSessionClaims | undefined;\n storage?: AuthRequestStorage | undefined;\n}\n\nlet authConfig: ResolvedAuthConfig = {\n forbiddenTo: \"/forbidden\",\n redirectTo: \"/login\",\n serializeClaims: defaultSerializeSessionClaims,\n};\n\nexport function configureAuth(config: AuthConfig): void {\n authConfig = {\n forbiddenTo: config.forbiddenTo ?? authConfig.forbiddenTo,\n redirectTo: config.redirectTo ?? authConfig.redirectTo,\n serializeClaims: config.serializeClaims ?? authConfig.serializeClaims,\n };\n}\n\nexport async function runWithAuthRequest<T>(fn: () => T | Promise<T>): Promise<Awaited<T>> {\n const storage = await authRequestStorage();\n\n return await storage.run({}, fn);\n}\n\nexport async function getCurrentSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const session = await getSession(request, store, options);\n\n setSessionClaims(session?.data);\n\n return session;\n}\n\nexport async function requireSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await getCurrentSession(request, store, options);\n\n if (session === undefined) {\n redirect(authRedirectTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function requireRole<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n role: AuthRequirement,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await requireSession(request, store, options);\n const result = authorizeRequirement(session.data.roles, role, \"missing-role\", options.mode);\n\n if (!result.authorized) {\n redirect(authForbiddenTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function requirePermission<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n permission: AuthRequirement,\n options: AuthGuardOptions = {},\n): Promise<SessionRecord<TData>> {\n const session = await requireSession(request, store, options);\n const result = authorizeRequirement(\n session.data.permissions,\n permission,\n \"missing-permission\",\n options.mode,\n );\n\n if (!result.authorized) {\n redirect(authForbiddenTo(options), { status: 303 });\n }\n\n return session;\n}\n\nexport async function tryRequireRole<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n role: AuthRequirement,\n options: Pick<AuthGuardOptions, \"mode\"> = {},\n): Promise<TryAuthResult<TData>> {\n const session = await getCurrentSession(request, store);\n\n if (session === undefined) {\n return { authorized: false, reason: \"missing-session\" };\n }\n\n const result = authorizeRequirement(session.data.roles, role, \"missing-role\", options.mode);\n\n return result.authorized ? { authorized: true, session } : result;\n}\n\nexport async function tryRequirePermission<TData extends AuthSessionClaims>(\n request: Request,\n store: SessionStore<TData>,\n permission: AuthRequirement,\n options: Pick<AuthGuardOptions, \"mode\"> = {},\n): Promise<TryAuthResult<TData>> {\n const session = await getCurrentSession(request, store);\n\n if (session === undefined) {\n return { authorized: false, reason: \"missing-session\" };\n }\n\n const result = authorizeRequirement(\n session.data.permissions,\n permission,\n \"missing-permission\",\n options.mode,\n );\n\n return result.authorized ? { authorized: true, session } : result;\n}\n\nexport function authorizeSession<TData extends AuthSessionClaims>(\n data: TData,\n policy: AuthorizationPolicy,\n): AuthorizationResult {\n if (!hasAll(data.roles, policy.roles)) {\n return {\n authorized: false,\n reason: \"missing-role\",\n };\n }\n\n if (!hasAll(data.permissions, policy.permissions)) {\n return {\n authorized: false,\n reason: \"missing-permission\",\n };\n }\n\n return { authorized: true };\n}\n\nexport async function refreshSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const session = await rotateRouterSession(request, response, store, options);\n\n setSessionClaims(session?.data);\n\n return session;\n}\n\nexport async function revokeCurrentSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<void> {\n await destroyRouterSession(request, response, store, options);\n setSessionClaims(undefined);\n}\n\nexport function getSessionClaims<TData extends AuthSessionClaims = AuthSessionClaims>():\n | TData\n | undefined {\n const state = authRuntimeState();\n const requestClaims = state.storage?.getStore()?.claims;\n\n if (requestClaims !== undefined) {\n return requestClaims as TData;\n }\n\n if (typeof document === \"undefined\") {\n warnMissingAuthRequestScope();\n return undefined;\n }\n\n if (state.browserClaims === undefined) {\n state.browserClaims = readClaimsFromDocument();\n }\n\n return state.browserClaims as TData | undefined;\n}\n\nexport function __resetAuthForTesting(): void {\n authConfig = {\n forbiddenTo: \"/forbidden\",\n redirectTo: \"/login\",\n serializeClaims: defaultSerializeSessionClaims,\n };\n const state = authRuntimeState();\n state.browserClaims = undefined;\n state.currentClaims = undefined;\n const requestState = state.storage?.getStore();\n if (requestState !== undefined) {\n requestState.claims = undefined;\n }\n}\n\nfunction authorizeRequirement(\n available: readonly string[] | undefined,\n requirement: AuthRequirement,\n reason: \"missing-permission\" | \"missing-role\",\n mode: AuthRequirementMode = \"any\",\n): AuthorizationResult {\n const required = Array.isArray(requirement) ? requirement : [requirement];\n const authorized = mode === \"all\" ? hasAll(available, required) : hasAny(available, required);\n\n return authorized ? { authorized: true } : { authorized: false, reason };\n}\n\nfunction authRedirectTo(options: AuthGuardOptions): string {\n return options.redirectTo ?? authConfig.redirectTo;\n}\n\nfunction authForbiddenTo(options: AuthGuardOptions): string {\n return options.forbiddenTo ?? authConfig.forbiddenTo;\n}\n\nfunction hasAll(\n available: readonly string[] | undefined,\n required: readonly string[] | undefined,\n): boolean {\n if (required === undefined || required.length === 0) {\n return true;\n }\n\n if (available === undefined || available.length === 0) {\n return false;\n }\n\n const values = new Set(available);\n\n return required.every((value) => values.has(value));\n}\n\nfunction hasAny(\n available: readonly string[] | undefined,\n required: readonly string[] | undefined,\n): boolean {\n if (required === undefined || required.length === 0) {\n return true;\n }\n\n if (available === undefined || available.length === 0) {\n return false;\n }\n\n const values = new Set(available);\n\n return required.some((value) => values.has(value));\n}\n\nfunction setSessionClaims(data: unknown): void {\n const claims = normalizeSessionClaims(authConfig.serializeClaims(data));\n const state = authRuntimeState();\n const requestState = state.storage?.getStore();\n\n if (requestState !== undefined) {\n requestState.claims = claims;\n return;\n }\n\n if (typeof document === \"undefined\") {\n return;\n }\n\n state.currentClaims = claims;\n}\n\nasync function authRequestStorage(): Promise<AuthRequestStorage> {\n const state = authRuntimeState();\n if (state.storage === undefined) {\n const { AsyncLocalStorage } = await import(\"node:async_hooks\");\n state.storage = new AsyncLocalStorage<AuthRuntimeRequestState>();\n }\n\n return state.storage;\n}\n\nfunction warnMissingAuthRequestScope(): void {\n console.warn(\n \"mreact auth session claims were read on the server without an active auth request scope. Wrap custom server work in runWithAuthRequest().\",\n );\n}\n\nfunction readClaimsFromDocument(): AuthSessionClaims | undefined {\n const node = document.getElementById(__MREACT_AUTH_SESSION_SCRIPT_ID);\n\n if (node?.textContent === undefined || node.textContent === \"\") {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(node.textContent) as unknown;\n return normalizeSessionClaims(parsed);\n } catch {\n return undefined;\n }\n}\n\nfunction defaultSerializeSessionClaims(data: unknown): AuthSessionClaims | undefined {\n if (typeof data !== \"object\" || data === null) {\n return undefined;\n }\n\n const claims = data as AuthSessionClaims;\n const roles = normalizeStringArray(claims.roles);\n const permissions = normalizeStringArray(claims.permissions);\n\n if (\n (claims.roles !== undefined && roles === undefined) ||\n (claims.permissions !== undefined && permissions === undefined)\n ) {\n return undefined;\n }\n\n const safeClaims: AuthSessionClaims = {};\n\n if (permissions !== undefined) {\n safeClaims.permissions = permissions;\n }\n\n if (roles !== undefined) {\n safeClaims.roles = roles;\n }\n\n return Object.keys(safeClaims).length === 0 ? undefined : safeClaims;\n}\n\nfunction normalizeSessionClaims(value: unknown): AuthSessionClaims | undefined {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n\n const claims = value as AuthSessionClaims;\n const roles = normalizeStringArray(claims.roles);\n const permissions = normalizeStringArray(claims.permissions);\n\n if (\n (claims.roles !== undefined && roles === undefined) ||\n (claims.permissions !== undefined && permissions === undefined)\n ) {\n return undefined;\n }\n\n return {\n ...claims,\n ...(permissions === undefined ? {} : { permissions }),\n ...(roles === undefined ? {} : { roles }),\n };\n}\n\nfunction normalizeStringArray(value: unknown): readonly string[] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return Array.isArray(value) && value.every((item) => typeof item === \"string\")\n ? value\n : undefined;\n}\n\nfunction authRuntimeState(): AuthRuntimeState {\n return getGlobalRuntimeState(authRuntimeStateKey, () => ({}));\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reckona/mreact-auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.98",
|
|
4
4
|
"description": "Session and authorization helpers for mreact app router applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@reckona/mreact-
|
|
45
|
-
"@reckona/mreact-
|
|
44
|
+
"@reckona/mreact-router": "0.0.98",
|
|
45
|
+
"@reckona/mreact-reactive-core": "0.0.98"
|
|
46
46
|
}
|
|
47
47
|
}
|
package/src/index.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface AuthSessionClaims {
|
|
|
28
28
|
roles?: readonly string[] | undefined;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export interface AuthGuardOptions {
|
|
31
|
+
export interface AuthGuardOptions extends SessionCookieOptions {
|
|
32
32
|
forbiddenTo?: string | undefined;
|
|
33
33
|
mode?: AuthRequirementMode | undefined;
|
|
34
34
|
redirectTo?: string | undefined;
|
|
@@ -80,14 +80,15 @@ interface AuthRuntimeRequestState {
|
|
|
80
80
|
claims?: AuthSessionClaims | undefined;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
interface AuthRequestStorage {
|
|
84
|
+
getStore(): AuthRuntimeRequestState | undefined;
|
|
85
|
+
run<T>(store: AuthRuntimeRequestState, callback: () => T): T;
|
|
86
|
+
}
|
|
87
|
+
|
|
83
88
|
interface AuthRuntimeState {
|
|
84
89
|
browserClaims?: AuthSessionClaims | undefined;
|
|
85
90
|
currentClaims?: AuthSessionClaims | undefined;
|
|
86
|
-
storage?:
|
|
87
|
-
| {
|
|
88
|
-
getStore(): AuthRuntimeRequestState | undefined;
|
|
89
|
-
}
|
|
90
|
-
| undefined;
|
|
91
|
+
storage?: AuthRequestStorage | undefined;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
let authConfig: ResolvedAuthConfig = {
|
|
@@ -104,6 +105,12 @@ export function configureAuth(config: AuthConfig): void {
|
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
export async function runWithAuthRequest<T>(fn: () => T | Promise<T>): Promise<Awaited<T>> {
|
|
109
|
+
const storage = await authRequestStorage();
|
|
110
|
+
|
|
111
|
+
return await storage.run({}, fn);
|
|
112
|
+
}
|
|
113
|
+
|
|
107
114
|
export async function getCurrentSession<TData>(
|
|
108
115
|
request: Request,
|
|
109
116
|
store: SessionStore<TData>,
|
|
@@ -121,7 +128,7 @@ export async function requireSession<TData>(
|
|
|
121
128
|
store: SessionStore<TData>,
|
|
122
129
|
options: AuthGuardOptions = {},
|
|
123
130
|
): Promise<SessionRecord<TData>> {
|
|
124
|
-
const session = await getCurrentSession(request, store);
|
|
131
|
+
const session = await getCurrentSession(request, store, options);
|
|
125
132
|
|
|
126
133
|
if (session === undefined) {
|
|
127
134
|
redirect(authRedirectTo(options), { status: 303 });
|
|
@@ -261,7 +268,8 @@ export function getSessionClaims<TData extends AuthSessionClaims = AuthSessionCl
|
|
|
261
268
|
}
|
|
262
269
|
|
|
263
270
|
if (typeof document === "undefined") {
|
|
264
|
-
|
|
271
|
+
warnMissingAuthRequestScope();
|
|
272
|
+
return undefined;
|
|
265
273
|
}
|
|
266
274
|
|
|
267
275
|
if (state.browserClaims === undefined) {
|
|
@@ -350,9 +358,29 @@ function setSessionClaims(data: unknown): void {
|
|
|
350
358
|
return;
|
|
351
359
|
}
|
|
352
360
|
|
|
361
|
+
if (typeof document === "undefined") {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
353
365
|
state.currentClaims = claims;
|
|
354
366
|
}
|
|
355
367
|
|
|
368
|
+
async function authRequestStorage(): Promise<AuthRequestStorage> {
|
|
369
|
+
const state = authRuntimeState();
|
|
370
|
+
if (state.storage === undefined) {
|
|
371
|
+
const { AsyncLocalStorage } = await import("node:async_hooks");
|
|
372
|
+
state.storage = new AsyncLocalStorage<AuthRuntimeRequestState>();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return state.storage;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function warnMissingAuthRequestScope(): void {
|
|
379
|
+
console.warn(
|
|
380
|
+
"mreact auth session claims were read on the server without an active auth request scope. Wrap custom server work in runWithAuthRequest().",
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
356
384
|
function readClaimsFromDocument(): AuthSessionClaims | undefined {
|
|
357
385
|
const node = document.getElementById(__MREACT_AUTH_SESSION_SCRIPT_ID);
|
|
358
386
|
|