@camstack/addon-auth 1.1.1 → 1.1.3
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/{dist-JmuFs-U5.mjs → dist-mmJDfwXE.js} +335 -8
- package/dist/{dist-CXCR7sEk.js → dist-suALViLT.mjs} +276 -37
- package/dist/magic-link/auth-magic-link.addon.js +104 -30
- package/dist/magic-link/auth-magic-link.addon.mjs +104 -30
- package/dist/oidc/auth-oidc.addon.js +36 -8
- package/dist/oidc/auth-oidc.addon.mjs +36 -8
- package/dist/webauthn/_stub.js +568 -0
- package/dist/webauthn/_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-Bg_T1-iY.mjs +156 -0
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-EnxrfqY5.mjs +26 -0
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-CQ-aEQ9b.mjs +26 -0
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react__loadShare__.js-BIIa6vDX.mjs +26 -0
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-BL2etuqg.mjs +26 -0
- package/dist/webauthn/auth-webauthn.addon.js +141 -5
- package/dist/webauthn/auth-webauthn.addon.mjs +136 -37
- package/dist/webauthn/dist-CYZr2fwk.mjs +2726 -0
- package/dist/webauthn/hostInit-Boe91Eeg.mjs +129 -0
- package/dist/webauthn/remoteEntry.js +134 -0
- package/dist/webauthn/remoteEntry.ssr.js +33 -0
- package/dist/webauthn/virtualExposes-Ckj56FAf.mjs +27 -0
- package/dist/webauthn/virtual_mf-exposes-ssr___mfe_internal__addon_auth_webauthn_widgets__remoteEntry_js-C5AzEzK5.mjs +10 -0
- package/package.json +30 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as loginMethodCapability, o as errMsg, r as authProviderCapability, s as BaseAddon, t as addonRoutesCapability } from "../dist-suALViLT.mjs";
|
|
2
2
|
//#region src/magic-link/auth-magic-link.addon.ts
|
|
3
3
|
/**
|
|
4
4
|
* Magic-link authentication addon.
|
|
@@ -33,21 +33,10 @@ var DEFAULT_CONFIG = {
|
|
|
33
33
|
ttlSec: 600
|
|
34
34
|
};
|
|
35
35
|
var AuthMagicLinkAddon = class extends BaseAddon {
|
|
36
|
-
kind = "magic-link";
|
|
37
|
-
hasRedirectFlow = false;
|
|
38
|
-
hasCredentialFlow = true;
|
|
39
|
-
displayName;
|
|
40
|
-
icon;
|
|
41
36
|
constructor() {
|
|
42
37
|
super({ ...DEFAULT_CONFIG });
|
|
43
|
-
this.displayName = DEFAULT_CONFIG.displayName;
|
|
44
|
-
this.icon = DEFAULT_CONFIG.icon;
|
|
45
38
|
}
|
|
46
39
|
async onInitialize() {
|
|
47
|
-
Object.assign(this, {
|
|
48
|
-
displayName: this.config.displayName || DEFAULT_CONFIG.displayName,
|
|
49
|
-
icon: this.config.icon || DEFAULT_CONFIG.icon
|
|
50
|
-
});
|
|
51
40
|
const authProvider = {
|
|
52
41
|
validateCredentials: async () => null,
|
|
53
42
|
validateToken: async () => null,
|
|
@@ -58,30 +47,58 @@ var AuthMagicLinkAddon = class extends BaseAddon {
|
|
|
58
47
|
throw new Error("Magic link does not use callback — the email link redirects to /api/auth/sso/finish directly");
|
|
59
48
|
}
|
|
60
49
|
};
|
|
61
|
-
const routes = [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
50
|
+
const routes = [
|
|
51
|
+
{
|
|
52
|
+
method: "GET",
|
|
53
|
+
path: "/start",
|
|
54
|
+
access: "public",
|
|
55
|
+
description: "Login-page landing: email-entry form that POSTs to /request",
|
|
56
|
+
handler: async (req, reply) => this.handleStart(req, reply)
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
method: "POST",
|
|
60
|
+
path: "/request",
|
|
61
|
+
access: "public",
|
|
62
|
+
description: "Request a magic link be delivered to the given email",
|
|
63
|
+
handler: async (req, reply) => this.handleRequest(req, reply)
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
method: "GET",
|
|
67
|
+
path: "/login",
|
|
68
|
+
access: "public",
|
|
69
|
+
description: "Click target embedded in the magic-link email",
|
|
70
|
+
handler: async (req, reply) => this.handleLogin(req, reply)
|
|
71
|
+
}
|
|
72
|
+
];
|
|
74
73
|
const routeProvider = {
|
|
75
74
|
id: "auth-magic-link",
|
|
76
75
|
getRoutes: () => routes
|
|
77
76
|
};
|
|
77
|
+
const loginMethodProvider = { getLoginMethods: async () => this.buildLoginMethods() };
|
|
78
78
|
this.ctx.logger.info("Magic-link auth provider initialized", { meta: { deliveryMode: this.config.deliveryMode } });
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
capability: authProviderCapability,
|
|
82
|
+
provider: authProvider
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
capability: addonRoutesCapability,
|
|
86
|
+
provider: routeProvider
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
capability: loginMethodCapability,
|
|
90
|
+
provider: loginMethodProvider
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
buildLoginMethods() {
|
|
79
95
|
return [{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
96
|
+
kind: "redirect",
|
|
97
|
+
id: "auth-magic-link",
|
|
98
|
+
label: this.config.displayName || DEFAULT_CONFIG.displayName,
|
|
99
|
+
icon: this.config.icon || DEFAULT_CONFIG.icon,
|
|
100
|
+
startUrl: "/addon/auth-magic-link/start",
|
|
101
|
+
stage: "primary"
|
|
85
102
|
}];
|
|
86
103
|
}
|
|
87
104
|
globalSettingsSchema() {
|
|
@@ -164,6 +181,59 @@ var AuthMagicLinkAddon = class extends BaseAddon {
|
|
|
164
181
|
for (const u of users) if (u.username.toLowerCase() === needle) return u;
|
|
165
182
|
return null;
|
|
166
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Login-page landing for the magic-link `redirect` login method. Serves
|
|
186
|
+
* a self-contained email-entry page that POSTs to `/request`; the tiny
|
|
187
|
+
* inline script lives in the ADDON's served HTML (not the admin shell),
|
|
188
|
+
* keeping the login page free of any magic-link-specific JS. Always
|
|
189
|
+
* responds 200 (account-enumeration-safe, mirroring `/request`).
|
|
190
|
+
*/
|
|
191
|
+
async handleStart(_req, reply) {
|
|
192
|
+
const title = this.config.displayName || DEFAULT_CONFIG.displayName;
|
|
193
|
+
const html = `<!doctype html>
|
|
194
|
+
<html lang="en"><head><meta charset="utf-8">
|
|
195
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
196
|
+
<title>${escapeHtml(title)}</title>
|
|
197
|
+
<style>
|
|
198
|
+
:root { color-scheme: dark; }
|
|
199
|
+
body { margin:0; min-height:100vh; display:flex; align-items:center; justify-content:center;
|
|
200
|
+
background:#0b0d12; color:#e5e7eb; font:14px/1.5 system-ui,-apple-system,sans-serif; }
|
|
201
|
+
.card { width:100%; max-width:22rem; padding:1.5rem; border:1px solid #232733; border-radius:0.75rem;
|
|
202
|
+
background:#12151c; box-shadow:0 10px 30px rgba(0,0,0,.35); }
|
|
203
|
+
h1 { font-size:1rem; margin:0 0 1rem; }
|
|
204
|
+
label { font-size:.75rem; color:#9ca3af; display:block; margin-bottom:.35rem; }
|
|
205
|
+
input { width:100%; box-sizing:border-box; padding:.6rem .7rem; border-radius:.5rem;
|
|
206
|
+
border:1px solid #232733; background:#0b0d12; color:#e5e7eb; outline:none; }
|
|
207
|
+
input:focus { border-color:#6366f1; }
|
|
208
|
+
button { margin-top:1rem; width:100%; padding:.6rem; border:0; border-radius:.5rem; cursor:pointer;
|
|
209
|
+
background:#6366f1; color:#fff; font-weight:600; }
|
|
210
|
+
button:disabled { opacity:.5; cursor:default; }
|
|
211
|
+
.msg { margin-top:1rem; font-size:.8rem; color:#34d399; }
|
|
212
|
+
.err { color:#f87171; }
|
|
213
|
+
a { color:#9ca3af; font-size:.75rem; }
|
|
214
|
+
</style></head>
|
|
215
|
+
<body><form class="card" id="f">
|
|
216
|
+
<h1>${escapeHtml(title)}</h1>
|
|
217
|
+
<label for="email">Email address</label>
|
|
218
|
+
<input id="email" name="email" type="email" autocomplete="email" required autofocus placeholder="you@example.com">
|
|
219
|
+
<button id="b" type="submit">Send login link</button>
|
|
220
|
+
<div class="msg" id="m" hidden></div>
|
|
221
|
+
<p style="margin-top:1rem"><a href="/admin/login">Back to sign in</a></p>
|
|
222
|
+
</form>
|
|
223
|
+
<script>
|
|
224
|
+
var f=document.getElementById('f'),b=document.getElementById('b'),m=document.getElementById('m');
|
|
225
|
+
f.addEventListener('submit',function(e){e.preventDefault();b.disabled=true;m.hidden=true;m.className='msg';
|
|
226
|
+
fetch('/addon/auth-magic-link/request',{method:'POST',headers:{'content-type':'application/json'},
|
|
227
|
+
body:JSON.stringify({email:document.getElementById('email').value})})
|
|
228
|
+
.then(function(){m.textContent='If that email matches an account, a login link is on its way.';m.hidden=false;})
|
|
229
|
+
.catch(function(){m.className='msg err';m.textContent='Something went wrong. Please try again.';m.hidden=false;})
|
|
230
|
+
.finally(function(){b.disabled=false;});});
|
|
231
|
+
<\/script>
|
|
232
|
+
</body></html>`;
|
|
233
|
+
reply.code(200);
|
|
234
|
+
reply.header("Content-Type", "text/html; charset=utf-8");
|
|
235
|
+
reply.send(html);
|
|
236
|
+
}
|
|
167
237
|
async handleRequest(req, reply) {
|
|
168
238
|
try {
|
|
169
239
|
const body = req.body ?? {};
|
|
@@ -230,5 +300,9 @@ var AuthMagicLinkAddon = class extends BaseAddon {
|
|
|
230
300
|
reply.send("");
|
|
231
301
|
}
|
|
232
302
|
};
|
|
303
|
+
/** Minimal HTML-attribute/text escaper for the interpolated page title. */
|
|
304
|
+
function escapeHtml(value) {
|
|
305
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
306
|
+
}
|
|
233
307
|
//#endregion
|
|
234
308
|
export { AuthMagicLinkAddon, AuthMagicLinkAddon as default };
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-mmJDfwXE.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
//#region node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
@@ -1254,14 +1254,42 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1254
1254
|
id: "auth-oidc",
|
|
1255
1255
|
getRoutes: () => routes
|
|
1256
1256
|
};
|
|
1257
|
+
const loginMethodProvider = { getLoginMethods: async () => this.buildLoginMethods() };
|
|
1257
1258
|
this.ctx.logger.info("OIDC auth provider initialized", { meta: { providers: [...this.instances.keys()] } });
|
|
1258
|
-
return [
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1259
|
+
return [
|
|
1260
|
+
{
|
|
1261
|
+
capability: require_dist.authProviderCapability,
|
|
1262
|
+
provider: authProvider
|
|
1263
|
+
},
|
|
1264
|
+
{
|
|
1265
|
+
capability: require_dist.addonRoutesCapability,
|
|
1266
|
+
provider: routeProvider
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
capability: require_dist.loginMethodCapability,
|
|
1270
|
+
provider: loginMethodProvider
|
|
1271
|
+
}
|
|
1272
|
+
];
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Build one `redirect` login-method per configured provider instance.
|
|
1276
|
+
* `startUrl` is the addon's public `/start` route for that instance;
|
|
1277
|
+
* the login page renders a generic button navigating to it.
|
|
1278
|
+
*/
|
|
1279
|
+
buildLoginMethods() {
|
|
1280
|
+
const out = [];
|
|
1281
|
+
for (const inst of this.instances.values()) {
|
|
1282
|
+
const id = inst.config.id;
|
|
1283
|
+
out.push({
|
|
1284
|
+
kind: "redirect",
|
|
1285
|
+
id: `auth-oidc/${id}`,
|
|
1286
|
+
label: inst.config.displayName || DEFAULT_PROVIDER.displayName,
|
|
1287
|
+
icon: inst.config.icon || DEFAULT_PROVIDER.icon,
|
|
1288
|
+
startUrl: `/addon/auth-oidc/${id}/start`,
|
|
1289
|
+
stage: "primary"
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
return out;
|
|
1265
1293
|
}
|
|
1266
1294
|
globalSettingsSchema() {
|
|
1267
1295
|
return this.schema({ sections: [{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as loginMethodCapability, o as errMsg, r as authProviderCapability, s as BaseAddon, t as addonRoutesCapability } from "../dist-suALViLT.mjs";
|
|
2
2
|
import * as crypto$1 from "node:crypto";
|
|
3
3
|
//#region node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
4
4
|
var encoder = new TextEncoder();
|
|
@@ -1248,14 +1248,42 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1248
1248
|
id: "auth-oidc",
|
|
1249
1249
|
getRoutes: () => routes
|
|
1250
1250
|
};
|
|
1251
|
+
const loginMethodProvider = { getLoginMethods: async () => this.buildLoginMethods() };
|
|
1251
1252
|
this.ctx.logger.info("OIDC auth provider initialized", { meta: { providers: [...this.instances.keys()] } });
|
|
1252
|
-
return [
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1253
|
+
return [
|
|
1254
|
+
{
|
|
1255
|
+
capability: authProviderCapability,
|
|
1256
|
+
provider: authProvider
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
capability: addonRoutesCapability,
|
|
1260
|
+
provider: routeProvider
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
capability: loginMethodCapability,
|
|
1264
|
+
provider: loginMethodProvider
|
|
1265
|
+
}
|
|
1266
|
+
];
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Build one `redirect` login-method per configured provider instance.
|
|
1270
|
+
* `startUrl` is the addon's public `/start` route for that instance;
|
|
1271
|
+
* the login page renders a generic button navigating to it.
|
|
1272
|
+
*/
|
|
1273
|
+
buildLoginMethods() {
|
|
1274
|
+
const out = [];
|
|
1275
|
+
for (const inst of this.instances.values()) {
|
|
1276
|
+
const id = inst.config.id;
|
|
1277
|
+
out.push({
|
|
1278
|
+
kind: "redirect",
|
|
1279
|
+
id: `auth-oidc/${id}`,
|
|
1280
|
+
label: inst.config.displayName || DEFAULT_PROVIDER.displayName,
|
|
1281
|
+
icon: inst.config.icon || DEFAULT_PROVIDER.icon,
|
|
1282
|
+
startUrl: `/addon/auth-oidc/${id}/start`,
|
|
1283
|
+
stage: "primary"
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
return out;
|
|
1259
1287
|
}
|
|
1260
1288
|
globalSettingsSchema() {
|
|
1261
1289
|
return this.schema({ sections: [{
|