@madauth/server 0.5.0-beta.1 → 0.5.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.
@@ -790,9 +790,13 @@ function passwordRoutes(app, ctx, users, webhook) {
790
790
  if (existing) {
791
791
  if (Date.now() - existing.lastMailAt < MAIL_INTERVAL_MS) return accepted(c);
792
792
  if (!existing.emailVerified) await users.dropUnprovenAccounts(existing.id, "password");
793
+ if (existing.emailVerified) await users.updateUser(existing.id, { emailVerified: false });
793
794
  const account = await users.passwordAccount(existing.id);
794
795
  if (account) await users.updateAccount(account.id, { secret: passwordHash, failedAttempts: 0, lockedUntil: 0 });
795
- else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) return accepted(c);
796
+ else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) {
797
+ if (existing.emailVerified && !await users.passwordAccount(existing.id)) await users.updateUser(existing.id, { emailVerified: true });
798
+ return accepted(c);
799
+ }
796
800
  await users.reopenSignUp(existing);
797
801
  await users.updateUser(existing.id, { name });
798
802
  return await emails.sendLinkEmail({ ...existing, name }, "verify", target, locale) ? accepted(c) : unavailable(c);
@@ -1208,7 +1212,8 @@ function totpRoutes(app, ctx, keys) {
1208
1212
  app.post(`${COOKIE_PATH4}/confirm`, async (c) => {
1209
1213
  const who = await whoSetsUp(c);
1210
1214
  if (!who) return noSession(c);
1211
- const { user, challenge } = who;
1215
+ const { challenge } = who;
1216
+ let { user } = who;
1212
1217
  if (challenge && !await methodStillOn(c, ctx, challenge)) return methodOff(c);
1213
1218
  const data = await body(c);
1214
1219
  const setup = await readToken(await ctx.keys, issuer, SETUP_TYP2, getCookie5(c, SETUP_COOKIE2));
@@ -1217,6 +1222,11 @@ function totpRoutes(app, ctx, keys) {
1217
1222
  const step = typeof data.code === "string" ? verifyTotp(secret, data.code, Date.now(), TOTP_WINDOW) : null;
1218
1223
  if (step === null) return error(c, 400, "code_invalid", "The code is wrong. Enter the current code from the app.");
1219
1224
  const signUp = challenge?.method === "totp";
1225
+ const fresh = signUp && !user.emailVerified ? await users.findById(user.id) : null;
1226
+ if (fresh && !fresh.emailVerified) {
1227
+ await users.verifyByProvider(fresh);
1228
+ user = { ...user, emailVerified: true, wrongCodes: 0 };
1229
+ }
1220
1230
  const { recoveryCodes, hashes } = newRecoveryCodes();
1221
1231
  await users.addRecoveryCodes(user.id, setup.setup, hashes);
1222
1232
  const patch = { secret: setup.secret, setupId: setup.setup, failedAttempts: 0, lockedUntil: 0, lastUsedStep: step };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-7DHKDRGY.js";
3
+ } from "../chunk-6SF2WNOC.js";
4
4
  import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-7DHKDRGY.js";
3
+ } from "../chunk-6SF2WNOC.js";
4
4
  import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-7DHKDRGY.js";
3
+ } from "../chunk-6SF2WNOC.js";
4
4
  import "../chunk-A7UYZRBL.js";
5
5
  import {
6
6
  loadConfig,
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  REDIRECT_ERROR_PARAM,
12
12
  createApp
13
- } from "./chunk-7DHKDRGY.js";
13
+ } from "./chunk-6SF2WNOC.js";
14
14
  import "./chunk-A7UYZRBL.js";
15
15
  import {
16
16
  ADMIN_ROLE,
@@ -12760,9 +12760,13 @@ function passwordRoutes(app2, ctx, users, webhook) {
12760
12760
  if (existing) {
12761
12761
  if (Date.now() - existing.lastMailAt < MAIL_INTERVAL_MS) return accepted(c);
12762
12762
  if (!existing.emailVerified) await users.dropUnprovenAccounts(existing.id, "password");
12763
+ if (existing.emailVerified) await users.updateUser(existing.id, { emailVerified: false });
12763
12764
  const account = await users.passwordAccount(existing.id);
12764
12765
  if (account) await users.updateAccount(account.id, { secret: passwordHash, failedAttempts: 0, lockedUntil: 0 });
12765
- else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) return accepted(c);
12766
+ else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) {
12767
+ if (existing.emailVerified && !await users.passwordAccount(existing.id)) await users.updateUser(existing.id, { emailVerified: true });
12768
+ return accepted(c);
12769
+ }
12766
12770
  await users.reopenSignUp(existing);
12767
12771
  await users.updateUser(existing.id, { name });
12768
12772
  return await emails.sendLinkEmail({ ...existing, name }, "verify", target, locale) ? accepted(c) : unavailable(c);
@@ -13173,7 +13177,8 @@ function totpRoutes(app2, ctx, keys) {
13173
13177
  app2.post(`${COOKIE_PATH4}/confirm`, async (c) => {
13174
13178
  const who = await whoSetsUp(c);
13175
13179
  if (!who) return noSession(c);
13176
- const { user, challenge } = who;
13180
+ const { challenge } = who;
13181
+ let { user } = who;
13177
13182
  if (challenge && !await methodStillOn(c, ctx, challenge)) return methodOff(c);
13178
13183
  const data = await body(c);
13179
13184
  const setup = await readToken(await ctx.keys, issuer, SETUP_TYP2, getCookie(c, SETUP_COOKIE2));
@@ -13182,6 +13187,11 @@ function totpRoutes(app2, ctx, keys) {
13182
13187
  const step = typeof data.code === "string" ? verifyTotp(secret, data.code, Date.now(), TOTP_WINDOW) : null;
13183
13188
  if (step === null) return error(c, 400, "code_invalid", "The code is wrong. Enter the current code from the app.");
13184
13189
  const signUp = challenge?.method === "totp";
13190
+ const fresh = signUp && !user.emailVerified ? await users.findById(user.id) : null;
13191
+ if (fresh && !fresh.emailVerified) {
13192
+ await users.verifyByProvider(fresh);
13193
+ user = { ...user, emailVerified: true, wrongCodes: 0 };
13194
+ }
13185
13195
  const { recoveryCodes, hashes } = newRecoveryCodes();
13186
13196
  await users.addRecoveryCodes(user.id, setup.setup, hashes);
13187
13197
  const patch = { secret: setup.secret, setupId: setup.setup, failedAttempts: 0, lockedUntil: 0, lastUsedStep: step };
@@ -8912,9 +8912,13 @@ function passwordRoutes(app, ctx, users, webhook) {
8912
8912
  if (existing) {
8913
8913
  if (Date.now() - existing.lastMailAt < MAIL_INTERVAL_MS) return accepted(c);
8914
8914
  if (!existing.emailVerified) await users.dropUnprovenAccounts(existing.id, "password");
8915
+ if (existing.emailVerified) await users.updateUser(existing.id, { emailVerified: false });
8915
8916
  const account = await users.passwordAccount(existing.id);
8916
8917
  if (account) await users.updateAccount(account.id, { secret: passwordHash, failedAttempts: 0, lockedUntil: 0 });
8917
- else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) return accepted(c);
8918
+ else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) {
8919
+ if (existing.emailVerified && !await users.passwordAccount(existing.id)) await users.updateUser(existing.id, { emailVerified: true });
8920
+ return accepted(c);
8921
+ }
8918
8922
  await users.reopenSignUp(existing);
8919
8923
  await users.updateUser(existing.id, { name });
8920
8924
  return await emails.sendLinkEmail({ ...existing, name }, "verify", target, locale) ? accepted(c) : unavailable(c);
@@ -9325,7 +9329,8 @@ function totpRoutes(app, ctx, keys) {
9325
9329
  app.post(`${COOKIE_PATH4}/confirm`, async (c) => {
9326
9330
  const who = await whoSetsUp(c);
9327
9331
  if (!who) return noSession(c);
9328
- const { user, challenge } = who;
9332
+ const { challenge } = who;
9333
+ let { user } = who;
9329
9334
  if (challenge && !await methodStillOn(c, ctx, challenge)) return methodOff(c);
9330
9335
  const data = await body(c);
9331
9336
  const setup = await readToken(await ctx.keys, issuer, SETUP_TYP2, getCookie(c, SETUP_COOKIE2));
@@ -9334,6 +9339,11 @@ function totpRoutes(app, ctx, keys) {
9334
9339
  const step = typeof data.code === "string" ? verifyTotp(secret, data.code, Date.now(), TOTP_WINDOW) : null;
9335
9340
  if (step === null) return error(c, 400, "code_invalid", "The code is wrong. Enter the current code from the app.");
9336
9341
  const signUp = challenge?.method === "totp";
9342
+ const fresh = signUp && !user.emailVerified ? await users.findById(user.id) : null;
9343
+ if (fresh && !fresh.emailVerified) {
9344
+ await users.verifyByProvider(fresh);
9345
+ user = { ...user, emailVerified: true, wrongCodes: 0 };
9346
+ }
9337
9347
  const { recoveryCodes, hashes } = newRecoveryCodes();
9338
9348
  await users.addRecoveryCodes(user.id, setup.setup, hashes);
9339
9349
  const patch = { secret: setup.secret, setupId: setup.setup, failedAttempts: 0, lockedUntil: 0, lastUsedStep: step };
@@ -38381,9 +38381,13 @@ function passwordRoutes(app, ctx, users, webhook) {
38381
38381
  if (existing) {
38382
38382
  if (Date.now() - existing.lastMailAt < MAIL_INTERVAL_MS) return accepted(c6);
38383
38383
  if (!existing.emailVerified) await users.dropUnprovenAccounts(existing.id, "password");
38384
+ if (existing.emailVerified) await users.updateUser(existing.id, { emailVerified: false });
38384
38385
  const account = await users.passwordAccount(existing.id);
38385
38386
  if (account) await users.updateAccount(account.id, { secret: passwordHash, failedAttempts: 0, lockedUntil: 0 });
38386
- else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) return accepted(c6);
38387
+ else if (!await users.linkAccount(existing.id, { key: passwordAccountKey(existing.id), secret: passwordHash })) {
38388
+ if (existing.emailVerified && !await users.passwordAccount(existing.id)) await users.updateUser(existing.id, { emailVerified: true });
38389
+ return accepted(c6);
38390
+ }
38387
38391
  await users.reopenSignUp(existing);
38388
38392
  await users.updateUser(existing.id, { name });
38389
38393
  return await emails.sendLinkEmail({ ...existing, name }, "verify", target, locale) ? accepted(c6) : unavailable(c6);
@@ -38794,7 +38798,8 @@ function totpRoutes(app, ctx, keys) {
38794
38798
  app.post(`${COOKIE_PATH4}/confirm`, async (c6) => {
38795
38799
  const who = await whoSetsUp(c6);
38796
38800
  if (!who) return noSession(c6);
38797
- const { user, challenge } = who;
38801
+ const { challenge } = who;
38802
+ let { user } = who;
38798
38803
  if (challenge && !await methodStillOn(c6, ctx, challenge)) return methodOff(c6);
38799
38804
  const data = await body(c6);
38800
38805
  const setup = await readToken(await ctx.keys, issuer, SETUP_TYP2, getCookie(c6, SETUP_COOKIE2));
@@ -38803,6 +38808,11 @@ function totpRoutes(app, ctx, keys) {
38803
38808
  const step = typeof data.code === "string" ? verifyTotp(secret, data.code, Date.now(), TOTP_WINDOW) : null;
38804
38809
  if (step === null) return error(c6, 400, "code_invalid", "The code is wrong. Enter the current code from the app.");
38805
38810
  const signUp = challenge?.method === "totp";
38811
+ const fresh = signUp && !user.emailVerified ? await users.findById(user.id) : null;
38812
+ if (fresh && !fresh.emailVerified) {
38813
+ await users.verifyByProvider(fresh);
38814
+ user = { ...user, emailVerified: true, wrongCodes: 0 };
38815
+ }
38806
38816
  const { recoveryCodes, hashes } = newRecoveryCodes();
38807
38817
  await users.addRecoveryCodes(user.id, setup.setup, hashes);
38808
38818
  const patch = { secret: setup.secret, setupId: setup.setup, failedAttempts: 0, lockedUntil: 0, lastUsedStep: step };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madauth/server",
3
- "version": "0.5.0-beta.1",
3
+ "version": "0.5.0-beta.2",
4
4
  "description": "madAuth server: Google, e-mail & password and authenticator-app sign-in with madAuth sessions, for Docker, AWS Lambda and Azure Functions.",
5
5
  "license": "MIT",
6
6
  "author": "David Neuy",