@madauth/server 0.2.0-beta.2 → 0.3.0-beta.2
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/bin.js +99 -32
- package/dist/{chunk-6EJDVZCD.js → chunk-3QRKWLR7.js} +10 -2
- package/dist/{chunk-CNL562LZ.js → chunk-56MOVFO4.js} +24 -2
- package/dist/{chunk-XNBWZZHT.js → chunk-CD7Y4T66.js} +11 -9
- package/dist/{chunk-7CTAB3QV.js → chunk-DCDTO5LG.js} +2 -2
- package/dist/{chunk-YALS7OMV.js → chunk-DVVBIFIV.js} +222 -122
- package/dist/{chunk-5CKEMC6M.js → chunk-TI35AZ2U.js} +227 -88
- package/dist/{config-BkxADgtp.d.ts → config-Dg2fZuWR.d.ts} +7 -6
- package/dist/dynamodb.js +1 -1
- package/dist/entry/azure.d.ts +3 -3
- package/dist/entry/azure.js +4 -4
- package/dist/entry/lambda.d.ts +3 -3
- package/dist/entry/lambda.js +4 -4
- package/dist/entry/node.d.ts +3 -3
- package/dist/entry/node.js +4 -4
- package/dist/index.d.ts +30 -7
- package/dist/index.js +15 -7
- package/dist/{schema-BSgYVRpd.d.ts → schema-3yhCc2jH.d.ts} +17 -9
- package/dist/sqlite.js +2 -2
- package/dist/standalone/azure.mjs +847 -597
- package/dist/standalone/lambda.mjs +847 -597
- package/dist/standalone/main.mjs +594 -344
- package/dist/store/dynamodb.d.ts +1 -1
- package/dist/store/sqlite.d.ts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +2 -0
- package/dist/user-BMWEWREH.d.ts +12 -0
- package/dist/verify.d.ts +1 -1
- package/dist/verify.js +1 -1
- package/dist/{webhook-ltwulgcB.d.ts → webhook-j5u9Kv9l.d.ts} +1 -1
- package/dist/webhook.d.ts +1 -1
- package/dist/webhook.js +1 -1
- package/package.json +1 -1
- package/dist/user-C1A3BfOo.d.ts +0 -12
package/dist/bin.js
CHANGED
|
@@ -2,29 +2,35 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createTablesSql,
|
|
4
4
|
upgradeTablesSql
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-56MOVFO4.js";
|
|
6
6
|
import {
|
|
7
7
|
madauthSchema
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CD7Y4T66.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
SIGN_IN_METHODS,
|
|
11
|
+
Settings,
|
|
11
12
|
Users,
|
|
13
|
+
anyOn,
|
|
12
14
|
checkPasswordPolicy,
|
|
15
|
+
claimsFromJson,
|
|
13
16
|
hashPassword,
|
|
17
|
+
isOn,
|
|
14
18
|
isValidEmail,
|
|
15
19
|
loadConfig,
|
|
16
20
|
loadStore,
|
|
17
21
|
loadUserStoreConfig,
|
|
18
22
|
normalizeEmail,
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
parseClaims,
|
|
24
|
+
parseRoles,
|
|
25
|
+
passwordAccountKey
|
|
26
|
+
} from "./chunk-TI35AZ2U.js";
|
|
21
27
|
import {
|
|
22
28
|
generateSigningKey
|
|
23
29
|
} from "./chunk-JDQLSL36.js";
|
|
24
30
|
import {
|
|
25
31
|
DEV_WEBHOOK_RECEIVER_URL,
|
|
26
32
|
generateWebhookSecret
|
|
27
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3QRKWLR7.js";
|
|
28
34
|
|
|
29
35
|
// src/cli.ts
|
|
30
36
|
import { existsSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -44,10 +50,17 @@ Commands:
|
|
|
44
50
|
generate-webhook-secret Print a new secret to use as WEBHOOK_SECRET (madAuth and your receiver)
|
|
45
51
|
create-user <email> Create a user with a password (asks for it), already verified.
|
|
46
52
|
Uses DATABASE_URL and PASSWORD_MIN_LENGTH from the environment.
|
|
47
|
-
set-roles <email> [role...] Set the roles of
|
|
53
|
+
set-roles <email> [role...] Set the roles of a user (the claim "roles"), e.g. to make the first admin:
|
|
48
54
|
set-roles you@example.com admin. Without roles, removes them all.
|
|
49
|
-
|
|
50
|
-
get-roles <email> Print the roles of
|
|
55
|
+
The user must exist: signed in once, or created with create-user.
|
|
56
|
+
get-roles <email> Print the roles of a user.
|
|
57
|
+
set-claims <email> <json> Replace the claims of a user, e.g. '{"roles":["admin"],"plan":"pro"}'.
|
|
58
|
+
get-claims <email> Print the claims of a user as JSON.
|
|
59
|
+
set-methods [method...] Switch sign-in methods on and off while the server runs: the listed ones
|
|
60
|
+
(google, password) are on, the others off. Without any, all are on.
|
|
61
|
+
get-methods Print which sign-in methods are switched on.
|
|
62
|
+
The claims commands use DATABASE_URL from the environment; the methods
|
|
63
|
+
commands need the server's whole configuration (e.g. --env-file .env).
|
|
51
64
|
schema [--dialect <name>] [--from <version>]
|
|
52
65
|
Print the SQL that creates madAuth's tables for a custom store adapter.
|
|
53
66
|
Dialects: postgres (default), mysql, sqlite. With --from, print only the
|
|
@@ -166,7 +179,8 @@ ${usage}`, exitCode: 1 };
|
|
|
166
179
|
}
|
|
167
180
|
const { values: options, positionals } = parsed;
|
|
168
181
|
const [command, ...rest] = positionals;
|
|
169
|
-
const
|
|
182
|
+
const argumentLimits = { "set-roles": Infinity, "set-methods": Infinity, "set-claims": 2, "create-user": 1, "get-roles": 1, "get-claims": 1 };
|
|
183
|
+
const maxArguments = command ? argumentLimits[command] ?? 0 : 0;
|
|
170
184
|
if (rest.length > maxArguments) {
|
|
171
185
|
return { output: `Unexpected argument: ${rest.at(-1)}
|
|
172
186
|
|
|
@@ -203,8 +217,11 @@ ${usage}`, exitCode: 1 };
|
|
|
203
217
|
if (command === "create-user") {
|
|
204
218
|
return await createUser(rest[0], io, env);
|
|
205
219
|
}
|
|
206
|
-
if (command === "set-roles" || command === "get-roles") {
|
|
207
|
-
return await
|
|
220
|
+
if (command === "set-roles" || command === "get-roles" || command === "set-claims" || command === "get-claims") {
|
|
221
|
+
return await claims(command, rest[0], rest.slice(1), env);
|
|
222
|
+
}
|
|
223
|
+
if (command === "set-methods" || command === "get-methods") {
|
|
224
|
+
return await methods(command, rest, env);
|
|
208
225
|
}
|
|
209
226
|
} catch (e) {
|
|
210
227
|
return { output: e instanceof Error ? e.message : String(e), exitCode: 1 };
|
|
@@ -239,14 +256,14 @@ async function init(options, io) {
|
|
|
239
256
|
}
|
|
240
257
|
const clientSecret = clientId ? (options["google-client-secret"] ?? await askClientSecret()).trim() : "";
|
|
241
258
|
const password = options.password ?? /^y/i.test(await answer(void 0, "E-mail & password sign-in? (yes/no)", "yes"));
|
|
242
|
-
if (!password &&
|
|
243
|
-
return fail("--
|
|
259
|
+
if (!password && options["webhook-url"] !== void 0) {
|
|
260
|
+
return fail("--webhook-url is for e-mail & password sign-in, which is turned off.");
|
|
244
261
|
}
|
|
245
262
|
if (!clientId && !password) {
|
|
246
263
|
return fail("No sign-in method is chosen. Give a Google client ID, turn on e-mail & password sign-in, or both.");
|
|
247
264
|
}
|
|
248
|
-
const database =
|
|
249
|
-
if (
|
|
265
|
+
const database = await answer(options.database, "Database for the users", "sqlite:./madauth.db");
|
|
266
|
+
if (!/^(sqlite|dynamodb):./.test(database)) {
|
|
250
267
|
return fail(`The database must be sqlite:<path> or dynamodb:<table> but is "${database}".`);
|
|
251
268
|
}
|
|
252
269
|
const webhookUrl = password ? await answer(options["webhook-url"], "Webhook URL, where madAuth hands over its e-mails", "http://localhost:8790/webhook") : "";
|
|
@@ -271,17 +288,17 @@ ${name}=${value}
|
|
|
271
288
|
variable("ALLOWED_ORIGINS", origin, "Origins of your apps, comma-separated. Only these may call the server."),
|
|
272
289
|
clientId && variable("GOOGLE_CLIENT_ID", clientId, "Google sign-in: your OAuth client ID, of the type Web application."),
|
|
273
290
|
clientSecret && variable("GOOGLE_CLIENT_SECRET", clientSecret, "Client secret of the same client. It enables the redirect flow."),
|
|
274
|
-
|
|
291
|
+
variable("DATABASE_URL", database, "Where the users are stored, whichever way they sign in."),
|
|
275
292
|
password && variable("WEBHOOK_URL", webhookUrl, "Your webhook receiver. madAuth hands its e-mails to it."),
|
|
276
293
|
password && variable("WEBHOOK_SECRET", generateWebhookSecret(), "Signs every webhook call. Your receiver needs the same one."),
|
|
277
294
|
password && variable(
|
|
278
295
|
"WEBHOOK_EVENTS",
|
|
279
|
-
"email.verify,email.reset,email.already_registered",
|
|
296
|
+
"email.verify,email.reset,email.already_registered,email.no_password",
|
|
280
297
|
"The types your webhook receiver handles; only these are sent. Add e.g. signup.before or user.created."
|
|
281
298
|
),
|
|
282
299
|
variable("PORT", String(PORT), "Port the server listens on.")
|
|
283
300
|
].filter(Boolean).join("");
|
|
284
|
-
await loadConfig({ ...parseEnv(content), DATABASE_URL: void 0 },
|
|
301
|
+
await loadConfig({ ...parseEnv(content), DATABASE_URL: void 0 }, { store: {} });
|
|
285
302
|
if (options.force) rmSync(file, { force: true });
|
|
286
303
|
writeFileSync(file, content, { mode: 384, flag: "wx" });
|
|
287
304
|
const google = clientSecret ? "GoogleRedirect" : clientId ? "GoogleFedcm" : void 0;
|
|
@@ -337,25 +354,74 @@ function nextSteps(file, origin, google, password) {
|
|
|
337
354
|
].filter((step) => !!step);
|
|
338
355
|
return steps.map((lines, i) => `${i + 1}. ${lines.map((line, j) => j && line ? ` ${line}` : line).join("\n")}`).join("\n\n");
|
|
339
356
|
}
|
|
340
|
-
async function
|
|
357
|
+
async function claims(command, email, args, env) {
|
|
341
358
|
if (!isValidEmail(email)) return { output: `"${email ?? ""}" is not an e-mail address.
|
|
342
359
|
|
|
343
360
|
${usage}`, exitCode: 1 };
|
|
344
|
-
const
|
|
361
|
+
const users = new Users(await loadStore(env));
|
|
345
362
|
const address = normalizeEmail(email);
|
|
346
|
-
const
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
363
|
+
const user = await users.findByEmail(address);
|
|
364
|
+
if (!user) return { output: `No user has the e-mail address ${address}. Users exist once they signed in, or with create-user.`, exitCode: 1 };
|
|
365
|
+
let current = claimsFromJson(user.claims);
|
|
366
|
+
if (command === "set-roles" || command === "set-claims") {
|
|
367
|
+
let next;
|
|
368
|
+
if (command === "set-roles") {
|
|
369
|
+
const roles2 = parseRoles(args);
|
|
370
|
+
if (!roles2) {
|
|
371
|
+
return {
|
|
372
|
+
output: 'Role names consist of lower-case letters, digits, "-" and "_", and start with a letter, e.g. admin.',
|
|
373
|
+
exitCode: 1
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
const { roles: _, ...rest } = current;
|
|
377
|
+
next = parseClaims(roles2.length ? { ...rest, roles: roles2 } : rest);
|
|
378
|
+
} else {
|
|
379
|
+
let parsed;
|
|
380
|
+
try {
|
|
381
|
+
parsed = JSON.parse(args[0] ?? "");
|
|
382
|
+
} catch {
|
|
383
|
+
return { output: `The claims must be JSON, e.g. '{"roles":["admin"]}'.
|
|
384
|
+
|
|
385
|
+
${usage}`, exitCode: 1 };
|
|
386
|
+
}
|
|
387
|
+
next = parseClaims(parsed);
|
|
388
|
+
}
|
|
389
|
+
if (!next) {
|
|
350
390
|
return {
|
|
351
|
-
output: '
|
|
391
|
+
output: 'Claims are a JSON object of at most 2048 characters whose keys are names (letters, digits and "_", starting with a letter); "roles" is a list of role names.',
|
|
352
392
|
exitCode: 1
|
|
353
393
|
};
|
|
354
394
|
}
|
|
355
|
-
await
|
|
395
|
+
await users.updateUser(user.id, { claims: Object.keys(next).length ? JSON.stringify(next) : null });
|
|
396
|
+
current = next;
|
|
397
|
+
}
|
|
398
|
+
if (command === "set-claims" || command === "get-claims") {
|
|
399
|
+
return { output: `${address}: ${JSON.stringify(current)}`, exitCode: 0 };
|
|
400
|
+
}
|
|
401
|
+
const roles = Array.isArray(current.roles) ? current.roles : [];
|
|
402
|
+
return { output: roles.length ? `${address}: ${roles.join(" ")}` : `${address} has no roles.`, exitCode: 0 };
|
|
403
|
+
}
|
|
404
|
+
async function methods(command, names, env) {
|
|
405
|
+
const config = await loadConfig(env);
|
|
406
|
+
const available = (method) => method === "google" ? !!config.google : !!config.password;
|
|
407
|
+
const settings = new Settings(config.store);
|
|
408
|
+
if (command === "set-methods") {
|
|
409
|
+
const unknown = names.filter((name) => !SIGN_IN_METHODS.includes(name));
|
|
410
|
+
if (unknown.length) {
|
|
411
|
+
return { output: `Unknown sign-in method ${unknown.join(", ")}. Methods: ${SIGN_IN_METHODS.join(", ")}.`, exitCode: 1 };
|
|
412
|
+
}
|
|
413
|
+
const next = {};
|
|
414
|
+
for (const method of SIGN_IN_METHODS) next[method] = !names.length || names.includes(method);
|
|
415
|
+
if (!anyOn(available, next)) {
|
|
416
|
+
const configured = SIGN_IN_METHODS.filter(available);
|
|
417
|
+
return { output: `That would switch off every sign-in method. The server is configured for: ${configured.join(", ")}.`, exitCode: 1 };
|
|
418
|
+
}
|
|
419
|
+
await settings.changeMethods(() => next, null);
|
|
356
420
|
}
|
|
357
|
-
const current = await
|
|
358
|
-
|
|
421
|
+
const current = await settings.methods();
|
|
422
|
+
const on = SIGN_IN_METHODS.filter((method) => isOn(method, available, current));
|
|
423
|
+
const off = SIGN_IN_METHODS.filter((method) => available(method) && !isOn(method, available, current));
|
|
424
|
+
return { output: `Switched on: ${on.join(", ")}.${off.length ? ` Switched off: ${off.join(", ")}.` : ""}`, exitCode: 0 };
|
|
359
425
|
}
|
|
360
426
|
async function createUser(email, io, env) {
|
|
361
427
|
if (!isValidEmail(email)) return { output: `"${email ?? ""}" is not an e-mail address.
|
|
@@ -366,12 +432,13 @@ ${usage}`, exitCode: 1 };
|
|
|
366
432
|
const policy = checkPasswordPolicy(password, minLength);
|
|
367
433
|
if (policy) return { output: policy, exitCode: 1 };
|
|
368
434
|
const users = new Users(store);
|
|
369
|
-
const
|
|
435
|
+
const passwordHash = await hashPassword(password);
|
|
436
|
+
const user = await users.createUser({
|
|
370
437
|
email: email.trim(),
|
|
371
438
|
emailNormalized: normalizeEmail(email),
|
|
372
439
|
name: null,
|
|
373
|
-
|
|
374
|
-
|
|
440
|
+
emailVerified: true,
|
|
441
|
+
account: (userId) => ({ key: passwordAccountKey(userId), secret: passwordHash })
|
|
375
442
|
});
|
|
376
443
|
if (!user) return { output: `A user with the e-mail address ${email} already exists.`, exitCode: 1 };
|
|
377
444
|
return { output: `Created user ${user.id} (${user.email}).`, exitCode: 0 };
|
|
@@ -4,14 +4,20 @@ var WEBHOOK_TYPES = [
|
|
|
4
4
|
"email.verify",
|
|
5
5
|
"email.reset",
|
|
6
6
|
"email.already_registered",
|
|
7
|
+
"email.no_password",
|
|
7
8
|
"signup.before",
|
|
8
9
|
"user.created",
|
|
9
10
|
"email.verified",
|
|
10
|
-
"
|
|
11
|
+
"email.password_reset",
|
|
11
12
|
"user.signed_in",
|
|
12
13
|
"user.deleted",
|
|
13
|
-
"
|
|
14
|
+
"user.claims_changed"
|
|
14
15
|
];
|
|
16
|
+
var WEBHOOK_TIMEOUT_MS = 1e4;
|
|
17
|
+
var MAX_LOCALE_LENGTH = 35;
|
|
18
|
+
function localeOf(value) {
|
|
19
|
+
return typeof value === "string" && value.length <= MAX_LOCALE_LENGTH ? value : void 0;
|
|
20
|
+
}
|
|
15
21
|
var REQUIRED_EMAIL_TYPES = ["email.verify", "email.reset"];
|
|
16
22
|
var SECRET_PREFIX = "whsec_";
|
|
17
23
|
var DEV_WEBHOOK_RECEIVER_URL = "https://github.com/inouiw/madAuth-webhooks/tree/main/dev-receiver";
|
|
@@ -93,6 +99,8 @@ function createWebhookClient(settings, fetchImpl = fetch) {
|
|
|
93
99
|
|
|
94
100
|
export {
|
|
95
101
|
WEBHOOK_TYPES,
|
|
102
|
+
WEBHOOK_TIMEOUT_MS,
|
|
103
|
+
localeOf,
|
|
96
104
|
REQUIRED_EMAIL_TYPES,
|
|
97
105
|
DEV_WEBHOOK_RECEIVER_URL,
|
|
98
106
|
WEBHOOK_TOLERANCE_SECONDS,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
madauthSchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CD7Y4T66.js";
|
|
4
4
|
|
|
5
5
|
// src/store/sql.ts
|
|
6
6
|
function tableName(model) {
|
|
@@ -21,8 +21,30 @@ var upgrades = [
|
|
|
21
21
|
sql: (dialect) => `ALTER TABLE ${tableName("user")} ADD COLUMN ${columnName("wrongCodes")} ${columnTypes[dialect].number} NOT NULL DEFAULT 0;`
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
|
+
// Roles were per e-mail address in their own table; since version 4 they are one of the user's claims.
|
|
24
25
|
version: 3,
|
|
25
|
-
sql: (dialect) => createTablesSql(dialect, {
|
|
26
|
+
sql: (dialect) => createTablesSql(dialect, {
|
|
27
|
+
version: 3,
|
|
28
|
+
models: {
|
|
29
|
+
role: {
|
|
30
|
+
fields: {
|
|
31
|
+
id: { type: "string", primaryKey: true },
|
|
32
|
+
roles: { type: "string" },
|
|
33
|
+
updatedAt: { type: "number" },
|
|
34
|
+
updatedBy: { type: "string", nullable: true }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
version: 4,
|
|
42
|
+
sql: (dialect) => [
|
|
43
|
+
`ALTER TABLE ${tableName("user")} ADD COLUMN ${columnName("claims")} ${columnTypes[dialect].string};`,
|
|
44
|
+
`ALTER TABLE ${tableName("account")} ADD COLUMN ${columnName("email")} ${columnTypes[dialect].string};`,
|
|
45
|
+
`DROP TABLE ${tableName("role")};`,
|
|
46
|
+
createTablesSql(dialect, { version: 4, models: { setting: madauthSchema.models.setting } })
|
|
47
|
+
].join("\n")
|
|
26
48
|
}
|
|
27
49
|
];
|
|
28
50
|
function upgradeTablesSql(dialect, fromVersion) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/store/schema.ts
|
|
2
2
|
var madauthSchema = {
|
|
3
|
-
version:
|
|
3
|
+
version: 4,
|
|
4
4
|
models: {
|
|
5
|
+
/** Someone who signed in, whichever way: the e-mail address is the identity shared by the sign-in methods. */
|
|
5
6
|
user: {
|
|
6
7
|
fields: {
|
|
7
8
|
id: { type: "string", primaryKey: true },
|
|
@@ -13,10 +14,12 @@ var madauthSchema = {
|
|
|
13
14
|
lastMailAt: { type: "number" },
|
|
14
15
|
/** Wrong e-mail codes in a row, counted across e-mails (since version 2). */
|
|
15
16
|
wrongCodes: { type: "number" },
|
|
17
|
+
/** What admins attached to the user, as JSON, e.g. `{"roles":["admin"]}` (since version 4). */
|
|
18
|
+
claims: { type: "string", nullable: true },
|
|
16
19
|
createdAt: { type: "number" }
|
|
17
20
|
}
|
|
18
21
|
},
|
|
19
|
-
/** How a user signs in. `key` is
|
|
22
|
+
/** How a user signs in. `key` is `password:<userId>` or `google:<sub>`; later e.g. `totp:<userId>`. */
|
|
20
23
|
account: {
|
|
21
24
|
fields: {
|
|
22
25
|
id: { type: "string", primaryKey: true },
|
|
@@ -25,6 +28,8 @@ var madauthSchema = {
|
|
|
25
28
|
secret: { type: "string", nullable: true },
|
|
26
29
|
failedAttempts: { type: "number" },
|
|
27
30
|
lockedUntil: { type: "number" },
|
|
31
|
+
/** The address the provider reported at the last sign-in, e.g. Google's current primary address (since version 4). */
|
|
32
|
+
email: { type: "string", nullable: true },
|
|
28
33
|
createdAt: { type: "number" }
|
|
29
34
|
}
|
|
30
35
|
},
|
|
@@ -39,16 +44,13 @@ var madauthSchema = {
|
|
|
39
44
|
expiresAt: { type: "number" }
|
|
40
45
|
}
|
|
41
46
|
},
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
* apply whichever way its owner signs in. `roles` holds the names separated by spaces.
|
|
45
|
-
*/
|
|
46
|
-
role: {
|
|
47
|
+
/** A setting admins change at runtime, as JSON (since version 4), e.g. `methods`: which sign-in methods are on. */
|
|
48
|
+
setting: {
|
|
47
49
|
fields: {
|
|
48
50
|
id: { type: "string", primaryKey: true },
|
|
49
|
-
|
|
51
|
+
value: { type: "string" },
|
|
50
52
|
updatedAt: { type: "number" },
|
|
51
|
-
/** The address of the admin who set
|
|
53
|
+
/** The address of the admin who set it; empty when set from the command line. */
|
|
52
54
|
updatedBy: { type: "string", nullable: true }
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -34,7 +34,7 @@ function signSession(keys, issuer, ttlSeconds, user, amr, extra = {}) {
|
|
|
34
34
|
email_verified: user.email ? true : void 0,
|
|
35
35
|
name: user.name,
|
|
36
36
|
picture: user.picture,
|
|
37
|
-
|
|
37
|
+
claims: user.claims && Object.keys(user.claims).length ? user.claims : void 0,
|
|
38
38
|
amr
|
|
39
39
|
};
|
|
40
40
|
return signToken(keys, issuer, SESSION_TYP, claims, ttlSeconds);
|
|
@@ -56,7 +56,7 @@ function userFromClaims(claims) {
|
|
|
56
56
|
if (claims.email) user.email = claims.email;
|
|
57
57
|
if (claims.name) user.name = claims.name;
|
|
58
58
|
if (claims.picture) user.picture = claims.picture;
|
|
59
|
-
if (
|
|
59
|
+
if (claims.claims && typeof claims.claims === "object" && Object.keys(claims.claims).length) user.claims = claims.claims;
|
|
60
60
|
return user;
|
|
61
61
|
}
|
|
62
62
|
|