@korajs/auth 0.5.0 → 1.0.0-beta.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/LICENSE +21 -0
- package/dist/chunk-MPMXJ62R.js +203 -0
- package/dist/chunk-MPMXJ62R.js.map +1 -0
- package/dist/{org-client-q2u55qod.d.cts → create-org-session-RsDj9cl4.d.cts} +58 -1
- package/dist/{org-client-q2u55qod.d.ts → create-org-session-RsDj9cl4.d.ts} +58 -1
- package/dist/index.cjs +168 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -19
- package/dist/index.d.ts +9 -19
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +294 -258
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +15 -215
- package/dist/react.d.ts +15 -215
- package/dist/react.js +135 -288
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +42 -5
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +24 -0
- package/dist/server.d.ts +24 -0
- package/dist/server.js +42 -5
- package/dist/server.js.map +1 -1
- package/dist/svelte.cjs +512 -0
- package/dist/svelte.cjs.map +1 -0
- package/dist/svelte.d.cts +100 -0
- package/dist/svelte.d.ts +100 -0
- package/dist/svelte.js +278 -0
- package/dist/svelte.js.map +1 -0
- package/dist/vue.cjs +565 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +136 -0
- package/dist/vue.d.ts +136 -0
- package/dist/vue.js +338 -0
- package/dist/vue.js.map +1 -0
- package/package.json +40 -6
- package/src/svelte/AuthProvider.svelte +37 -0
- package/src/svelte/OrgProvider.svelte +22 -0
package/dist/server.d.cts
CHANGED
|
@@ -3602,6 +3602,13 @@ interface TotpSecret {
|
|
|
3602
3602
|
createdAt: number;
|
|
3603
3603
|
/** When MFA was verified (confirmed with first valid code) */
|
|
3604
3604
|
verifiedAt: number | null;
|
|
3605
|
+
/**
|
|
3606
|
+
* The most recent TOTP time-step counter that was successfully consumed
|
|
3607
|
+
* during authentication. Used to enforce single-use of codes (RFC 6238 §5.2):
|
|
3608
|
+
* a code at or before this time-step is rejected as a replay. `undefined`
|
|
3609
|
+
* until the first code is consumed.
|
|
3610
|
+
*/
|
|
3611
|
+
lastUsedTimeStep?: number;
|
|
3605
3612
|
}
|
|
3606
3613
|
/**
|
|
3607
3614
|
* Setup result returned when enabling TOTP MFA.
|
|
@@ -3702,6 +3709,11 @@ declare class TotpManager {
|
|
|
3702
3709
|
/**
|
|
3703
3710
|
* Verify a TOTP code during login.
|
|
3704
3711
|
* Returns true if the code is valid, false otherwise.
|
|
3712
|
+
*
|
|
3713
|
+
* Enforces single-use: a code is rejected if its time-step has already
|
|
3714
|
+
* been consumed (or predates a previously consumed time-step). This
|
|
3715
|
+
* prevents an attacker who observes one valid code from replaying it
|
|
3716
|
+
* within the acceptance window (RFC 6238 §5.2).
|
|
3705
3717
|
*/
|
|
3706
3718
|
verify(userId: string, code: string): Promise<boolean>;
|
|
3707
3719
|
/**
|
|
@@ -3728,6 +3740,18 @@ declare class TotpManager {
|
|
|
3728
3740
|
*/
|
|
3729
3741
|
remainingRecoveryCodes(userId: string): Promise<number>;
|
|
3730
3742
|
private validateCode;
|
|
3743
|
+
/**
|
|
3744
|
+
* Find the TOTP time-step counter (within the acceptance window) whose
|
|
3745
|
+
* generated code matches `code`, or null if none matches. Comparison is
|
|
3746
|
+
* timing-safe.
|
|
3747
|
+
*/
|
|
3748
|
+
private matchTimeStep;
|
|
3749
|
+
/**
|
|
3750
|
+
* Validate a code AND consume its time-step so it (and any earlier code in
|
|
3751
|
+
* the window) cannot be reused. Returns false for an invalid code or a
|
|
3752
|
+
* replay of an already-consumed time-step. Persists the consumed time-step.
|
|
3753
|
+
*/
|
|
3754
|
+
private consumeCode;
|
|
3731
3755
|
}
|
|
3732
3756
|
/**
|
|
3733
3757
|
* Encode bytes to base32 string (RFC 4648, no padding).
|
package/dist/server.d.ts
CHANGED
|
@@ -3602,6 +3602,13 @@ interface TotpSecret {
|
|
|
3602
3602
|
createdAt: number;
|
|
3603
3603
|
/** When MFA was verified (confirmed with first valid code) */
|
|
3604
3604
|
verifiedAt: number | null;
|
|
3605
|
+
/**
|
|
3606
|
+
* The most recent TOTP time-step counter that was successfully consumed
|
|
3607
|
+
* during authentication. Used to enforce single-use of codes (RFC 6238 §5.2):
|
|
3608
|
+
* a code at or before this time-step is rejected as a replay. `undefined`
|
|
3609
|
+
* until the first code is consumed.
|
|
3610
|
+
*/
|
|
3611
|
+
lastUsedTimeStep?: number;
|
|
3605
3612
|
}
|
|
3606
3613
|
/**
|
|
3607
3614
|
* Setup result returned when enabling TOTP MFA.
|
|
@@ -3702,6 +3709,11 @@ declare class TotpManager {
|
|
|
3702
3709
|
/**
|
|
3703
3710
|
* Verify a TOTP code during login.
|
|
3704
3711
|
* Returns true if the code is valid, false otherwise.
|
|
3712
|
+
*
|
|
3713
|
+
* Enforces single-use: a code is rejected if its time-step has already
|
|
3714
|
+
* been consumed (or predates a previously consumed time-step). This
|
|
3715
|
+
* prevents an attacker who observes one valid code from replaying it
|
|
3716
|
+
* within the acceptance window (RFC 6238 §5.2).
|
|
3705
3717
|
*/
|
|
3706
3718
|
verify(userId: string, code: string): Promise<boolean>;
|
|
3707
3719
|
/**
|
|
@@ -3728,6 +3740,18 @@ declare class TotpManager {
|
|
|
3728
3740
|
*/
|
|
3729
3741
|
remainingRecoveryCodes(userId: string): Promise<number>;
|
|
3730
3742
|
private validateCode;
|
|
3743
|
+
/**
|
|
3744
|
+
* Find the TOTP time-step counter (within the acceptance window) whose
|
|
3745
|
+
* generated code matches `code`, or null if none matches. Comparison is
|
|
3746
|
+
* timing-safe.
|
|
3747
|
+
*/
|
|
3748
|
+
private matchTimeStep;
|
|
3749
|
+
/**
|
|
3750
|
+
* Validate a code AND consume its time-step so it (and any earlier code in
|
|
3751
|
+
* the window) cannot be reused. Returns false for an invalid code or a
|
|
3752
|
+
* replay of an already-consumed time-step. Persists the consumed time-step.
|
|
3753
|
+
*/
|
|
3754
|
+
private consumeCode;
|
|
3731
3755
|
}
|
|
3732
3756
|
/**
|
|
3733
3757
|
* Encode bytes to base32 string (RFC 4648, no padding).
|
package/dist/server.js
CHANGED
|
@@ -3783,6 +3783,13 @@ var OrgRoutes = class {
|
|
|
3783
3783
|
body: { error: "Cannot assign owner role directly. Use ownership transfer." }
|
|
3784
3784
|
};
|
|
3785
3785
|
}
|
|
3786
|
+
const org = await this.store.getOrg(orgId);
|
|
3787
|
+
if (org && org.ownerId === params.targetUserId) {
|
|
3788
|
+
return {
|
|
3789
|
+
status: 403,
|
|
3790
|
+
body: { error: "The organization owner's role cannot be changed. Use ownership transfer." }
|
|
3791
|
+
};
|
|
3792
|
+
}
|
|
3786
3793
|
const callerMembership = await this.store.getMembership(orgId, userId);
|
|
3787
3794
|
if (callerMembership && callerMembership.role !== "owner" && params.role === "admin") {
|
|
3788
3795
|
return { status: 403, body: { error: "Only the owner can assign admin role." } };
|
|
@@ -5358,9 +5365,9 @@ var TotpManager = class {
|
|
|
5358
5365
|
throw new TotpNotEnabledError(userId);
|
|
5359
5366
|
}
|
|
5360
5367
|
if (stored.verified) {
|
|
5361
|
-
return this.
|
|
5368
|
+
return this.consumeCode(stored, code);
|
|
5362
5369
|
}
|
|
5363
|
-
const valid = this.
|
|
5370
|
+
const valid = await this.consumeCode(stored, code);
|
|
5364
5371
|
if (!valid) {
|
|
5365
5372
|
throw new TotpInvalidCodeError();
|
|
5366
5373
|
}
|
|
@@ -5372,6 +5379,11 @@ var TotpManager = class {
|
|
|
5372
5379
|
/**
|
|
5373
5380
|
* Verify a TOTP code during login.
|
|
5374
5381
|
* Returns true if the code is valid, false otherwise.
|
|
5382
|
+
*
|
|
5383
|
+
* Enforces single-use: a code is rejected if its time-step has already
|
|
5384
|
+
* been consumed (or predates a previously consumed time-step). This
|
|
5385
|
+
* prevents an attacker who observes one valid code from replaying it
|
|
5386
|
+
* within the acceptance window (RFC 6238 §5.2).
|
|
5375
5387
|
*/
|
|
5376
5388
|
async verify(userId, code) {
|
|
5377
5389
|
const stored = await this.store.getByUserId(userId);
|
|
@@ -5381,7 +5393,7 @@ var TotpManager = class {
|
|
|
5381
5393
|
if (!stored.verified) {
|
|
5382
5394
|
throw new TotpNotVerifiedError(userId);
|
|
5383
5395
|
}
|
|
5384
|
-
return this.
|
|
5396
|
+
return this.consumeCode(stored, code);
|
|
5385
5397
|
}
|
|
5386
5398
|
/**
|
|
5387
5399
|
* Verify a recovery code as an alternative to TOTP.
|
|
@@ -5465,16 +5477,41 @@ var TotpManager = class {
|
|
|
5465
5477
|
}
|
|
5466
5478
|
// --- Private ---
|
|
5467
5479
|
validateCode(base32Secret, code) {
|
|
5480
|
+
return this.matchTimeStep(base32Secret, code) !== null;
|
|
5481
|
+
}
|
|
5482
|
+
/**
|
|
5483
|
+
* Find the TOTP time-step counter (within the acceptance window) whose
|
|
5484
|
+
* generated code matches `code`, or null if none matches. Comparison is
|
|
5485
|
+
* timing-safe.
|
|
5486
|
+
*/
|
|
5487
|
+
matchTimeStep(base32Secret, code) {
|
|
5468
5488
|
const secretBytes = base32Decode(base32Secret);
|
|
5469
5489
|
const now = Math.floor(Date.now() / 1e3);
|
|
5470
5490
|
for (let offset = -this.window; offset <= this.window; offset++) {
|
|
5471
5491
|
const timeCounter = Math.floor((now + offset * this.period) / this.period);
|
|
5472
5492
|
const expected = generateTotpCode(secretBytes, timeCounter, this.digits, this.algorithm);
|
|
5473
5493
|
if (timingSafeEqual(code, expected)) {
|
|
5474
|
-
return
|
|
5494
|
+
return timeCounter;
|
|
5475
5495
|
}
|
|
5476
5496
|
}
|
|
5477
|
-
return
|
|
5497
|
+
return null;
|
|
5498
|
+
}
|
|
5499
|
+
/**
|
|
5500
|
+
* Validate a code AND consume its time-step so it (and any earlier code in
|
|
5501
|
+
* the window) cannot be reused. Returns false for an invalid code or a
|
|
5502
|
+
* replay of an already-consumed time-step. Persists the consumed time-step.
|
|
5503
|
+
*/
|
|
5504
|
+
async consumeCode(stored, code) {
|
|
5505
|
+
const matched = this.matchTimeStep(stored.secret, code);
|
|
5506
|
+
if (matched === null) {
|
|
5507
|
+
return false;
|
|
5508
|
+
}
|
|
5509
|
+
if (stored.lastUsedTimeStep !== void 0 && matched <= stored.lastUsedTimeStep) {
|
|
5510
|
+
return false;
|
|
5511
|
+
}
|
|
5512
|
+
stored.lastUsedTimeStep = matched;
|
|
5513
|
+
await this.store.save(stored);
|
|
5514
|
+
return true;
|
|
5478
5515
|
}
|
|
5479
5516
|
};
|
|
5480
5517
|
function generateTotpCode(secret, counter, digits, algorithm) {
|