@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/dist/ui/totp.mjs
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { Layout, renderToHTML } from "./base.mjs";
|
|
2
|
-
import { FormAlert } from "./form.mjs";
|
|
3
|
-
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
4
|
-
import QRCode from "qrcode";
|
|
5
|
-
|
|
6
|
-
//#region src/ui/totp.tsx
|
|
7
|
-
const DEFAULT_COPY = {
|
|
8
|
-
setup_manual_entry: "Can't scan? Enter this code manually:",
|
|
9
|
-
setup_backup_codes_title: "Save your backup codes",
|
|
10
|
-
setup_backup_codes_description: "Store these backup codes in a safe place. You can use them to access your account if you lose your device.",
|
|
11
|
-
button_continue: "Continue",
|
|
12
|
-
link_use_recovery: "Use backup code instead",
|
|
13
|
-
link_back_to_totp: "Back to authenticator code",
|
|
14
|
-
input_token: "000000",
|
|
15
|
-
input_recovery_code: "XXXX-XXXX"
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Creates a complete UI configuration for TOTP authentication
|
|
19
|
-
*/
|
|
20
|
-
const TOTPUI = (options = {}) => {
|
|
21
|
-
const { qrSize = 200, showManualEntry = true } = options;
|
|
22
|
-
const copy = {
|
|
23
|
-
...DEFAULT_COPY,
|
|
24
|
-
...options.copy
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Generates QR code as data URL using the qrcode library
|
|
28
|
-
*/
|
|
29
|
-
const generateQRCode = async (text) => {
|
|
30
|
-
try {
|
|
31
|
-
return await QRCode.toDataURL(text, {
|
|
32
|
-
width: qrSize,
|
|
33
|
-
margin: 1,
|
|
34
|
-
color: {
|
|
35
|
-
dark: "#000000",
|
|
36
|
-
light: "#FFFFFF"
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
} catch (error) {
|
|
40
|
-
console.error("QR Code generation failed:", error);
|
|
41
|
-
return "";
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Renders the setup form with QR code and backup codes
|
|
46
|
-
*/
|
|
47
|
-
const renderRegister = async (qrCodeUrl, secret, backupCodes, error, email) => {
|
|
48
|
-
if (!qrCodeUrl) return /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsxs("form", {
|
|
49
|
-
"data-component": "form",
|
|
50
|
-
method: "post",
|
|
51
|
-
action: "./register",
|
|
52
|
-
children: [
|
|
53
|
-
/* @__PURE__ */ jsx(FormAlert, { message: error }),
|
|
54
|
-
/* @__PURE__ */ jsx("input", {
|
|
55
|
-
type: "email",
|
|
56
|
-
name: "email",
|
|
57
|
-
placeholder: "Email",
|
|
58
|
-
autoComplete: "email",
|
|
59
|
-
"data-component": "input",
|
|
60
|
-
required: true
|
|
61
|
-
}),
|
|
62
|
-
/* @__PURE__ */ jsx("input", {
|
|
63
|
-
type: "hidden",
|
|
64
|
-
name: "action",
|
|
65
|
-
value: "generate"
|
|
66
|
-
}),
|
|
67
|
-
/* @__PURE__ */ jsx("button", {
|
|
68
|
-
type: "submit",
|
|
69
|
-
"data-component": "button",
|
|
70
|
-
children: "Generate QR Code"
|
|
71
|
-
}),
|
|
72
|
-
/* @__PURE__ */ jsx("div", {
|
|
73
|
-
"data-component": "form-footer",
|
|
74
|
-
children: /* @__PURE__ */ jsxs("span", { children: [
|
|
75
|
-
"Already have TOTP?",
|
|
76
|
-
" ",
|
|
77
|
-
/* @__PURE__ */ jsx("a", {
|
|
78
|
-
href: "./authorize",
|
|
79
|
-
"data-component": "link",
|
|
80
|
-
children: "Login"
|
|
81
|
-
})
|
|
82
|
-
] })
|
|
83
|
-
})
|
|
84
|
-
]
|
|
85
|
-
}) });
|
|
86
|
-
const qrCodeDataUrl = await generateQRCode(qrCodeUrl);
|
|
87
|
-
return /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsxs("form", {
|
|
88
|
-
"data-component": "form",
|
|
89
|
-
method: "post",
|
|
90
|
-
action: "./register",
|
|
91
|
-
children: [
|
|
92
|
-
/* @__PURE__ */ jsx(FormAlert, { message: error }),
|
|
93
|
-
email && /* @__PURE__ */ jsx("input", {
|
|
94
|
-
type: "hidden",
|
|
95
|
-
name: "email",
|
|
96
|
-
value: email
|
|
97
|
-
}),
|
|
98
|
-
qrCodeDataUrl && /* @__PURE__ */ jsx("img", {
|
|
99
|
-
src: qrCodeDataUrl,
|
|
100
|
-
alt: "TOTP QR Code",
|
|
101
|
-
width: qrSize,
|
|
102
|
-
height: qrSize,
|
|
103
|
-
style: {
|
|
104
|
-
display: "block",
|
|
105
|
-
margin: "0 auto"
|
|
106
|
-
}
|
|
107
|
-
}),
|
|
108
|
-
showManualEntry && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
109
|
-
"data-component": "description",
|
|
110
|
-
children: copy.setup_manual_entry
|
|
111
|
-
}), /* @__PURE__ */ jsx("code", {
|
|
112
|
-
style: {
|
|
113
|
-
display: "block",
|
|
114
|
-
textAlign: "center",
|
|
115
|
-
margin: "8px 0"
|
|
116
|
-
},
|
|
117
|
-
children: secret
|
|
118
|
-
})] }),
|
|
119
|
-
/* @__PURE__ */ jsx("input", {
|
|
120
|
-
type: "text",
|
|
121
|
-
name: "token",
|
|
122
|
-
placeholder: copy.input_token,
|
|
123
|
-
pattern: "[0-9]{6}",
|
|
124
|
-
maxLength: 6,
|
|
125
|
-
minLength: 6,
|
|
126
|
-
autoComplete: "one-time-code",
|
|
127
|
-
"data-component": "input",
|
|
128
|
-
required: true
|
|
129
|
-
}),
|
|
130
|
-
/* @__PURE__ */ jsx("button", {
|
|
131
|
-
type: "submit",
|
|
132
|
-
"data-component": "button",
|
|
133
|
-
children: copy.button_continue
|
|
134
|
-
}),
|
|
135
|
-
backupCodes.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
136
|
-
/* @__PURE__ */ jsx("h3", {
|
|
137
|
-
style: { textAlign: "center" },
|
|
138
|
-
children: copy.setup_backup_codes_title
|
|
139
|
-
}),
|
|
140
|
-
/* @__PURE__ */ jsx("p", {
|
|
141
|
-
"data-component": "description",
|
|
142
|
-
children: copy.setup_backup_codes_description
|
|
143
|
-
}),
|
|
144
|
-
/* @__PURE__ */ jsx("div", {
|
|
145
|
-
style: {
|
|
146
|
-
display: "grid",
|
|
147
|
-
gridTemplateColumns: "repeat(2, 1fr)",
|
|
148
|
-
gap: "8px",
|
|
149
|
-
margin: "16px 0"
|
|
150
|
-
},
|
|
151
|
-
children: backupCodes.map((code, index) => /* @__PURE__ */ jsx("code", {
|
|
152
|
-
"data-component": "button",
|
|
153
|
-
children: code
|
|
154
|
-
}, `${code}-${index + Math.random()}`))
|
|
155
|
-
})
|
|
156
|
-
] })
|
|
157
|
-
]
|
|
158
|
-
}) });
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* Renders the authorize form (main TOTP login page following passkey pattern)
|
|
162
|
-
*/
|
|
163
|
-
const renderAuthorize = (error) => /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsxs("form", {
|
|
164
|
-
"data-component": "form",
|
|
165
|
-
method: "post",
|
|
166
|
-
action: "./authorize",
|
|
167
|
-
children: [
|
|
168
|
-
/* @__PURE__ */ jsx(FormAlert, { message: error }),
|
|
169
|
-
/* @__PURE__ */ jsx("input", {
|
|
170
|
-
type: "email",
|
|
171
|
-
name: "email",
|
|
172
|
-
placeholder: "Email",
|
|
173
|
-
autoComplete: "email",
|
|
174
|
-
"data-component": "input",
|
|
175
|
-
required: true
|
|
176
|
-
}),
|
|
177
|
-
/* @__PURE__ */ jsx("input", {
|
|
178
|
-
type: "text",
|
|
179
|
-
name: "token",
|
|
180
|
-
placeholder: copy.input_token,
|
|
181
|
-
pattern: "[0-9]{6}",
|
|
182
|
-
maxLength: 6,
|
|
183
|
-
minLength: 6,
|
|
184
|
-
autoComplete: "one-time-code",
|
|
185
|
-
"data-component": "input",
|
|
186
|
-
required: true
|
|
187
|
-
}),
|
|
188
|
-
/* @__PURE__ */ jsx("button", {
|
|
189
|
-
type: "submit",
|
|
190
|
-
"data-component": "button",
|
|
191
|
-
children: copy.button_continue
|
|
192
|
-
}),
|
|
193
|
-
/* @__PURE__ */ jsxs("div", {
|
|
194
|
-
"data-component": "form-footer",
|
|
195
|
-
children: [/* @__PURE__ */ jsxs("span", { children: [
|
|
196
|
-
"Don't have TOTP setup?",
|
|
197
|
-
" ",
|
|
198
|
-
/* @__PURE__ */ jsx("a", {
|
|
199
|
-
href: "./register",
|
|
200
|
-
"data-component": "link",
|
|
201
|
-
children: "Register"
|
|
202
|
-
})
|
|
203
|
-
] }), /* @__PURE__ */ jsx("a", {
|
|
204
|
-
href: "./recovery",
|
|
205
|
-
"data-component": "link",
|
|
206
|
-
children: copy.link_use_recovery
|
|
207
|
-
})]
|
|
208
|
-
})
|
|
209
|
-
]
|
|
210
|
-
}) });
|
|
211
|
-
/**
|
|
212
|
-
* Renders the recovery form
|
|
213
|
-
*/
|
|
214
|
-
const renderRecovery = (error) => /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsxs("form", {
|
|
215
|
-
"data-component": "form",
|
|
216
|
-
method: "post",
|
|
217
|
-
action: "./recovery",
|
|
218
|
-
children: [
|
|
219
|
-
/* @__PURE__ */ jsx(FormAlert, { message: error }),
|
|
220
|
-
/* @__PURE__ */ jsx("input", {
|
|
221
|
-
type: "email",
|
|
222
|
-
name: "email",
|
|
223
|
-
placeholder: "Email",
|
|
224
|
-
autoComplete: "email",
|
|
225
|
-
"data-component": "input",
|
|
226
|
-
required: true
|
|
227
|
-
}),
|
|
228
|
-
/* @__PURE__ */ jsx("input", {
|
|
229
|
-
type: "text",
|
|
230
|
-
name: "code",
|
|
231
|
-
placeholder: copy.input_recovery_code,
|
|
232
|
-
pattern: "[A-Z0-9]{4}-[A-Z0-9]{4}",
|
|
233
|
-
maxLength: 9,
|
|
234
|
-
autoComplete: "off",
|
|
235
|
-
"data-component": "input",
|
|
236
|
-
required: true
|
|
237
|
-
}),
|
|
238
|
-
/* @__PURE__ */ jsx("button", {
|
|
239
|
-
type: "submit",
|
|
240
|
-
"data-component": "button",
|
|
241
|
-
children: copy.button_continue
|
|
242
|
-
}),
|
|
243
|
-
/* @__PURE__ */ jsx("div", {
|
|
244
|
-
"data-component": "form-footer",
|
|
245
|
-
children: /* @__PURE__ */ jsx("a", {
|
|
246
|
-
href: "./authorize",
|
|
247
|
-
"data-component": "link",
|
|
248
|
-
children: copy.link_back_to_totp
|
|
249
|
-
})
|
|
250
|
-
})
|
|
251
|
-
]
|
|
252
|
-
}) });
|
|
253
|
-
return {
|
|
254
|
-
authorize: async (_req, error) => {
|
|
255
|
-
const jsx$1 = renderAuthorize(error);
|
|
256
|
-
return new Response(renderToHTML(jsx$1), { headers: { "Content-Type": "text/html" } });
|
|
257
|
-
},
|
|
258
|
-
register: async (_req, qrCodeUrl, secret, backupCodes, error, email) => {
|
|
259
|
-
const jsx$1 = await renderRegister(qrCodeUrl, secret, backupCodes, error, email);
|
|
260
|
-
return new Response(renderToHTML(jsx$1), { headers: { "Content-Type": "text/html" } });
|
|
261
|
-
},
|
|
262
|
-
recovery: async (_req, error) => {
|
|
263
|
-
const jsx$1 = renderRecovery(error);
|
|
264
|
-
return new Response(renderToHTML(jsx$1), { headers: { "Content-Type": "text/html" } });
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
//#endregion
|
|
270
|
-
export { TOTPUI };
|
package/dist/util.mjs
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
//#region src/util.ts
|
|
2
|
-
/**
|
|
3
|
-
* Constructs a complete URL relative to the current request context.
|
|
4
|
-
* Handles proxy headers (x-forwarded-*) to ensure correct URL generation
|
|
5
|
-
* in containerized and load-balanced environments.
|
|
6
|
-
*
|
|
7
|
-
* @param ctx - Router context containing request information
|
|
8
|
-
* @param path - Relative path to append to the base URL
|
|
9
|
-
* @returns Complete URL string with proper protocol, host, and port
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const callbackUrl = getRelativeUrl(ctx, "/callback")
|
|
14
|
-
* // Returns: "https://myapp.com/auth/callback"
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
const getRelativeUrl = (ctx, path) => {
|
|
18
|
-
const result = new URL(path, ctx.request.url);
|
|
19
|
-
result.host = ctx.header("x-forwarded-host") || result.host;
|
|
20
|
-
result.protocol = ctx.header("x-forwarded-proto") || result.protocol;
|
|
21
|
-
result.port = ctx.header("x-forwarded-port") || result.port;
|
|
22
|
-
return result.toString();
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* List of known two-part top-level domains that require special handling
|
|
26
|
-
* for domain matching. These domains have an additional level that should
|
|
27
|
-
* be considered when determining effective domain boundaries.
|
|
28
|
-
*/
|
|
29
|
-
const twoPartTlds = [
|
|
30
|
-
"co.uk",
|
|
31
|
-
"co.jp",
|
|
32
|
-
"co.kr",
|
|
33
|
-
"co.nz",
|
|
34
|
-
"co.za",
|
|
35
|
-
"co.in",
|
|
36
|
-
"com.au",
|
|
37
|
-
"com.br",
|
|
38
|
-
"com.cn",
|
|
39
|
-
"com.mx",
|
|
40
|
-
"com.tw",
|
|
41
|
-
"net.au",
|
|
42
|
-
"org.uk",
|
|
43
|
-
"ne.jp",
|
|
44
|
-
"ac.uk",
|
|
45
|
-
"gov.uk",
|
|
46
|
-
"edu.au",
|
|
47
|
-
"gov.au"
|
|
48
|
-
];
|
|
49
|
-
/**
|
|
50
|
-
* Determines if two domain names are considered a match for security purposes.
|
|
51
|
-
* Uses effective TLD+1 matching to allow subdomains while preventing
|
|
52
|
-
* unauthorized cross-domain requests.
|
|
53
|
-
*
|
|
54
|
-
* @param a - First domain name to compare
|
|
55
|
-
* @param b - Second domain name to compare
|
|
56
|
-
* @returns True if domains are considered a security match
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```ts
|
|
60
|
-
* isDomainMatch("app.example.com", "auth.example.com") // true
|
|
61
|
-
* isDomainMatch("example.com", "evil.com") // false
|
|
62
|
-
* isDomainMatch("app.co.uk", "auth.co.uk") // true (handles two-part TLD)
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
const isDomainMatch = (a, b) => {
|
|
66
|
-
if (a === b) return true;
|
|
67
|
-
const partsA = a.split(".");
|
|
68
|
-
const partsB = b.split(".");
|
|
69
|
-
const numParts = twoPartTlds.some((tld) => a.endsWith(`.${tld}`) || b.endsWith(`.${tld}`)) ? -3 : -2;
|
|
70
|
-
const min = Math.min(partsA.length, partsB.length, numParts);
|
|
71
|
-
return partsA.slice(min).join(".") === partsB.slice(min).join(".");
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Creates a lazy-evaluated function that caches the result of the first execution.
|
|
75
|
-
* Subsequent calls return the cached value without re-executing the function.
|
|
76
|
-
*
|
|
77
|
-
* @template T - The return type of the lazy function
|
|
78
|
-
* @param fn - Function to execute lazily
|
|
79
|
-
* @returns Function that returns the cached result
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```ts
|
|
83
|
-
* const expensiveOperation = lazy(() => {
|
|
84
|
-
* // Computing... (only logs once)
|
|
85
|
-
* return heavyComputation()
|
|
86
|
-
* })
|
|
87
|
-
*
|
|
88
|
-
* const result1 = expensiveOperation() // Executes and caches
|
|
89
|
-
* const result2 = expensiveOperation() // Returns cached value
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
const lazy = (fn) => {
|
|
93
|
-
let value;
|
|
94
|
-
let hasValue = false;
|
|
95
|
-
return () => {
|
|
96
|
-
if (!hasValue) {
|
|
97
|
-
value = fn();
|
|
98
|
-
hasValue = true;
|
|
99
|
-
}
|
|
100
|
-
return value;
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Utility function to immediately invoke a function and return its result.
|
|
105
|
-
* Useful for complex conditional rendering logic in JSX/TSX where you want
|
|
106
|
-
* to use if/else statements instead of ternary operators.
|
|
107
|
-
*
|
|
108
|
-
* @template T - The return type of the function
|
|
109
|
-
* @param fn - Function to execute immediately
|
|
110
|
-
* @returns The result of executing the function
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```tsx
|
|
114
|
-
* return (
|
|
115
|
-
* <div>
|
|
116
|
-
* {run(() => {
|
|
117
|
-
* if (state === "loading") return <Spinner />
|
|
118
|
-
* if (state === "error") return <Error />
|
|
119
|
-
* return <Content />
|
|
120
|
-
* })}
|
|
121
|
-
* </div>
|
|
122
|
-
* )
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
const run = (fn) => fn();
|
|
126
|
-
|
|
127
|
-
//#endregion
|
|
128
|
-
export { getRelativeUrl, isDomainMatch, lazy, run };
|