nucleus-core-ts 0.9.700 → 0.9.702
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.
|
@@ -9,6 +9,26 @@ interface MagicLinkToken {
|
|
|
9
9
|
tokenHash: string;
|
|
10
10
|
expiresAt: Date;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Build the Set-Cookie for the short-lived, single-use OAuth `state` CSRF cookie.
|
|
14
|
+
*
|
|
15
|
+
* Path is ALWAYS `/`, NOT the backend's internal OAuth `basePath`. The cookie is
|
|
16
|
+
* set when the browser starts the flow and must be re-sent on the provider's
|
|
17
|
+
* callback, but the EXTERNAL callback path is decided by the deployment's
|
|
18
|
+
* ingress/proxy (commonly `/api/auth/oauth/<provider>/callback` or
|
|
19
|
+
* `/oauth/<provider>`) and routinely differs from the backend-internal basePath
|
|
20
|
+
* (`/auth/oauth`). A basePath-scoped cookie then silently fails the browser's
|
|
21
|
+
* path match on the callback, the cookie is never attached, and the M6 CSRF
|
|
22
|
+
* check rejects the login with `invalid_state`. `Path=/` makes the cookie
|
|
23
|
+
* round-trip regardless of how the edge remaps the OAuth routes. `SameSite=Lax`
|
|
24
|
+
* is required so the top-level GET redirect back from the IdP still carries it;
|
|
25
|
+
* the cookie stays HttpOnly + single-use, so the wider path does not weaken CSRF.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildOAuthStateCookie(value: string, opts: {
|
|
28
|
+
maxAge: number;
|
|
29
|
+
secure?: boolean;
|
|
30
|
+
domain?: string;
|
|
31
|
+
}): string;
|
|
12
32
|
export declare function createOAuthRoutes(config: AuthRouteConfig, oauthService: OAuthService, signAccessToken: (userId: string, roles?: string[], claims?: string[], tenant?: string) => string, signRefreshToken: (userId: string) => string, createSession: (params: CreateSessionParams) => Promise<string>, saveSessionToDb?: (sessionId: string, params: CreateSessionParams, schemaName?: string) => Promise<{
|
|
13
33
|
requiresApproval?: boolean;
|
|
14
34
|
sessionId?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -16,6 +16,16 @@ export type RedisLike = {
|
|
|
16
16
|
* Redis-backed store (P3) — works across instances and survives restarts. State
|
|
17
17
|
* is single-use: consume() deletes the key before returning, so a replayed
|
|
18
18
|
* callback (or a double-submit) finds nothing.
|
|
19
|
+
*
|
|
20
|
+
* IMPORTANT: store the payload as an OBJECT and let the store layer handle
|
|
21
|
+
* serialization. Do NOT JSON.stringify here / JSON.parse on read. The RedisLike
|
|
22
|
+
* implementations already serialize internally — the direct ioredis store
|
|
23
|
+
* `JSON.stringify`s on write and `JSON.parse`s on read, and the Dapr store's
|
|
24
|
+
* `state.get` AUTO-PARSES JSON strings back into objects. A pre-stringify here
|
|
25
|
+
* therefore round-trips fine on the direct store (double-encode cancels out) but
|
|
26
|
+
* breaks on Dapr: `read` returns a parsed OBJECT, so a second `JSON.parse(object)`
|
|
27
|
+
* throws ("[object Object]") and consume returns null → every OAuth login fails
|
|
28
|
+
* with `invalid_state`. Passing the object through works on BOTH backends.
|
|
19
29
|
*/
|
|
20
30
|
export declare const createRedisOAuthStateStore: (redis: RedisLike) => OAuthStateStore;
|
|
21
31
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nucleus-core-ts",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.702",
|
|
4
4
|
"description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
|
|
5
5
|
"author": "Hidayet Can \u00d6zcan <hidayetcan@gmail.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|