@draftlab/auth 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/allow.js +26 -0
- package/dist/esm/client.js +254 -0
- package/dist/esm/core.js +597 -0
- package/dist/esm/css.d.js +0 -0
- package/dist/esm/error.js +88 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/keys.js +126 -0
- package/dist/esm/mutex.js +53 -0
- package/dist/esm/pkce.js +87 -0
- package/dist/esm/provider/apple.js +15 -0
- package/dist/esm/provider/code.js +62 -0
- package/dist/esm/provider/discord.js +15 -0
- package/dist/esm/provider/facebook.js +15 -0
- package/dist/esm/provider/github.js +15 -0
- package/dist/esm/provider/gitlab.js +15 -0
- package/dist/esm/provider/google.js +16 -0
- package/dist/esm/provider/linkedin.js +15 -0
- package/dist/esm/provider/magiclink.js +83 -0
- package/dist/esm/provider/microsoft.js +15 -0
- package/dist/esm/provider/oauth2.js +130 -0
- package/dist/esm/provider/password.js +331 -0
- package/dist/esm/provider/provider.js +18 -0
- package/dist/esm/provider/reddit.js +15 -0
- package/dist/esm/provider/slack.js +15 -0
- package/dist/esm/provider/spotify.js +15 -0
- package/dist/esm/provider/twitch.js +15 -0
- package/dist/esm/provider/vercel.js +17 -0
- package/dist/esm/random.js +40 -0
- package/dist/esm/revocation.js +27 -0
- package/dist/esm/storage/memory.js +110 -0
- package/dist/esm/storage/storage.js +56 -0
- package/dist/esm/storage/turso.js +93 -0
- package/dist/esm/storage/unstorage.js +78 -0
- package/dist/esm/subject.js +7 -0
- package/dist/esm/themes/theme.js +115 -0
- package/dist/esm/toolkit/client.js +119 -0
- package/dist/esm/toolkit/index.js +25 -0
- package/dist/esm/toolkit/providers/facebook.js +11 -0
- package/dist/esm/toolkit/providers/github.js +11 -0
- package/dist/esm/toolkit/providers/google.js +11 -0
- package/dist/esm/toolkit/providers/strategy.js +0 -0
- package/dist/esm/toolkit/storage.js +81 -0
- package/dist/esm/toolkit/utils.js +18 -0
- package/dist/esm/types.js +0 -0
- package/dist/esm/ui/base.js +478 -0
- package/dist/esm/ui/code.js +186 -0
- package/dist/esm/ui/form.js +46 -0
- package/dist/esm/ui/icon.js +242 -0
- package/dist/esm/ui/magiclink.js +158 -0
- package/dist/esm/ui/password.js +435 -0
- package/dist/esm/ui/select.js +102 -0
- package/dist/esm/util.js +59 -0
- package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
- package/dist/types/allow.d.ts.map +1 -0
- package/dist/types/client.d.ts +462 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/core.d.ts +113 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/{error.d.mts → types/error.d.ts} +95 -97
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{keys.d.mts → types/keys.d.ts} +20 -24
- package/dist/types/keys.d.ts.map +1 -0
- package/dist/types/mutex.d.ts +42 -0
- package/dist/types/mutex.d.ts.map +1 -0
- package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
- package/dist/types/pkce.d.ts.map +1 -0
- package/dist/types/provider/apple.d.ts +197 -0
- package/dist/types/provider/apple.d.ts.map +1 -0
- package/dist/types/provider/code.d.ts +288 -0
- package/dist/types/provider/code.d.ts.map +1 -0
- package/dist/types/provider/discord.d.ts +206 -0
- package/dist/types/provider/discord.d.ts.map +1 -0
- package/dist/types/provider/facebook.d.ts +200 -0
- package/dist/types/provider/facebook.d.ts.map +1 -0
- package/dist/types/provider/github.d.ts +220 -0
- package/dist/types/provider/github.d.ts.map +1 -0
- package/dist/types/provider/gitlab.d.ts +180 -0
- package/dist/types/provider/gitlab.d.ts.map +1 -0
- package/dist/types/provider/google.d.ts +158 -0
- package/dist/types/provider/google.d.ts.map +1 -0
- package/dist/types/provider/linkedin.d.ts +190 -0
- package/dist/types/provider/linkedin.d.ts.map +1 -0
- package/dist/types/provider/magiclink.d.ts +141 -0
- package/dist/types/provider/magiclink.d.ts.map +1 -0
- package/dist/types/provider/microsoft.d.ts +247 -0
- package/dist/types/provider/microsoft.d.ts.map +1 -0
- package/dist/types/provider/oauth2.d.ts +229 -0
- package/dist/types/provider/oauth2.d.ts.map +1 -0
- package/dist/types/provider/password.d.ts +408 -0
- package/dist/types/provider/password.d.ts.map +1 -0
- package/dist/types/provider/provider.d.ts +226 -0
- package/dist/types/provider/provider.d.ts.map +1 -0
- package/dist/types/provider/reddit.d.ts +159 -0
- package/dist/types/provider/reddit.d.ts.map +1 -0
- package/dist/types/provider/slack.d.ts +171 -0
- package/dist/types/provider/slack.d.ts.map +1 -0
- package/dist/types/provider/spotify.d.ts +168 -0
- package/dist/types/provider/spotify.d.ts.map +1 -0
- package/dist/types/provider/twitch.d.ts +163 -0
- package/dist/types/provider/twitch.d.ts.map +1 -0
- package/dist/types/provider/vercel.d.ts +294 -0
- package/dist/types/provider/vercel.d.ts.map +1 -0
- package/dist/{random.d.mts → types/random.d.ts} +4 -6
- package/dist/types/random.d.ts.map +1 -0
- package/dist/types/revocation.d.ts +76 -0
- package/dist/types/revocation.d.ts.map +1 -0
- package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -21
- package/dist/types/storage/memory.d.ts.map +1 -0
- package/dist/types/storage/storage.d.ts +177 -0
- package/dist/types/storage/storage.d.ts.map +1 -0
- package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -8
- package/dist/types/storage/turso.d.ts.map +1 -0
- package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
- package/dist/types/storage/unstorage.d.ts.map +1 -0
- package/dist/types/subject.d.ts +115 -0
- package/dist/types/subject.d.ts.map +1 -0
- package/dist/types/themes/theme.d.ts +207 -0
- package/dist/types/themes/theme.d.ts.map +1 -0
- package/dist/types/toolkit/client.d.ts +235 -0
- package/dist/types/toolkit/client.d.ts.map +1 -0
- package/dist/types/toolkit/index.d.ts +45 -0
- package/dist/types/toolkit/index.d.ts.map +1 -0
- package/dist/types/toolkit/providers/facebook.d.ts +8 -0
- package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
- package/dist/types/toolkit/providers/github.d.ts +8 -0
- package/dist/types/toolkit/providers/github.d.ts.map +1 -0
- package/dist/types/toolkit/providers/google.d.ts +8 -0
- package/dist/types/toolkit/providers/google.d.ts.map +1 -0
- package/dist/types/toolkit/providers/strategy.d.ts +38 -0
- package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
- package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
- package/dist/types/toolkit/storage.d.ts.map +1 -0
- package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
- package/dist/types/toolkit/utils.d.ts.map +1 -0
- package/dist/types/types.d.ts +92 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/ui/base.d.ts +18 -0
- package/dist/types/ui/base.d.ts.map +1 -0
- package/dist/types/ui/code.d.ts +43 -0
- package/dist/types/ui/code.d.ts.map +1 -0
- package/dist/types/ui/form.d.ts +24 -0
- package/dist/types/ui/form.d.ts.map +1 -0
- package/dist/types/ui/icon.d.ts +60 -0
- package/dist/types/ui/icon.d.ts.map +1 -0
- package/dist/types/ui/magiclink.d.ts +41 -0
- package/dist/types/ui/magiclink.d.ts.map +1 -0
- package/dist/types/ui/password.d.ts +43 -0
- package/dist/types/ui/password.d.ts.map +1 -0
- package/dist/types/ui/select.d.ts +33 -0
- package/dist/types/ui/select.d.ts.map +1 -0
- package/dist/{util.d.mts → types/util.d.ts} +11 -13
- package/dist/types/util.d.ts.map +1 -0
- package/package.json +10 -16
- package/dist/adapters/node.d.mts +0 -18
- package/dist/adapters/node.mjs +0 -69
- package/dist/allow.mjs +0 -63
- package/dist/client.d.mts +0 -456
- package/dist/client.mjs +0 -283
- package/dist/core.d.mts +0 -110
- package/dist/core.mjs +0 -595
- package/dist/error.mjs +0 -237
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -3
- package/dist/keys.mjs +0 -146
- package/dist/mutex.d.mts +0 -44
- package/dist/mutex.mjs +0 -110
- package/dist/pkce.mjs +0 -157
- package/dist/provider/apple.d.mts +0 -111
- package/dist/provider/apple.mjs +0 -164
- package/dist/provider/code.d.mts +0 -228
- package/dist/provider/code.mjs +0 -246
- package/dist/provider/discord.d.mts +0 -146
- package/dist/provider/discord.mjs +0 -156
- package/dist/provider/facebook.d.mts +0 -142
- package/dist/provider/facebook.mjs +0 -150
- package/dist/provider/github.d.mts +0 -140
- package/dist/provider/github.mjs +0 -169
- package/dist/provider/gitlab.d.mts +0 -106
- package/dist/provider/gitlab.mjs +0 -147
- package/dist/provider/google.d.mts +0 -112
- package/dist/provider/google.mjs +0 -109
- package/dist/provider/linkedin.d.mts +0 -132
- package/dist/provider/linkedin.mjs +0 -142
- package/dist/provider/magiclink.d.mts +0 -89
- package/dist/provider/magiclink.mjs +0 -143
- package/dist/provider/microsoft.d.mts +0 -178
- package/dist/provider/microsoft.mjs +0 -177
- package/dist/provider/oauth2.d.mts +0 -176
- package/dist/provider/oauth2.mjs +0 -222
- package/dist/provider/passkey.d.mts +0 -104
- package/dist/provider/passkey.mjs +0 -320
- package/dist/provider/password.d.mts +0 -412
- package/dist/provider/password.mjs +0 -363
- package/dist/provider/provider.d.mts +0 -227
- package/dist/provider/provider.mjs +0 -44
- package/dist/provider/reddit.d.mts +0 -107
- package/dist/provider/reddit.mjs +0 -127
- package/dist/provider/slack.d.mts +0 -114
- package/dist/provider/slack.mjs +0 -138
- package/dist/provider/spotify.d.mts +0 -113
- package/dist/provider/spotify.mjs +0 -135
- package/dist/provider/totp.d.mts +0 -112
- package/dist/provider/totp.mjs +0 -191
- package/dist/provider/twitch.d.mts +0 -108
- package/dist/provider/twitch.mjs +0 -131
- package/dist/provider/vercel.d.mts +0 -177
- package/dist/provider/vercel.mjs +0 -230
- package/dist/random.mjs +0 -86
- package/dist/revocation.d.mts +0 -55
- package/dist/revocation.mjs +0 -63
- package/dist/router/context.d.mts +0 -21
- package/dist/router/context.mjs +0 -193
- package/dist/router/cookies.d.mts +0 -8
- package/dist/router/cookies.mjs +0 -13
- package/dist/router/index.d.mts +0 -21
- package/dist/router/index.mjs +0 -107
- package/dist/router/matcher.d.mts +0 -15
- package/dist/router/matcher.mjs +0 -76
- package/dist/router/middleware/cors.d.mts +0 -15
- package/dist/router/middleware/cors.mjs +0 -114
- package/dist/router/safe-request.d.mts +0 -52
- package/dist/router/safe-request.mjs +0 -160
- package/dist/router/types.d.mts +0 -67
- package/dist/router/types.mjs +0 -1
- package/dist/router/variables.d.mts +0 -12
- package/dist/router/variables.mjs +0 -20
- package/dist/storage/memory.mjs +0 -125
- package/dist/storage/storage.d.mts +0 -179
- package/dist/storage/storage.mjs +0 -104
- package/dist/storage/turso.mjs +0 -117
- package/dist/storage/unstorage.mjs +0 -103
- package/dist/subject.d.mts +0 -62
- package/dist/subject.mjs +0 -36
- package/dist/themes/theme.d.mts +0 -209
- package/dist/themes/theme.mjs +0 -120
- package/dist/toolkit/client.d.mts +0 -169
- package/dist/toolkit/client.mjs +0 -209
- package/dist/toolkit/index.d.mts +0 -9
- package/dist/toolkit/index.mjs +0 -9
- package/dist/toolkit/providers/facebook.d.mts +0 -12
- package/dist/toolkit/providers/facebook.mjs +0 -16
- package/dist/toolkit/providers/github.d.mts +0 -12
- package/dist/toolkit/providers/github.mjs +0 -16
- package/dist/toolkit/providers/google.d.mts +0 -12
- package/dist/toolkit/providers/google.mjs +0 -20
- package/dist/toolkit/providers/strategy.d.mts +0 -40
- package/dist/toolkit/providers/strategy.mjs +0 -1
- package/dist/toolkit/storage.mjs +0 -157
- package/dist/toolkit/utils.mjs +0 -30
- package/dist/types.d.mts +0 -94
- package/dist/types.mjs +0 -1
- package/dist/ui/base.d.mts +0 -30
- package/dist/ui/base.mjs +0 -407
- package/dist/ui/code.d.mts +0 -43
- package/dist/ui/code.mjs +0 -173
- package/dist/ui/form.d.mts +0 -32
- package/dist/ui/form.mjs +0 -49
- package/dist/ui/icon.d.mts +0 -58
- package/dist/ui/icon.mjs +0 -247
- package/dist/ui/magiclink.d.mts +0 -41
- package/dist/ui/magiclink.mjs +0 -152
- package/dist/ui/passkey.d.mts +0 -27
- package/dist/ui/passkey.mjs +0 -323
- package/dist/ui/password.d.mts +0 -42
- package/dist/ui/password.mjs +0 -402
- package/dist/ui/select.d.mts +0 -34
- package/dist/ui/select.mjs +0 -98
- package/dist/ui/totp.d.mts +0 -34
- package/dist/ui/totp.mjs +0 -270
- package/dist/util.mjs +0 -128
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draftlab/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core implementation for @draftlab/auth",
|
|
6
6
|
"author": "Matheus Pergoli",
|
|
7
|
-
"main": "dist/index.
|
|
8
|
-
"typings": "dist/index.d.
|
|
7
|
+
"main": "dist/esm/index.js",
|
|
8
|
+
"typings": "dist/types/index.d.ts",
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"import": "./dist/index.
|
|
15
|
-
"types": "./dist/index.d.
|
|
14
|
+
"import": "./dist/esm/index.js",
|
|
15
|
+
"types": "./dist/types/index.d.ts"
|
|
16
16
|
},
|
|
17
17
|
"./*": {
|
|
18
|
-
"import": "./dist/*.
|
|
19
|
-
"types": "./dist/*.d.
|
|
18
|
+
"import": "./dist/esm/*.js",
|
|
19
|
+
"types": "./dist/types/*.d.ts"
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"sideEffects": false,
|
|
@@ -37,14 +37,12 @@
|
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^25.0.3",
|
|
41
|
-
"@types/qrcode": "^1.5.6",
|
|
42
|
-
"tsdown": "0.19.0-beta.5",
|
|
43
40
|
"typescript": "^5.9.3",
|
|
44
41
|
"@draftlab/tsconfig": "0.1.0"
|
|
45
42
|
},
|
|
46
43
|
"peerDependencies": {
|
|
47
44
|
"@libsql/client": "^0.15.0",
|
|
45
|
+
"hono": "^4.0.0",
|
|
48
46
|
"unstorage": "^1.0.0"
|
|
49
47
|
},
|
|
50
48
|
"peerDependenciesMeta": {
|
|
@@ -56,13 +54,9 @@
|
|
|
56
54
|
}
|
|
57
55
|
},
|
|
58
56
|
"dependencies": {
|
|
59
|
-
"@simplewebauthn/server": "^13.2.2",
|
|
60
57
|
"@standard-schema/spec": "^1.1.0",
|
|
61
58
|
"jose": "^6.1.3",
|
|
62
|
-
"
|
|
63
|
-
"preact": "^10.28.2",
|
|
64
|
-
"preact-render-to-string": "^6.6.5",
|
|
65
|
-
"qrcode": "^1.5.4"
|
|
59
|
+
"zod": "^4.3.6"
|
|
66
60
|
},
|
|
67
61
|
"engines": {
|
|
68
62
|
"node": ">=18"
|
|
@@ -71,7 +65,7 @@
|
|
|
71
65
|
"access": "public"
|
|
72
66
|
},
|
|
73
67
|
"scripts": {
|
|
74
|
-
"build": "
|
|
68
|
+
"build": "bun run scripts/build.ts",
|
|
75
69
|
"typecheck": "tsc --noEmit --emitDeclarationOnly false",
|
|
76
70
|
"clean": "rm -rf dist .turbo node_modules"
|
|
77
71
|
}
|
package/dist/adapters/node.d.mts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
-
|
|
3
|
-
//#region src/adapters/node.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Converts Node.js IncomingMessage to Web Standards Request
|
|
7
|
-
*/
|
|
8
|
-
declare const nodeRequestAdapter: (req: IncomingMessage) => Request;
|
|
9
|
-
/**
|
|
10
|
-
* Writes Web Standards Response to Node.js ServerResponse
|
|
11
|
-
*/
|
|
12
|
-
declare const nodeResponseAdapter: (response: Response, res: ServerResponse) => Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
* Creates a Node.js HTTP handler from a Web Standards fetch function
|
|
15
|
-
*/
|
|
16
|
-
declare const createNodeHandler: (fetchHandler: (request: Request) => Promise<Response>) => ((req: IncomingMessage, res: ServerResponse) => void);
|
|
17
|
-
//#endregion
|
|
18
|
-
export { createNodeHandler, nodeRequestAdapter, nodeResponseAdapter };
|
package/dist/adapters/node.mjs
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Readable } from "node:stream";
|
|
2
|
-
|
|
3
|
-
//#region src/adapters/node.ts
|
|
4
|
-
/**
|
|
5
|
-
* Converts Node.js IncomingMessage to Web Standards Request
|
|
6
|
-
*/
|
|
7
|
-
const nodeRequestAdapter = (req) => {
|
|
8
|
-
const sanitizedHost = (req.headers.host || "localhost").split(",")[0]?.trim();
|
|
9
|
-
const url = new URL(req.url || "/", `http://${sanitizedHost}`);
|
|
10
|
-
const headers = new Headers();
|
|
11
|
-
for (const [key, value] of Object.entries(req.headers)) if (value !== void 0) if (Array.isArray(value)) for (const v of value) headers.append(key, v);
|
|
12
|
-
else headers.set(key, value);
|
|
13
|
-
let body;
|
|
14
|
-
if (req.method !== "GET" && req.method !== "HEAD") body = Readable.toWeb(req);
|
|
15
|
-
return new Request(url.toString(), {
|
|
16
|
-
method: req.method || "GET",
|
|
17
|
-
headers,
|
|
18
|
-
body,
|
|
19
|
-
duplex: "half"
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Writes Web Standards Response to Node.js ServerResponse
|
|
24
|
-
*/
|
|
25
|
-
const nodeResponseAdapter = async (response, res) => {
|
|
26
|
-
res.statusCode = response.status;
|
|
27
|
-
res.statusMessage = response.statusText;
|
|
28
|
-
response.headers.forEach((value, key) => {
|
|
29
|
-
res.setHeader(key, value);
|
|
30
|
-
});
|
|
31
|
-
if (response.body) {
|
|
32
|
-
const reader = response.body.getReader();
|
|
33
|
-
try {
|
|
34
|
-
while (true) {
|
|
35
|
-
const { done, value } = await reader.read();
|
|
36
|
-
if (done) break;
|
|
37
|
-
if (!res.write(value)) await new Promise((resolve) => res.once("drain", resolve));
|
|
38
|
-
}
|
|
39
|
-
} finally {
|
|
40
|
-
reader.releaseLock();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
res.end();
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Creates a Node.js HTTP handler from a Web Standards fetch function
|
|
47
|
-
*/
|
|
48
|
-
const createNodeHandler = (fetchHandler) => {
|
|
49
|
-
return (req, res) => {
|
|
50
|
-
try {
|
|
51
|
-
fetchHandler(nodeRequestAdapter(req)).then((response) => nodeResponseAdapter(response, res)).catch((error) => {
|
|
52
|
-
console.error("Handler error:", error instanceof Error ? error.message : "Unknown error");
|
|
53
|
-
if (!res.headersSent) {
|
|
54
|
-
res.statusCode = 500;
|
|
55
|
-
res.end("Internal Server Error");
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error("Request adapter error:", error instanceof Error ? error.message : "Unknown error");
|
|
60
|
-
if (!res.headersSent) {
|
|
61
|
-
res.statusCode = 400;
|
|
62
|
-
res.end("Bad Request");
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
export { createNodeHandler, nodeRequestAdapter, nodeResponseAdapter };
|
package/dist/allow.mjs
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { isDomainMatch } from "./util.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/allow.ts
|
|
4
|
-
/**
|
|
5
|
-
* Default authorization check that validates client requests based on redirect URI security.
|
|
6
|
-
*
|
|
7
|
-
* ## Security Policy
|
|
8
|
-
* - **Localhost**: Always allowed (for development)
|
|
9
|
-
* - **Same domain**: Redirect URI must match request origin at TLD+1 level
|
|
10
|
-
* - **Cross-domain**: Rejected for security
|
|
11
|
-
*
|
|
12
|
-
* This prevents unauthorized applications from hijacking authorization codes by using
|
|
13
|
-
* malicious redirect URIs that don't belong to the legitimate client application.
|
|
14
|
-
*
|
|
15
|
-
* @param input - Client request details including ID and redirect URI
|
|
16
|
-
* @param req - The original HTTP request for domain comparison
|
|
17
|
-
* @returns Promise resolving to true if the request should be allowed
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```ts
|
|
21
|
-
* // Allowed: localhost development
|
|
22
|
-
* await defaultAllowCheck({
|
|
23
|
-
* clientID: "dev-app",
|
|
24
|
-
* redirectURI: "http://localhost:3000/callback"
|
|
25
|
-
* }, request) // → true
|
|
26
|
-
*
|
|
27
|
-
* // Allowed: same domain
|
|
28
|
-
* // Request from: https://myapp.com
|
|
29
|
-
* await defaultAllowCheck({
|
|
30
|
-
* clientID: "web-app",
|
|
31
|
-
* redirectURI: "https://auth.myapp.com/callback"
|
|
32
|
-
* }, request) // → true
|
|
33
|
-
*
|
|
34
|
-
* // Rejected: different domain
|
|
35
|
-
* // Request from: https://myapp.com
|
|
36
|
-
* await defaultAllowCheck({
|
|
37
|
-
* clientID: "malicious-app",
|
|
38
|
-
* redirectURI: "https://evil.com/steal-codes"
|
|
39
|
-
* }, request) // → false
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
const defaultAllowCheck = (input, req) => {
|
|
43
|
-
return Promise.resolve((() => {
|
|
44
|
-
let redirectHostname;
|
|
45
|
-
try {
|
|
46
|
-
redirectHostname = new URL(input.redirectURI).hostname;
|
|
47
|
-
} catch {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
if (redirectHostname === "localhost" || redirectHostname === "127.0.0.1") return true;
|
|
51
|
-
let currentHostname;
|
|
52
|
-
try {
|
|
53
|
-
const forwardedHost = req.headers.get("x-forwarded-host");
|
|
54
|
-
currentHostname = forwardedHost ? new URL(`https://${forwardedHost}`).hostname : new URL(req.url).hostname;
|
|
55
|
-
} catch {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
return isDomainMatch(redirectHostname, currentHostname);
|
|
59
|
-
})());
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
//#endregion
|
|
63
|
-
export { defaultAllowCheck };
|
package/dist/client.d.mts
DELETED
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
import { InvalidAccessTokenError, InvalidAuthorizationCodeError, InvalidRefreshTokenError, InvalidSubjectError } from "./error.mjs";
|
|
2
|
-
import { SubjectSchema } from "./subject.mjs";
|
|
3
|
-
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
4
|
-
|
|
5
|
-
//#region src/client.d.ts
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Result type for operations that can succeed or fail.
|
|
9
|
-
*
|
|
10
|
-
* @template T - The success data type
|
|
11
|
-
* @template E - The error type
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* const result = await client.exchange(code, redirectUri)
|
|
16
|
-
* if (result.success) {
|
|
17
|
-
* // Access token available: result.data.access
|
|
18
|
-
* } else {
|
|
19
|
-
* // Handle error: result.error.message
|
|
20
|
-
* }
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
type Result<T, E = Error> = {
|
|
24
|
-
success: true;
|
|
25
|
-
data: T;
|
|
26
|
-
} | {
|
|
27
|
-
success: false;
|
|
28
|
-
error: E;
|
|
29
|
-
};
|
|
30
|
-
interface FetchResponse {
|
|
31
|
-
ok: boolean;
|
|
32
|
-
text(): Promise<string>;
|
|
33
|
-
json(): Promise<unknown>;
|
|
34
|
-
}
|
|
35
|
-
type FetchLike = (url: string, init?: RequestInit) => Promise<FetchResponse>;
|
|
36
|
-
/**
|
|
37
|
-
* Authorization server metadata from well-known endpoints.
|
|
38
|
-
*/
|
|
39
|
-
interface WellKnown {
|
|
40
|
-
/**
|
|
41
|
-
* URI to the JWKS endpoint for token verification.
|
|
42
|
-
*/
|
|
43
|
-
jwks_uri: string;
|
|
44
|
-
/**
|
|
45
|
-
* URI to the token endpoint for authorization code exchange.
|
|
46
|
-
*/
|
|
47
|
-
token_endpoint: string;
|
|
48
|
-
/**
|
|
49
|
-
* URI to the authorization endpoint for starting flows.
|
|
50
|
-
*/
|
|
51
|
-
authorization_endpoint: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Tokens returned by the authorization server.
|
|
55
|
-
*/
|
|
56
|
-
interface Tokens {
|
|
57
|
-
/**
|
|
58
|
-
* Access token for making authenticated API requests.
|
|
59
|
-
*/
|
|
60
|
-
access: string;
|
|
61
|
-
/**
|
|
62
|
-
* Refresh token for obtaining new access tokens.
|
|
63
|
-
*/
|
|
64
|
-
refresh: string;
|
|
65
|
-
/**
|
|
66
|
-
* Number of seconds until the access token expires.
|
|
67
|
-
*/
|
|
68
|
-
expiresIn: number;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Challenge data for PKCE flows.
|
|
72
|
-
*/
|
|
73
|
-
type Challenge = {
|
|
74
|
-
/**
|
|
75
|
-
* State parameter for CSRF protection.
|
|
76
|
-
*/
|
|
77
|
-
state: string;
|
|
78
|
-
/**
|
|
79
|
-
* PKCE code verifier for token exchange.
|
|
80
|
-
*/
|
|
81
|
-
verifier?: string;
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* Client configuration options.
|
|
85
|
-
*/
|
|
86
|
-
interface ClientInput {
|
|
87
|
-
/**
|
|
88
|
-
* Client ID that identifies your application.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* {
|
|
93
|
-
* clientID: "my-web-app"
|
|
94
|
-
* }
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
|
-
clientID: string;
|
|
98
|
-
/**
|
|
99
|
-
* Base URL of your Draft Auth server.
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* ```ts
|
|
103
|
-
* {
|
|
104
|
-
* issuer: "https://auth.myserver.com"
|
|
105
|
-
* }
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
issuer: string;
|
|
109
|
-
/**
|
|
110
|
-
* Optionally, override the internally used fetch function.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```ts
|
|
114
|
-
* {
|
|
115
|
-
* fetch: customFetch
|
|
116
|
-
* }
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
fetch?: FetchLike;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Options for starting an authorization flow.
|
|
123
|
-
*/
|
|
124
|
-
interface AuthorizeOptions {
|
|
125
|
-
/**
|
|
126
|
-
* Enable PKCE flow for enhanced security.
|
|
127
|
-
*
|
|
128
|
-
* Recommended for single-page applications and mobile apps.
|
|
129
|
-
*
|
|
130
|
-
* @default false
|
|
131
|
-
* @example
|
|
132
|
-
* ```ts
|
|
133
|
-
* {
|
|
134
|
-
* pkce: true
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
pkce?: boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Specific authentication provider to use.
|
|
141
|
-
*
|
|
142
|
-
* If not specified, users see a provider selection screen
|
|
143
|
-
* or are redirected to the single configured provider.
|
|
144
|
-
*
|
|
145
|
-
* @example
|
|
146
|
-
* ```ts
|
|
147
|
-
* {
|
|
148
|
-
* provider: "google"
|
|
149
|
-
* }
|
|
150
|
-
* ```
|
|
151
|
-
*/
|
|
152
|
-
provider?: string;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Result of starting an authorization flow.
|
|
156
|
-
*/
|
|
157
|
-
interface AuthorizeResult {
|
|
158
|
-
/**
|
|
159
|
-
* Challenge data needed for PKCE flows.
|
|
160
|
-
*
|
|
161
|
-
* Store this securely and use when exchanging the code.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```ts
|
|
165
|
-
* sessionStorage.setItem("challenge", JSON.stringify(challenge))
|
|
166
|
-
* ```
|
|
167
|
-
*/
|
|
168
|
-
challenge: Challenge;
|
|
169
|
-
/**
|
|
170
|
-
* Authorization URL to redirect the user to.
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```ts
|
|
174
|
-
* window.location.href = url
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
url: string;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Options for token refresh operations.
|
|
181
|
-
*/
|
|
182
|
-
interface RefreshOptions {
|
|
183
|
-
/**
|
|
184
|
-
* Current access token to check before refreshing.
|
|
185
|
-
*
|
|
186
|
-
* Helps avoid unnecessary refresh requests.
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```ts
|
|
190
|
-
* {
|
|
191
|
-
* access: currentAccessToken
|
|
192
|
-
* }
|
|
193
|
-
* ```
|
|
194
|
-
*/
|
|
195
|
-
access?: string;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Options for token verification.
|
|
199
|
-
*/
|
|
200
|
-
interface VerifyOptions {
|
|
201
|
-
/**
|
|
202
|
-
* Refresh token for automatic refresh if access token is expired.
|
|
203
|
-
*
|
|
204
|
-
* If passed in, this will automatically refresh the access token if it has expired.
|
|
205
|
-
*
|
|
206
|
-
* @example
|
|
207
|
-
* ```ts
|
|
208
|
-
* {
|
|
209
|
-
* refresh: refreshToken
|
|
210
|
-
* }
|
|
211
|
-
* ```
|
|
212
|
-
*/
|
|
213
|
-
refresh?: string;
|
|
214
|
-
/**
|
|
215
|
-
* Expected issuer for validation.
|
|
216
|
-
* @internal
|
|
217
|
-
*/
|
|
218
|
-
issuer?: string;
|
|
219
|
-
/**
|
|
220
|
-
* Expected audience for validation.
|
|
221
|
-
* Defaults to clientID for security. Override only if you know what you're doing.
|
|
222
|
-
* @internal
|
|
223
|
-
*/
|
|
224
|
-
audience?: string;
|
|
225
|
-
/**
|
|
226
|
-
* Custom fetch for HTTP requests.
|
|
227
|
-
*
|
|
228
|
-
* Optionally, override the internally used fetch function.
|
|
229
|
-
*/
|
|
230
|
-
fetch?: FetchLike;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Result of successful token verification.
|
|
234
|
-
*/
|
|
235
|
-
interface VerifyResult<T extends SubjectSchema> {
|
|
236
|
-
/**
|
|
237
|
-
* New tokens if access token was refreshed during verification.
|
|
238
|
-
*/
|
|
239
|
-
tokens?: Tokens;
|
|
240
|
-
/**
|
|
241
|
-
* Audience (client ID) the token was issued for.
|
|
242
|
-
* @internal
|
|
243
|
-
*/
|
|
244
|
-
aud: string;
|
|
245
|
-
/**
|
|
246
|
-
* Decoded subject information from the access token.
|
|
247
|
-
*
|
|
248
|
-
* Contains user data that was encoded when the token was issued.
|
|
249
|
-
*/
|
|
250
|
-
subject: { [K in keyof T]: {
|
|
251
|
-
type: K;
|
|
252
|
-
properties: StandardSchemaV1.InferOutput<T[K]>;
|
|
253
|
-
} }[keyof T];
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Options for token revocation.
|
|
257
|
-
*/
|
|
258
|
-
interface RevokeOptions {
|
|
259
|
-
/**
|
|
260
|
-
* Optional hint about the token type.
|
|
261
|
-
* Can be "access_token" or "refresh_token".
|
|
262
|
-
*
|
|
263
|
-
* Helps the server optimize token lookup.
|
|
264
|
-
*
|
|
265
|
-
* @example
|
|
266
|
-
* ```ts
|
|
267
|
-
* {
|
|
268
|
-
* tokenTypeHint: "refresh_token"
|
|
269
|
-
* }
|
|
270
|
-
* ```
|
|
271
|
-
*/
|
|
272
|
-
tokenTypeHint?: "access_token" | "refresh_token";
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Draft Auth client with OAuth 2.0 operations.
|
|
276
|
-
*/
|
|
277
|
-
interface Client {
|
|
278
|
-
/**
|
|
279
|
-
* Start an OAuth authorization flow.
|
|
280
|
-
*
|
|
281
|
-
* @param redirectURI - Where users will be sent after authorization
|
|
282
|
-
* @param response - Response type ("code" or "token")
|
|
283
|
-
* @param opts - Additional authorization options
|
|
284
|
-
* @returns Authorization URL and challenge data
|
|
285
|
-
*
|
|
286
|
-
* @example Basic flow
|
|
287
|
-
* ```ts
|
|
288
|
-
* const result = await client.authorize(
|
|
289
|
-
* "https://myapp.com/callback",
|
|
290
|
-
* "code"
|
|
291
|
-
* )
|
|
292
|
-
* if (result.success) {
|
|
293
|
-
* window.location.href = result.data.url
|
|
294
|
-
* }
|
|
295
|
-
* ```
|
|
296
|
-
*
|
|
297
|
-
* @example PKCE flow
|
|
298
|
-
* ```ts
|
|
299
|
-
* const result = await client.authorize(
|
|
300
|
-
* "https://spa.example.com/callback",
|
|
301
|
-
* "code",
|
|
302
|
-
* { pkce: true, scopes: ["read", "write"] }
|
|
303
|
-
* )
|
|
304
|
-
* if (result.success) {
|
|
305
|
-
* sessionStorage.setItem("challenge", JSON.stringify(result.data.challenge))
|
|
306
|
-
* window.location.href = result.data.url
|
|
307
|
-
* }
|
|
308
|
-
* ```
|
|
309
|
-
*/
|
|
310
|
-
authorize(redirectURI: string, response: "code" | "token", opts?: AuthorizeOptions): Promise<Result<AuthorizeResult>>;
|
|
311
|
-
/**
|
|
312
|
-
* Exchange authorization code for tokens.
|
|
313
|
-
*
|
|
314
|
-
* @param code - Authorization code from the callback
|
|
315
|
-
* @param redirectURI - Same redirect URI used in authorization
|
|
316
|
-
* @param verifier - PKCE code verifier (required for PKCE flows)
|
|
317
|
-
* @returns Access tokens and metadata
|
|
318
|
-
*
|
|
319
|
-
* @example Basic exchange
|
|
320
|
-
* ```ts
|
|
321
|
-
* const urlParams = new URLSearchParams(window.location.search)
|
|
322
|
-
* const code = urlParams.get('code')
|
|
323
|
-
*
|
|
324
|
-
* if (code) {
|
|
325
|
-
* const result = await client.exchange(code, "https://myapp.com/callback")
|
|
326
|
-
* if (result.success) {
|
|
327
|
-
* const { access, refresh } = result.data
|
|
328
|
-
* // Store tokens securely
|
|
329
|
-
* }
|
|
330
|
-
* }
|
|
331
|
-
* ```
|
|
332
|
-
*
|
|
333
|
-
* @example PKCE exchange
|
|
334
|
-
* ```ts
|
|
335
|
-
* const challenge = JSON.parse(sessionStorage.getItem("challenge") || "{}")
|
|
336
|
-
* const code = new URLSearchParams(window.location.search).get('code')
|
|
337
|
-
*
|
|
338
|
-
* if (code && challenge.verifier) {
|
|
339
|
-
* const result = await client.exchange(
|
|
340
|
-
* code,
|
|
341
|
-
* "https://spa.example.com/callback",
|
|
342
|
-
* challenge.verifier
|
|
343
|
-
* )
|
|
344
|
-
* if (result.success) {
|
|
345
|
-
* sessionStorage.removeItem("challenge")
|
|
346
|
-
* // Handle tokens
|
|
347
|
-
* }
|
|
348
|
-
* }
|
|
349
|
-
* ```
|
|
350
|
-
*/
|
|
351
|
-
exchange(code: string, redirectURI: string, verifier?: string): Promise<Result<Tokens, InvalidAuthorizationCodeError>>;
|
|
352
|
-
/**
|
|
353
|
-
* Refresh an access token using a refresh token.
|
|
354
|
-
*
|
|
355
|
-
* @param refresh - Refresh token to use
|
|
356
|
-
* @param opts - Additional refresh options
|
|
357
|
-
* @returns New tokens if refresh was needed
|
|
358
|
-
*
|
|
359
|
-
* @example Basic refresh
|
|
360
|
-
* ```ts
|
|
361
|
-
* const result = await client.refresh(storedRefreshToken)
|
|
362
|
-
*
|
|
363
|
-
* if (result.success && result.data.tokens) {
|
|
364
|
-
* const { access, refresh: newRefresh } = result.data.tokens
|
|
365
|
-
* updateStoredTokens(access, newRefresh)
|
|
366
|
-
* } else if (result.success) {
|
|
367
|
-
* // Token still valid
|
|
368
|
-
* } else {
|
|
369
|
-
* redirectToLogin()
|
|
370
|
-
* }
|
|
371
|
-
* ```
|
|
372
|
-
*/
|
|
373
|
-
refresh(refresh: string, opts?: RefreshOptions): Promise<Result<{
|
|
374
|
-
tokens?: Tokens;
|
|
375
|
-
}, InvalidRefreshTokenError | InvalidAccessTokenError>>;
|
|
376
|
-
/**
|
|
377
|
-
* Verify and decode an access token.
|
|
378
|
-
*
|
|
379
|
-
* @param subjects - Subject schema used when creating the issuer
|
|
380
|
-
* @param token - Access token to verify
|
|
381
|
-
* @param options - Additional verification options
|
|
382
|
-
* @returns Decoded token data and user information
|
|
383
|
-
*
|
|
384
|
-
* @example Basic verification
|
|
385
|
-
* ```ts
|
|
386
|
-
* const result = await client.verify(subjects, accessToken)
|
|
387
|
-
*
|
|
388
|
-
* if (result.success) {
|
|
389
|
-
* const { subject, scopes } = result.data
|
|
390
|
-
* // Access user ID: subject.properties.userID
|
|
391
|
-
* // Access scopes: scopes?.join(', ')
|
|
392
|
-
* }
|
|
393
|
-
* ```
|
|
394
|
-
*
|
|
395
|
-
* @example With automatic refresh
|
|
396
|
-
* ```ts
|
|
397
|
-
* const result = await client.verify(subjects, accessToken, {
|
|
398
|
-
* refresh: refreshToken
|
|
399
|
-
* })
|
|
400
|
-
*
|
|
401
|
-
* if (result.success) {
|
|
402
|
-
* if (result.data.tokens) {
|
|
403
|
-
* // Tokens were refreshed
|
|
404
|
-
* updateStoredTokens(result.data.tokens.access, result.data.tokens.refresh)
|
|
405
|
-
* }
|
|
406
|
-
* // Use verified subject data
|
|
407
|
-
* const user = result.data.subject.properties
|
|
408
|
-
* }
|
|
409
|
-
* ```
|
|
410
|
-
*/
|
|
411
|
-
verify<T extends SubjectSchema>(subjects: T, token: string, options?: VerifyOptions): Promise<Result<VerifyResult<T>, InvalidRefreshTokenError | InvalidAccessTokenError | InvalidSubjectError>>;
|
|
412
|
-
/**
|
|
413
|
-
* Revoke a token (access or refresh token).
|
|
414
|
-
*
|
|
415
|
-
* Once revoked, the token cannot be used to access resources or refresh.
|
|
416
|
-
* Useful for implementing logout functionality.
|
|
417
|
-
*
|
|
418
|
-
* @param token - The token to revoke
|
|
419
|
-
* @param opts - Additional revocation options
|
|
420
|
-
* @returns Empty result on success
|
|
421
|
-
*
|
|
422
|
-
* @example Logout with refresh token revocation
|
|
423
|
-
* ```ts
|
|
424
|
-
* const result = await client.revoke(refreshToken, {
|
|
425
|
-
* tokenTypeHint: "refresh_token"
|
|
426
|
-
* })
|
|
427
|
-
*
|
|
428
|
-
* if (result.success) {
|
|
429
|
-
* // Token revoked successfully, user is logged out
|
|
430
|
-
* clearStoredTokens()
|
|
431
|
-
* redirectToHome()
|
|
432
|
-
* } else {
|
|
433
|
-
* // Revocation failed, but still clear tokens on client
|
|
434
|
-
* clearStoredTokens()
|
|
435
|
-
* }
|
|
436
|
-
* ```
|
|
437
|
-
*/
|
|
438
|
-
revoke(token: string, opts?: RevokeOptions): Promise<Result<void>>;
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Create a Draft Auth client.
|
|
442
|
-
*
|
|
443
|
-
* @param input - Client configuration
|
|
444
|
-
* @returns Configured client instance
|
|
445
|
-
*
|
|
446
|
-
* @example Basic setup
|
|
447
|
-
* ```ts
|
|
448
|
-
* const client = createClient({
|
|
449
|
-
* clientID: "my-web-app",
|
|
450
|
-
* issuer: "https://auth.mycompany.com"
|
|
451
|
-
* })
|
|
452
|
-
* ```
|
|
453
|
-
*/
|
|
454
|
-
declare const createClient: (input: ClientInput) => Client;
|
|
455
|
-
//#endregion
|
|
456
|
-
export { AuthorizeOptions, AuthorizeResult, Challenge, Client, ClientInput, RefreshOptions, Result, RevokeOptions, Tokens, VerifyOptions, VerifyResult, WellKnown, createClient };
|