@seamless-auth/core 0.1.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.
Files changed (64) hide show
  1. package/LICENSE +79 -0
  2. package/LICENSE.md +26 -0
  3. package/README.md +141 -0
  4. package/dist/authFetch.d.ts +8 -0
  5. package/dist/authFetch.d.ts.map +1 -0
  6. package/dist/authFetch.js +13 -0
  7. package/dist/authFetch.js.map +1 -0
  8. package/dist/createServiceToken.d.ts +10 -0
  9. package/dist/createServiceToken.d.ts.map +1 -0
  10. package/dist/createServiceToken.js +15 -0
  11. package/dist/createServiceToken.js.map +1 -0
  12. package/dist/ensureCookies.d.ts +42 -0
  13. package/dist/ensureCookies.d.ts.map +1 -0
  14. package/dist/ensureCookies.js +116 -0
  15. package/dist/ensureCookies.js.map +1 -0
  16. package/dist/getSeamlessUser.d.ts +7 -0
  17. package/dist/getSeamlessUser.d.ts.map +1 -0
  18. package/dist/getSeamlessUser.js +19 -0
  19. package/dist/getSeamlessUser.js.map +1 -0
  20. package/dist/handlers/finishLogin.d.ts +24 -0
  21. package/dist/handlers/finishLogin.d.ts.map +1 -0
  22. package/dist/handlers/finishLogin.js +48 -0
  23. package/dist/handlers/finishLogin.js.map +1 -0
  24. package/dist/handlers/finishRegister.d.ts +23 -0
  25. package/dist/handlers/finishRegister.d.ts.map +1 -0
  26. package/dist/handlers/finishRegister.js +47 -0
  27. package/dist/handlers/finishRegister.js.map +1 -0
  28. package/dist/handlers/login.d.ts +21 -0
  29. package/dist/handlers/login.d.ts.map +1 -0
  30. package/dist/handlers/login.js +34 -0
  31. package/dist/handlers/login.js.map +1 -0
  32. package/dist/handlers/logout.d.ts +12 -0
  33. package/dist/handlers/logout.d.ts.map +1 -0
  34. package/dist/handlers/logout.js +15 -0
  35. package/dist/handlers/logout.js.map +1 -0
  36. package/dist/handlers/me.d.ts +16 -0
  37. package/dist/handlers/me.d.ts.map +1 -0
  38. package/dist/handlers/me.js +25 -0
  39. package/dist/handlers/me.js.map +1 -0
  40. package/dist/handlers/register.d.ts +22 -0
  41. package/dist/handlers/register.d.ts.map +1 -0
  42. package/dist/handlers/register.js +27 -0
  43. package/dist/handlers/register.js.map +1 -0
  44. package/dist/index.d.ts +13 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +13 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/refreshAccessToken.d.ts +17 -0
  49. package/dist/refreshAccessToken.d.ts.map +1 -0
  50. package/dist/refreshAccessToken.js +26 -0
  51. package/dist/refreshAccessToken.js.map +1 -0
  52. package/dist/verifyCookieJwt.d.ts +3 -0
  53. package/dist/verifyCookieJwt.d.ts.map +1 -0
  54. package/dist/verifyCookieJwt.js +13 -0
  55. package/dist/verifyCookieJwt.js.map +1 -0
  56. package/dist/verifyRefreshCookie.d.ts +7 -0
  57. package/dist/verifyRefreshCookie.d.ts.map +1 -0
  58. package/dist/verifyRefreshCookie.js +12 -0
  59. package/dist/verifyRefreshCookie.js.map +1 -0
  60. package/dist/verifySignedAuthResponse.d.ts +2 -0
  61. package/dist/verifySignedAuthResponse.d.ts.map +1 -0
  62. package/dist/verifySignedAuthResponse.js +17 -0
  63. package/dist/verifySignedAuthResponse.js.map +1 -0
  64. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,79 @@
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc.
5
+ <https://fsf.org/>
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ This license is identical to the GNU General Public License, except that it also
10
+ ensures that software running as a network service makes its source code
11
+ available to users.
12
+
13
+ ---
14
+
15
+ TERMS AND CONDITIONS
16
+
17
+ 0. Definitions.
18
+
19
+ “This License” refers to version 3 of the GNU Affero General Public License.
20
+
21
+ “Copyright” also means copyright-like laws that apply to other kinds of works,
22
+ such as semiconductor masks.
23
+
24
+ The “Program” refers to any copyrightable work licensed under this License.
25
+ Each licensee is addressed as “you”.
26
+
27
+ To “modify” a work means to copy from or adapt all or part of the work in a
28
+ fashion requiring copyright permission, other than the making of an exact copy.
29
+
30
+ To “propagate” a work means to do anything with it that, without permission,
31
+ would make you directly or secondarily liable for infringement under applicable
32
+ copyright law, except executing it on a computer or modifying a private copy.
33
+
34
+ To “convey” a work means any kind of propagation that enables other parties to
35
+ make or receive copies.
36
+
37
+ An interactive user interface displays “Appropriate Legal Notices” to the extent
38
+ that it includes a convenient and prominently visible feature that displays an
39
+ appropriate copyright notice, and tells the user that there is no warranty for
40
+ the work (except to the extent that warranties are provided), that licensees may
41
+ convey the work under this License, and how to view a copy of this License.
42
+
43
+ ---
44
+
45
+ 13. Remote Network Interaction; Use with the GNU General Public License.
46
+
47
+ Notwithstanding any other provision of this License, if you modify the Program,
48
+ your modified version must prominently offer all users interacting with it
49
+ remotely through a computer network an opportunity to receive the Corresponding
50
+ Source of your version by providing access to the Corresponding Source from a
51
+ network server at no charge, through some standard or customary means of
52
+ facilitating copying of software.
53
+
54
+ ---
55
+
56
+ 15. Disclaimer of Warranty.
57
+
58
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
59
+ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
60
+ PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
61
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
62
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
63
+
64
+ ---
65
+
66
+ 16. Limitation of Liability.
67
+
68
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
69
+ COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
70
+ PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
71
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
72
+ THE PROGRAM.
73
+
74
+ ---
75
+
76
+ END OF TERMS AND CONDITIONS
77
+
78
+ You should have received a copy of the GNU Affero General Public License along
79
+ with this program. If not, see <https://www.gnu.org/licenses/>.
package/LICENSE.md ADDED
@@ -0,0 +1,26 @@
1
+ # License
2
+
3
+ Seamless Auth Server - Core ("@seamless-auth/core") is licensed under the **GNU Affero General Public License v3.0 (AGPL-3.0-only)**.
4
+
5
+ - SPDX: `AGPL-3.0-only`
6
+
7
+ ## What this means (high level)
8
+
9
+ - You are free to **use**, **modify**, and **self-host** this software.
10
+ - If you **modify** this software and **run it as a network service** (for example, hosting it for others to use), you must **make the complete corresponding source code of your modified version available** to users of that service, under the AGPL.
11
+
12
+ This summary is not legal advice and does not replace the license text.
13
+
14
+ ## Full license text
15
+
16
+ The full license text is available here:
17
+
18
+ - https://www.gnu.org/licenses/agpl-3.0.html
19
+
20
+ You should include a copy of the AGPLv3 license in your distribution. If this repository does not contain the full license text yet, add it as `LICENSE` or `LICENSE.txt` (recommended), and keep this `LICENSE.md` as the human-friendly summary.
21
+
22
+ ## Commercial licensing
23
+
24
+ If you would like to embed Seamless Auth API into a proprietary product, redistribute it under different terms, or offer it as a managed service without AGPL obligations, commercial licensing may be available.
25
+
26
+ Contact: support@seamlessauth.com
package/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # @seamless-auth/core
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@seamless-auth/core.svg)](https://www.npmjs.com/package/@seamless-auth/core)
4
+ [![license](https://img.shields.io/badge/license-AGPL--3.0-blue)](#license "License")
5
+
6
+ ### Seamless Auth – Core
7
+
8
+ `@seamless-auth/core` contains the **framework-agnostic authentication logic** that powers the Seamless Auth ecosystem.
9
+
10
+ It is designed to be:
11
+
12
+ - deterministic
13
+ - auditable
14
+ - testable
15
+ - independent of any web framework
16
+
17
+ If you are building a custom adapter (Express, Fastify, Next.js, Hono, etc.), this is the package you integrate with.
18
+
19
+ ---
20
+
21
+ ## What This Package Is
22
+
23
+ - Core authentication state machine
24
+ - Cookie validation and refresh logic
25
+ - Service-token–based API ↔ Auth Server communication
26
+ - Stateless, cryptographically verifiable flows
27
+
28
+ This package **does not**:
29
+
30
+ - depend on Express or any framework
31
+ - read environment variables
32
+ - set cookies or headers directly
33
+ - manage HTTP requests or responses
34
+
35
+ ---
36
+
37
+ ## Who Should Use This
38
+
39
+ You should use `@seamless-auth/core` if:
40
+
41
+ - You are building a backend adapter
42
+ - You want full control over your HTTP layer
43
+ - You are integrating Seamless Auth into a non-Express runtime
44
+ - You want to audit or extend authentication behavior
45
+
46
+ If you are using Express, you probably want:
47
+
48
+ ```
49
+ @seamless-auth/express
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Design Principles
55
+
56
+ - **Explicit trust boundaries**
57
+ Browser cookies are never forwarded upstream.
58
+
59
+ - **Stateless by default**
60
+ All session data is encoded and signed.
61
+
62
+ - **Short-lived assertions**
63
+ Service tokens are minimal and ephemeral.
64
+
65
+ - **No hidden magic**
66
+ All inputs are explicit.
67
+
68
+ ---
69
+
70
+ ## Core Concepts
71
+
72
+ ### Identity States
73
+
74
+ - **Unauthenticated**
75
+ - **Pre-authenticated** (OTP / WebAuthn in progress)
76
+ - **Authenticated** (access cookie issued)
77
+
78
+ Core helpers enforce transitions between these states.
79
+
80
+ ---
81
+
82
+ ## Public API (Overview)
83
+
84
+ Key exports include:
85
+
86
+ - `ensureCookies(...)` – validates and refreshes session cookies
87
+ - `refreshAccessToken(...)` – rotates expired access sessions
88
+ - `verifyCookieJwt(...)` – verifies signed cookie payloads
89
+ - `createServiceToken(...)` – creates short-lived M2M assertions
90
+
91
+ These functions return **descriptive results**, not HTTP responses.
92
+
93
+ ---
94
+
95
+ ## Example (Adapter Pseudocode)
96
+
97
+ ```ts
98
+ const result = await ensureCookies(
99
+ { path, cookies },
100
+ {
101
+ authServerUrl,
102
+ cookieSecret,
103
+ serviceSecret,
104
+ issuer,
105
+ audience,
106
+ keyId,
107
+ accessCookieName,
108
+ refreshCookieName,
109
+ preAuthCookieName,
110
+ },
111
+ );
112
+
113
+ if (result.setCookies) {
114
+ // adapter applies cookies
115
+ }
116
+
117
+ if (result.type === "error") {
118
+ // adapter sends HTTP error
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Testing
125
+
126
+ All logic in this package is tested against compiled output (`dist/`),
127
+ ensuring behavior matches production runtime exactly.
128
+
129
+ ---
130
+
131
+ ## License
132
+
133
+ **AGPL-3.0-only** © 2026 Fells Code LLC
134
+
135
+ This license ensures:
136
+
137
+ - transparency of security-critical code
138
+ - freedom to self-host and modify
139
+ - sustainability of the managed service offering
140
+
141
+ See [`LICENSE`](./LICENSE) for details.
@@ -0,0 +1,8 @@
1
+ export interface AuthFetchOptions {
2
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
3
+ headers?: Record<string, string>;
4
+ body?: unknown;
5
+ authorization?: string;
6
+ }
7
+ export declare function authFetch(url: string, options: AuthFetchOptions): Promise<Response>;
8
+ //# sourceMappingURL=authFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authFetch.d.ts","sourceRoot":"","sources":["../src/authFetch.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC,CAYnB"}
@@ -0,0 +1,13 @@
1
+ export async function authFetch(url, options) {
2
+ const headers = {
3
+ "Content-Type": "application/json",
4
+ ...options.headers,
5
+ ...(options.authorization ? { Authorization: options.authorization } : {}),
6
+ };
7
+ return fetch(url, {
8
+ method: options.method,
9
+ headers,
10
+ body: options.body ? JSON.stringify(options.body) : undefined,
11
+ });
12
+ }
13
+ //# sourceMappingURL=authFetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authFetch.js","sourceRoot":"","sources":["../src/authFetch.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAAyB;IAEzB,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,OAAO,CAAC,OAAO;QAClB,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;IAEF,OAAO,KAAK,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO;QACP,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9D,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface ServiceTokenOptions {
2
+ issuer: string;
3
+ audience: string;
4
+ subject: string;
5
+ refreshToken?: string;
6
+ serviceSecret: string;
7
+ keyId: string;
8
+ }
9
+ export declare function createServiceToken(opts: ServiceTokenOptions): string;
10
+ //# sourceMappingURL=createServiceToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createServiceToken.d.ts","sourceRoot":"","sources":["../src/createServiceToken.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAgBpE"}
@@ -0,0 +1,15 @@
1
+ import jwt from "jsonwebtoken";
2
+ export function createServiceToken(opts) {
3
+ return jwt.sign({
4
+ iss: opts.issuer,
5
+ aud: opts.audience,
6
+ sub: opts.subject,
7
+ refreshToken: opts.refreshToken,
8
+ iat: Math.floor(Date.now() / 1000),
9
+ }, opts.serviceSecret, {
10
+ expiresIn: "60s",
11
+ algorithm: "HS256",
12
+ keyid: opts.keyId,
13
+ });
14
+ }
15
+ //# sourceMappingURL=createServiceToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createServiceToken.js","sourceRoot":"","sources":["../src/createServiceToken.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAW/B,MAAM,UAAU,kBAAkB,CAAC,IAAyB;IAC1D,OAAO,GAAG,CAAC,IAAI,CACb;QACE,GAAG,EAAE,IAAI,CAAC,MAAM;QAChB,GAAG,EAAE,IAAI,CAAC,QAAQ;QAClB,GAAG,EAAE,IAAI,CAAC,OAAO;QACjB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;KACnC,EACD,IAAI,CAAC,aAAa,EAClB;QACE,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,OAAO;QAClB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ export interface EnsureCookiesInput {
2
+ path: string;
3
+ cookies: Record<string, string | undefined>;
4
+ }
5
+ export interface CookiePayload {
6
+ sub: string;
7
+ token?: string;
8
+ refreshToken?: string;
9
+ roles?: string[];
10
+ }
11
+ export interface CookieInstruction {
12
+ name: string;
13
+ value: CookiePayload;
14
+ ttl: number;
15
+ domain?: string;
16
+ }
17
+ export interface EnsureCookiesResult {
18
+ type: "ok" | "error";
19
+ status?: number;
20
+ error?: string;
21
+ user?: {
22
+ sub: string;
23
+ roles?: string[];
24
+ };
25
+ setCookies?: CookieInstruction[];
26
+ clearCookies?: string[];
27
+ }
28
+ export interface EnsureCookiesOptions {
29
+ authServerUrl: string;
30
+ cookieDomain?: string;
31
+ accessCookieName: string;
32
+ registrationCookieName: string;
33
+ refreshCookieName: string;
34
+ preAuthCookieName: string;
35
+ cookieSecret: string;
36
+ serviceSecret: string;
37
+ issuer: string;
38
+ audience: string;
39
+ keyId: string;
40
+ }
41
+ export declare function ensureCookies(input: EnsureCookiesInput, opts: EnsureCookiesOptions): Promise<EnsureCookiesResult>;
42
+ //# sourceMappingURL=ensureCookies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureCookies.d.ts","sourceRoot":"","sources":["../src/ensureCookies.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AA4BD,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,EACzB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,CAAC,CAsG9B"}
@@ -0,0 +1,116 @@
1
+ import { verifyCookieJwt } from "./verifyCookieJwt.js";
2
+ import { refreshAccessToken } from "./refreshAccessToken.js";
3
+ const COOKIE_REQUIREMENTS = {
4
+ "/webAuthn/login/finish": { name: "preAuthCookieName", required: true },
5
+ "/webAuthn/login/start": { name: "preAuthCookieName", required: true },
6
+ "/webAuthn/register/start": {
7
+ name: "registrationCookieName",
8
+ required: true,
9
+ },
10
+ "/webAuthn/register/finish": {
11
+ name: "registrationCookieName",
12
+ required: true,
13
+ },
14
+ "/otp/verify-email-otp": {
15
+ name: "registrationCookieName",
16
+ required: true,
17
+ },
18
+ "/otp/verify-phone-otp": {
19
+ name: "registrationCookieName",
20
+ required: true,
21
+ },
22
+ "/logout": { name: "accessCookieName", required: true },
23
+ "/users/me": { name: "accessCookieName", required: true },
24
+ };
25
+ export async function ensureCookies(input, opts) {
26
+ const match = Object.entries(COOKIE_REQUIREMENTS).find(([path]) => input.path.startsWith(path));
27
+ if (!match) {
28
+ return { type: "ok" };
29
+ }
30
+ const [, { name, required }] = match;
31
+ const cookieName = opts[name];
32
+ if (!cookieName) {
33
+ return {
34
+ type: "error",
35
+ status: 400,
36
+ error: "Missing required cookie",
37
+ };
38
+ }
39
+ const cookieValue = input.cookies[cookieName];
40
+ const refreshCookie = input.cookies[opts.refreshCookieName];
41
+ if (required && !cookieValue) {
42
+ if (!refreshCookie) {
43
+ return {
44
+ type: "error",
45
+ status: 400,
46
+ error: `Missing required cookie "${cookieName}"`,
47
+ };
48
+ }
49
+ const refreshed = await refreshAccessToken(refreshCookie, {
50
+ authServerUrl: opts.authServerUrl,
51
+ cookieSecret: opts.cookieSecret,
52
+ serviceSecret: opts.serviceSecret,
53
+ issuer: opts.issuer,
54
+ audience: opts.audience,
55
+ keyId: opts.keyId,
56
+ });
57
+ if (!refreshed?.token) {
58
+ return {
59
+ type: "error",
60
+ status: 401,
61
+ error: "Refresh failed",
62
+ clearCookies: [
63
+ cookieName,
64
+ opts.registrationCookieName,
65
+ opts.refreshCookieName,
66
+ ],
67
+ };
68
+ }
69
+ return {
70
+ type: "ok",
71
+ user: {
72
+ sub: refreshed.sub,
73
+ roles: refreshed.roles,
74
+ },
75
+ setCookies: [
76
+ {
77
+ name: cookieName,
78
+ value: {
79
+ sub: refreshed.sub,
80
+ roles: refreshed.roles,
81
+ },
82
+ ttl: refreshed.ttl,
83
+ domain: opts.cookieDomain,
84
+ },
85
+ {
86
+ name: opts.refreshCookieName,
87
+ value: {
88
+ sub: refreshed.sub,
89
+ refreshToken: refreshed.refreshToken,
90
+ },
91
+ ttl: refreshed.refreshTtl,
92
+ domain: opts.cookieDomain,
93
+ },
94
+ ],
95
+ };
96
+ }
97
+ if (cookieValue) {
98
+ const payload = verifyCookieJwt(cookieValue, opts.cookieSecret);
99
+ if (!payload) {
100
+ return {
101
+ type: "error",
102
+ status: 401,
103
+ error: `Invalid or expired ${cookieName} cookie`,
104
+ };
105
+ }
106
+ return {
107
+ type: "ok",
108
+ user: {
109
+ sub: payload.sub,
110
+ roles: payload.roles,
111
+ },
112
+ };
113
+ }
114
+ return { type: "ok" };
115
+ }
116
+ //# sourceMappingURL=ensureCookies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureCookies.js","sourceRoot":"","sources":["../src/ensureCookies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface GetSeamlessUserOptions {
2
+ authServerUrl: string;
3
+ cookieSecret: string;
4
+ cookieName?: string;
5
+ }
6
+ export declare function getSeamlessUser<T = any>(cookies: Record<string, string | undefined>, opts: GetSeamlessUserOptions): Promise<T | null>;
7
+ //# sourceMappingURL=getSeamlessUser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSeamlessUser.d.ts","sourceRoot":"","sources":["../src/getSeamlessUser.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,eAAe,CAAC,CAAC,GAAG,GAAG,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC3C,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAiBnB"}
@@ -0,0 +1,19 @@
1
+ import { authFetch } from "./authFetch.js";
2
+ import { verifyCookieJwt } from "./verifyCookieJwt.js";
3
+ export async function getSeamlessUser(cookies, opts) {
4
+ const cookieName = opts.cookieName ?? "seamless-access";
5
+ const token = cookies[cookieName];
6
+ if (!token)
7
+ return null;
8
+ const payload = verifyCookieJwt(token, opts.cookieSecret);
9
+ if (!payload)
10
+ return null;
11
+ const response = await authFetch(`${opts.authServerUrl}/users/me`, {
12
+ method: "GET",
13
+ });
14
+ if (!response.ok)
15
+ return null;
16
+ const data = await response.json();
17
+ return data.user ?? null;
18
+ }
19
+ //# sourceMappingURL=getSeamlessUser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSeamlessUser.js","sourceRoot":"","sources":["../src/getSeamlessUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQvD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA2C,EAC3C,IAA4B;IAE5B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAElC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,WAAW,EAAE;QACjE,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { CookiePayload } from "../ensureCookies.js";
2
+ export interface FinishLoginInput {
3
+ body: unknown;
4
+ authorization?: string;
5
+ }
6
+ export interface FinishLoginOptions {
7
+ authServerUrl: string;
8
+ cookieDomain?: string;
9
+ accessCookieName: string;
10
+ refreshCookieName: string;
11
+ }
12
+ export interface FinishLoginResult {
13
+ status: number;
14
+ body?: unknown;
15
+ error?: string;
16
+ setCookies?: {
17
+ name: string;
18
+ value: CookiePayload;
19
+ ttl: number;
20
+ domain?: string;
21
+ }[];
22
+ }
23
+ export declare function finishLoginHandler(input: FinishLoginInput, opts: FinishLoginOptions): Promise<FinishLoginResult>;
24
+ //# sourceMappingURL=finishLogin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finishLogin.d.ts","sourceRoot":"","sources":["../../src/handlers/finishLogin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;CACL;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAqD5B"}
@@ -0,0 +1,48 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ import { verifySignedAuthResponse } from "../verifySignedAuthResponse.js";
3
+ export async function finishLoginHandler(input, opts) {
4
+ const up = await authFetch(`${opts.authServerUrl}/webAuthn/login/finish`, {
5
+ method: "POST",
6
+ body: input.body,
7
+ authorization: input.authorization,
8
+ });
9
+ const data = await up.json();
10
+ if (!up.ok) {
11
+ return {
12
+ status: up.status,
13
+ error: data,
14
+ };
15
+ }
16
+ const verifiedAccessToken = await verifySignedAuthResponse(data.token, opts.authServerUrl);
17
+ if (!verifiedAccessToken) {
18
+ throw new Error("Invalid signed response from Auth Server");
19
+ }
20
+ if (verifiedAccessToken.sub !== data.sub) {
21
+ throw new Error("Signature mismatch with data payload");
22
+ }
23
+ return {
24
+ status: 200,
25
+ body: data,
26
+ setCookies: [
27
+ {
28
+ name: opts.accessCookieName,
29
+ value: {
30
+ sub: data.sub,
31
+ roles: data.roles,
32
+ },
33
+ ttl: data.ttl,
34
+ domain: opts.cookieDomain,
35
+ },
36
+ {
37
+ name: opts.refreshCookieName,
38
+ value: {
39
+ sub: data.sub,
40
+ refreshToken: data.refreshToken,
41
+ },
42
+ ttl: data.refreshTtl,
43
+ domain: opts.cookieDomain,
44
+ },
45
+ ],
46
+ };
47
+ }
48
+ //# sourceMappingURL=finishLogin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finishLogin.js","sourceRoot":"","sources":["../../src/handlers/finishLogin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AA0B1E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAuB,EACvB,IAAwB;IAExB,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,wBAAwB,EAAE;QACxE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,MAAM,mBAAmB,GAAG,MAAM,wBAAwB,CACxD,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,aAAa,CACnB,CAAC;IAEF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,mBAAmB,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,IAAI;QACV,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,IAAI,CAAC,gBAAgB;gBAC3B,KAAK,EAAE;oBACL,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB;gBACD,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;YACD;gBACE,IAAI,EAAE,IAAI,CAAC,iBAAiB;gBAC5B,KAAK,EAAE;oBACL,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,YAAY,EAAE,IAAI,CAAC,YAAY;iBAChC;gBACD,GAAG,EAAE,IAAI,CAAC,UAAU;gBACpB,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { CookiePayload } from "../ensureCookies.js";
2
+ export interface FinishRegisterInput {
3
+ authorization?: string;
4
+ body: unknown;
5
+ }
6
+ export interface FinishRegisterOptions {
7
+ authServerUrl: string;
8
+ cookieDomain?: string;
9
+ accessCookieName: string;
10
+ refreshCookieName: string;
11
+ }
12
+ export interface FinishRegisterResult {
13
+ status: number;
14
+ error?: unknown;
15
+ setCookies?: {
16
+ name: string;
17
+ value: CookiePayload;
18
+ ttl: number;
19
+ domain?: string;
20
+ }[];
21
+ }
22
+ export declare function finishRegisterHandler(input: FinishRegisterInput, opts: FinishRegisterOptions): Promise<FinishRegisterResult>;
23
+ //# sourceMappingURL=finishRegister.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finishRegister.d.ts","sourceRoot":"","sources":["../../src/handlers/finishRegister.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,MAAM,WAAW,mBAAmB;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;CACL;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAoD/B"}
@@ -0,0 +1,47 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ import { verifySignedAuthResponse } from "../verifySignedAuthResponse.js";
3
+ export async function finishRegisterHandler(input, opts) {
4
+ const up = await authFetch(`${opts.authServerUrl}/webAuthn/register/finish`, {
5
+ method: "POST",
6
+ body: input.body,
7
+ authorization: input.authorization,
8
+ });
9
+ const data = await up.json();
10
+ if (!up.ok) {
11
+ return {
12
+ status: up.status,
13
+ error: data,
14
+ };
15
+ }
16
+ const verified = await verifySignedAuthResponse(data.token, opts.authServerUrl);
17
+ if (!verified) {
18
+ throw new Error("Invalid signed response from Auth Server");
19
+ }
20
+ if (verified.sub !== data.sub) {
21
+ throw new Error("Signature mismatch with data payload");
22
+ }
23
+ return {
24
+ status: 204,
25
+ setCookies: [
26
+ {
27
+ name: opts.accessCookieName,
28
+ value: {
29
+ sub: data.sub,
30
+ roles: data.roles,
31
+ },
32
+ ttl: data.ttl,
33
+ domain: opts.cookieDomain,
34
+ },
35
+ {
36
+ name: opts.refreshCookieName,
37
+ value: {
38
+ sub: data.sub,
39
+ refreshToken: data.refreshToken,
40
+ },
41
+ ttl: data.refreshTtl,
42
+ domain: opts.cookieDomain,
43
+ },
44
+ ],
45
+ };
46
+ }
47
+ //# sourceMappingURL=finishRegister.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finishRegister.js","sourceRoot":"","sources":["../../src/handlers/finishRegister.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAyB1E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAA0B,EAC1B,IAA2B;IAE3B,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,2BAA2B,EAAE;QAC3E,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAC7C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,aAAa,CACnB,CAAC;IAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,QAAQ,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG;QACX,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,IAAI,CAAC,gBAAgB;gBAC3B,KAAK,EAAE;oBACL,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB;gBACD,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;YACD;gBACE,IAAI,EAAE,IAAI,CAAC,iBAAiB;gBAC5B,KAAK,EAAE;oBACL,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,YAAY,EAAE,IAAI,CAAC,YAAY;iBAChC;gBACD,GAAG,EAAE,IAAI,CAAC,UAAU;gBACpB,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { CookiePayload } from "../ensureCookies.js";
2
+ export interface LoginInput {
3
+ body: unknown;
4
+ }
5
+ export interface LoginOptions {
6
+ authServerUrl: string;
7
+ cookieDomain?: string;
8
+ preAuthCookieName: string;
9
+ }
10
+ export interface LoginResult {
11
+ status: number;
12
+ error?: string;
13
+ setCookies?: {
14
+ name: string;
15
+ value: CookiePayload;
16
+ ttl: number;
17
+ domain?: string;
18
+ }[];
19
+ }
20
+ export declare function loginHandler(input: LoginInput, opts: LoginOptions): Promise<LoginResult>;
21
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;CACL;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,WAAW,CAAC,CAuCtB"}
@@ -0,0 +1,34 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ import { verifySignedAuthResponse } from "../verifySignedAuthResponse.js";
3
+ export async function loginHandler(input, opts) {
4
+ const up = await authFetch(`${opts.authServerUrl}/login`, {
5
+ method: "POST",
6
+ body: input.body,
7
+ });
8
+ const data = await up.json();
9
+ if (!up.ok) {
10
+ return {
11
+ status: up.status,
12
+ error: data,
13
+ };
14
+ }
15
+ const verified = await verifySignedAuthResponse(data.token, opts.authServerUrl);
16
+ if (!verified) {
17
+ throw new Error("Invalid signed response from Auth Server");
18
+ }
19
+ if (verified.sub !== data.sub) {
20
+ throw new Error("Signature mismatch with data payload");
21
+ }
22
+ return {
23
+ status: 204,
24
+ setCookies: [
25
+ {
26
+ name: opts.preAuthCookieName,
27
+ value: { sub: data.sub, token: data.token },
28
+ ttl: data.ttl,
29
+ domain: opts.cookieDomain,
30
+ },
31
+ ],
32
+ };
33
+ }
34
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAuB1E,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiB,EACjB,IAAkB;IAElB,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,QAAQ,EAAE;QACxD,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAC7C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,aAAa,CACnB,CAAC;IAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,QAAQ,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG;QACX,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,IAAI,CAAC,iBAAiB;gBAC5B,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;gBAC3C,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface LogoutOptions {
2
+ authServerUrl: string;
3
+ accessCookieName: string;
4
+ registrationCookieName: string;
5
+ refreshCookieName: string;
6
+ }
7
+ export interface LogoutResult {
8
+ status: number;
9
+ clearCookies: string[];
10
+ }
11
+ export declare function logoutHandler(opts: LogoutOptions): Promise<LogoutResult>;
12
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/handlers/logout.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,YAAY,CAAC,CAavB"}
@@ -0,0 +1,15 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ export async function logoutHandler(opts) {
3
+ await authFetch(`${opts.authServerUrl}/logout`, {
4
+ method: "GET",
5
+ });
6
+ return {
7
+ status: 204,
8
+ clearCookies: [
9
+ opts.accessCookieName,
10
+ opts.registrationCookieName,
11
+ opts.refreshCookieName,
12
+ ],
13
+ };
14
+ }
15
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/handlers/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAc5C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAmB;IAEnB,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,SAAS,EAAE;QAC9C,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,GAAG;QACX,YAAY,EAAE;YACZ,IAAI,CAAC,gBAAgB;YACrB,IAAI,CAAC,sBAAsB;YAC3B,IAAI,CAAC,iBAAiB;SACvB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface MeOptions {
2
+ authServerUrl: string;
3
+ preAuthCookieName: string;
4
+ authorization?: string;
5
+ }
6
+ export interface MeResult {
7
+ status: number;
8
+ body?: {
9
+ user: unknown;
10
+ credentials?: unknown;
11
+ };
12
+ error?: string;
13
+ clearCookies?: string[];
14
+ }
15
+ export declare function meHandler(opts: MeOptions): Promise<MeResult>;
16
+ //# sourceMappingURL=me.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,OAAO,CAAC;QACd,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyBlE"}
@@ -0,0 +1,25 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ export async function meHandler(opts) {
3
+ const up = await authFetch(`${opts.authServerUrl}/users/me`, {
4
+ method: "GET",
5
+ authorization: opts.authorization,
6
+ });
7
+ const data = await up.json();
8
+ const clearCookies = [opts.preAuthCookieName];
9
+ if (!data?.user) {
10
+ return {
11
+ status: 401,
12
+ error: "unauthenticated",
13
+ clearCookies,
14
+ };
15
+ }
16
+ return {
17
+ status: 200,
18
+ body: {
19
+ user: data.user,
20
+ credentials: data.credentials,
21
+ },
22
+ clearCookies,
23
+ };
24
+ }
25
+ //# sourceMappingURL=me.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAkB5C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAe;IAC7C,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,WAAW,EAAE;QAC3D,MAAM,EAAE,KAAK;QACb,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE9C,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAChB,OAAO;YACL,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,iBAAiB;YACxB,YAAY;SACb,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B;QACD,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { CookiePayload } from "../ensureCookies.js";
2
+ export interface RegisterInput {
3
+ body: unknown;
4
+ }
5
+ export interface RegisterOptions {
6
+ authServerUrl: string;
7
+ cookieDomain?: string;
8
+ registrationCookieName: string;
9
+ }
10
+ export interface RegisterResult {
11
+ status: number;
12
+ body?: unknown;
13
+ error?: unknown;
14
+ setCookies?: {
15
+ name: string;
16
+ value: CookiePayload;
17
+ ttl: number;
18
+ domain?: string;
19
+ }[];
20
+ }
21
+ export declare function registerHandler(input: RegisterInput, opts: RegisterOptions): Promise<RegisterResult>;
22
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/handlers/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,aAAa,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;CACL;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,cAAc,CAAC,CA2BzB"}
@@ -0,0 +1,27 @@
1
+ import { authFetch } from "../authFetch.js";
2
+ export async function registerHandler(input, opts) {
3
+ const up = await authFetch(`${opts.authServerUrl}/registration/register`, {
4
+ method: "POST",
5
+ body: input.body,
6
+ });
7
+ const data = await up.json();
8
+ if (!up.ok) {
9
+ return {
10
+ status: up.status,
11
+ error: data,
12
+ };
13
+ }
14
+ return {
15
+ status: 200,
16
+ body: data,
17
+ setCookies: [
18
+ {
19
+ name: opts.registrationCookieName,
20
+ value: { sub: data.sub },
21
+ ttl: data.ttl,
22
+ domain: opts.cookieDomain,
23
+ },
24
+ ],
25
+ };
26
+ }
27
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/handlers/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAyB5C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,IAAqB;IAErB,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,wBAAwB,EAAE;QACxE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,IAAI;QACV,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,IAAI,CAAC,sBAAsB;gBACjC,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;gBACxB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,IAAI,CAAC,YAAY;aAC1B;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export * from "./authFetch.js";
2
+ export * from "./ensureCookies.js";
3
+ export * from "./verifyCookieJwt.js";
4
+ export * from "./refreshAccessToken.js";
5
+ export * from "./getSeamlessUser.js";
6
+ export * from "./createServiceToken.js";
7
+ export * from "./handlers/login.js";
8
+ export * from "./handlers/finishLogin.js";
9
+ export * from "./handlers/register.js";
10
+ export * from "./handlers/finishRegister.js";
11
+ export * from "./handlers/logout.js";
12
+ export * from "./handlers/me.js";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AAExC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export * from "./authFetch.js";
2
+ export * from "./ensureCookies.js";
3
+ export * from "./verifyCookieJwt.js";
4
+ export * from "./refreshAccessToken.js";
5
+ export * from "./getSeamlessUser.js";
6
+ export * from "./createServiceToken.js";
7
+ export * from "./handlers/login.js";
8
+ export * from "./handlers/finishLogin.js";
9
+ export * from "./handlers/register.js";
10
+ export * from "./handlers/finishRegister.js";
11
+ export * from "./handlers/logout.js";
12
+ export * from "./handlers/me.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AAExC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface RefreshAccessTokenOptions {
2
+ authServerUrl: string;
3
+ cookieSecret: string;
4
+ serviceSecret: string;
5
+ issuer: string;
6
+ audience: string;
7
+ keyId: string;
8
+ }
9
+ export declare function refreshAccessToken(refreshCookie: string, opts: RefreshAccessTokenOptions): Promise<{
10
+ sub: string;
11
+ token: string;
12
+ refreshToken: string;
13
+ roles: string[];
14
+ ttl: number;
15
+ refreshTtl: number;
16
+ } | null>;
17
+ //# sourceMappingURL=refreshAccessToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshAccessToken.d.ts","sourceRoot":"","sources":["../src/refreshAccessToken.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,IAAI,CAAC,CAuBR"}
@@ -0,0 +1,26 @@
1
+ import { authFetch } from "./authFetch.js";
2
+ import { verifyRefreshCookie } from "./verifyRefreshCookie.js";
3
+ import { createServiceToken } from "./createServiceToken.js";
4
+ export async function refreshAccessToken(refreshCookie, opts) {
5
+ const payload = verifyRefreshCookie(refreshCookie, opts.cookieSecret);
6
+ if (!payload)
7
+ return null;
8
+ const serviceToken = createServiceToken({
9
+ issuer: opts.issuer,
10
+ audience: opts.audience,
11
+ subject: payload.sub,
12
+ refreshToken: payload.refreshToken,
13
+ serviceSecret: opts.serviceSecret,
14
+ keyId: opts.keyId,
15
+ });
16
+ const response = await authFetch(`${opts.authServerUrl}/refresh`, {
17
+ method: "GET",
18
+ headers: {
19
+ Authorization: `Bearer ${serviceToken}`,
20
+ },
21
+ });
22
+ if (!response.ok)
23
+ return null;
24
+ return response.json();
25
+ }
26
+ //# sourceMappingURL=refreshAccessToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshAccessToken.js","sourceRoot":"","sources":["../src/refreshAccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAW7D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,aAAqB,EACrB,IAA+B;IAS/B,MAAM,OAAO,GAAG,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACtE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,YAAY,GAAG,kBAAkB,CAAC;QACtC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,OAAO,EAAE,OAAO,CAAC,GAAG;QACpB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,UAAU,EAAE;QAChE,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,YAAY,EAAE;SACxC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAE9B,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type JwtPayload } from "jsonwebtoken";
2
+ export declare function verifyCookieJwt<T extends JwtPayload = JwtPayload>(token: string, secret: string): T | null;
3
+ //# sourceMappingURL=verifyCookieJwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyCookieJwt.d.ts","sourceRoot":"","sources":["../src/verifyCookieJwt.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,EAC/D,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,CAAC,GAAG,IAAI,CASV"}
@@ -0,0 +1,13 @@
1
+ import jwt, {} from "jsonwebtoken";
2
+ export function verifyCookieJwt(token, secret) {
3
+ try {
4
+ return jwt.verify(token, secret, {
5
+ algorithms: ["HS256"],
6
+ });
7
+ }
8
+ catch {
9
+ // Intentional no-op
10
+ return null;
11
+ }
12
+ }
13
+ //# sourceMappingURL=verifyCookieJwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyCookieJwt.js","sourceRoot":"","sources":["../src/verifyCookieJwt.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,EAAE,EAAmB,MAAM,cAAc,CAAC;AAEpD,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE;YAC/B,UAAU,EAAE,CAAC,OAAO,CAAC;SACtB,CAAM,CAAC;IACV,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type JwtPayload } from "jsonwebtoken";
2
+ export interface RefreshCookiePayload extends JwtPayload {
3
+ sub: string;
4
+ refreshToken: string;
5
+ }
6
+ export declare function verifyRefreshCookie(token: string, cookieSecret: string): RefreshCookiePayload | null;
7
+ //# sourceMappingURL=verifyRefreshCookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyRefreshCookie.d.ts","sourceRoot":"","sources":["../src/verifyRefreshCookie.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,oBAAqB,SAAQ,UAAU;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,GACnB,oBAAoB,GAAG,IAAI,CAQ7B"}
@@ -0,0 +1,12 @@
1
+ import jwt, {} from "jsonwebtoken";
2
+ export function verifyRefreshCookie(token, cookieSecret) {
3
+ try {
4
+ return jwt.verify(token, cookieSecret, {
5
+ algorithms: ["HS256"],
6
+ });
7
+ }
8
+ catch {
9
+ return null;
10
+ }
11
+ }
12
+ //# sourceMappingURL=verifyRefreshCookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyRefreshCookie.js","sourceRoot":"","sources":["../src/verifyRefreshCookie.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,EAAE,EAAmB,MAAM,cAAc,CAAC;AAOpD,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,YAAoB;IAEpB,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE;YACrC,UAAU,EAAE,CAAC,OAAO,CAAC;SACtB,CAAyB,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function verifySignedAuthResponse<T = any>(token: string, authServerUrl: string): Promise<T | null>;
2
+ //# sourceMappingURL=verifySignedAuthResponse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifySignedAuthResponse.d.ts","sourceRoot":"","sources":["../src/verifySignedAuthResponse.ts"],"names":[],"mappings":"AAEA,wBAAsB,wBAAwB,CAAC,CAAC,GAAG,GAAG,EACpD,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAenB"}
@@ -0,0 +1,17 @@
1
+ import { createRemoteJWKSet, jwtVerify } from "jose";
2
+ export async function verifySignedAuthResponse(token, authServerUrl) {
3
+ try {
4
+ const jwksUrl = new URL("/.well-known/jwks.json", authServerUrl).toString();
5
+ const JWKS = createRemoteJWKSet(new URL(jwksUrl));
6
+ const { payload } = await jwtVerify(token, JWKS, {
7
+ algorithms: ["RS256"],
8
+ issuer: authServerUrl,
9
+ });
10
+ return payload;
11
+ }
12
+ catch (err) {
13
+ console.error("[SeamlessAuth] Failed to verify signed auth response:", err);
14
+ return null;
15
+ }
16
+ }
17
+ //# sourceMappingURL=verifySignedAuthResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifySignedAuthResponse.js","sourceRoot":"","sources":["../src/verifySignedAuthResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAa,EACb,aAAqB;IAErB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5E,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAElD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/C,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE,aAAa;SACtB,CAAC,CAAC;QAEH,OAAO,OAAY,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,uDAAuD,EAAE,GAAG,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@seamless-auth/core",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic core authentication logic for SeamlessAuth",
5
+ "license": "AGPL-3.0-only",
6
+ "author": "Fells Code, LLC",
7
+ "sideEffects": false,
8
+ "homepage": "https://seamlessauth.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/fells-code/seamless-auth-server/packages/core"
12
+ },
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./handlers/*": {
22
+ "types": "./dist/handlers/*.d.ts",
23
+ "import": "./dist/handlers/*.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "LICENSE",
29
+ "LICENSE.md",
30
+ "README.md"
31
+ ],
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.json",
37
+ "clean": "rm -rf dist",
38
+ "prepublishOnly": "npm run clean && npm run build",
39
+ "test": "npm run build && NODE_OPTIONS=--experimental-vm-modules jest",
40
+ "test:watch": "npm run build && NODE_OPTIONS=--experimental-vm-modules jest --watch"
41
+ },
42
+ "dependencies": {
43
+ "jose": "^6.1.3",
44
+ "jsonwebtoken": "^9.0.2"
45
+ },
46
+ "devDependencies": {
47
+ "@types/jest": "^29.5.14",
48
+ "@types/jsonwebtoken": "^9.0.10",
49
+ "jest": "^29.7.0",
50
+ "ts-node": "^10.9.2",
51
+ "typescript": "^5.9.3"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }