@revealui/auth 0.3.8 → 0.4.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/server/mfa.d.ts.map +1 -1
- package/dist/server/mfa.js +12 -5
- package/dist/server/oauth.d.ts +1 -1
- package/dist/server/oauth.js +2 -2
- package/package.json +7 -7
package/dist/server/mfa.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../../src/server/mfa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../../src/server/mfa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,WAAW,SAAS;IACxB,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAUD,wBAAgB,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAEhE;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC;AA2ED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA0C7F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyC/C;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC/C;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAuCxE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBvE;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1C;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgD/C;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUnE"}
|
package/dist/server/mfa.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { randomBytes, timingSafeEqual } from 'node:crypto';
|
|
8
8
|
import { TwoFactorAuth } from '@revealui/core/security';
|
|
9
9
|
import { getClient } from '@revealui/db/client';
|
|
10
|
+
import { decryptFieldOrPassthrough, encryptField } from '@revealui/db/crypto';
|
|
10
11
|
import { users } from '@revealui/db/schema';
|
|
11
12
|
import bcrypt from 'bcryptjs';
|
|
12
13
|
import { eq } from 'drizzle-orm';
|
|
@@ -100,11 +101,13 @@ export async function initiateMFASetup(userId, email) {
|
|
|
100
101
|
const secret = TwoFactorAuth.generateSecret();
|
|
101
102
|
const { plaintext, hashed } = await generateBackupCodes();
|
|
102
103
|
const uri = buildProvisioningUri(secret, email);
|
|
103
|
-
//
|
|
104
|
+
// Encrypt TOTP secret before storage (AES-256-GCM, KEK from REVEALUI_KEK)
|
|
105
|
+
const encryptedSecret = encryptField(secret);
|
|
106
|
+
// Store encrypted secret and backup codes (MFA stays disabled until verified)
|
|
104
107
|
await db
|
|
105
108
|
.update(users)
|
|
106
109
|
.set({
|
|
107
|
-
mfaSecret:
|
|
110
|
+
mfaSecret: encryptedSecret,
|
|
108
111
|
mfaBackupCodes: hashed,
|
|
109
112
|
updatedAt: new Date(),
|
|
110
113
|
})
|
|
@@ -136,8 +139,10 @@ export async function verifyMFASetup(userId, code) {
|
|
|
136
139
|
if (!user.mfaSecret) {
|
|
137
140
|
return { success: false, error: 'MFA setup not initiated' };
|
|
138
141
|
}
|
|
139
|
-
//
|
|
140
|
-
const
|
|
142
|
+
// Decrypt TOTP secret (supports legacy plaintext for rolling migration)
|
|
143
|
+
const plainSecret = decryptFieldOrPassthrough(user.mfaSecret);
|
|
144
|
+
// Verify the TOTP code against the decrypted secret
|
|
145
|
+
const valid = TwoFactorAuth.verifyCode(plainSecret, code);
|
|
141
146
|
if (!valid) {
|
|
142
147
|
return { success: false, error: 'Invalid verification code' };
|
|
143
148
|
}
|
|
@@ -172,7 +177,9 @@ export async function verifyMFACode(userId, code) {
|
|
|
172
177
|
if (!(user?.mfaEnabled && user.mfaSecret)) {
|
|
173
178
|
return { success: false, error: 'MFA not enabled' };
|
|
174
179
|
}
|
|
175
|
-
|
|
180
|
+
// Decrypt TOTP secret (supports legacy plaintext for rolling migration)
|
|
181
|
+
const plainSecret = decryptFieldOrPassthrough(user.mfaSecret);
|
|
182
|
+
const matchedCounter = verifyCodeWithCounter(plainSecret, code);
|
|
176
183
|
if (matchedCounter === null) {
|
|
177
184
|
return { success: false, error: 'Invalid code' };
|
|
178
185
|
}
|
package/dist/server/oauth.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export interface UpsertOAuthOptions {
|
|
|
55
55
|
* 1. Look up oauth_accounts by (provider, providerUserId) → get userId
|
|
56
56
|
* 2. If found: refresh metadata + return user
|
|
57
57
|
* 3. If not found: check users by email → link if match (with consent) or throw
|
|
58
|
-
* 4. If no match: create new user (role: '
|
|
58
|
+
* 4. If no match: create new user (role: 'viewer', no password)
|
|
59
59
|
* 5. Insert oauth_accounts row
|
|
60
60
|
*/
|
|
61
61
|
export declare function upsertOAuthUser(provider: string, providerUser: ProviderUser, options?: UpsertOAuthOptions): Promise<User>;
|
package/dist/server/oauth.js
CHANGED
|
@@ -153,7 +153,7 @@ export async function fetchProviderUser(provider, accessToken) {
|
|
|
153
153
|
* 1. Look up oauth_accounts by (provider, providerUserId) → get userId
|
|
154
154
|
* 2. If found: refresh metadata + return user
|
|
155
155
|
* 3. If not found: check users by email → link if match (with consent) or throw
|
|
156
|
-
* 4. If no match: create new user (role: '
|
|
156
|
+
* 4. If no match: create new user (role: 'viewer', no password)
|
|
157
157
|
* 5. Insert oauth_accounts row
|
|
158
158
|
*/
|
|
159
159
|
export async function upsertOAuthUser(provider, providerUser, options) {
|
|
@@ -227,7 +227,7 @@ export async function upsertOAuthUser(provider, providerUser, options) {
|
|
|
227
227
|
email: providerUser.email,
|
|
228
228
|
avatarUrl: providerUser.avatarUrl,
|
|
229
229
|
password: null,
|
|
230
|
-
role: '
|
|
230
|
+
role: 'viewer',
|
|
231
231
|
status: 'active',
|
|
232
232
|
});
|
|
233
233
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Authentication system for RevealUI - database-backed sessions with Better Auth patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
"bcryptjs": "^3.0.3",
|
|
15
15
|
"drizzle-orm": "^0.45.2",
|
|
16
16
|
"zod": "^4.3.6",
|
|
17
|
-
"@revealui/config": "0.
|
|
18
|
-
"@revealui/contracts": "1.
|
|
19
|
-
"@revealui/core": "0.
|
|
20
|
-
"@revealui/db": "0.
|
|
21
|
-
"@revealui/security": "0.
|
|
17
|
+
"@revealui/config": "0.4.0",
|
|
18
|
+
"@revealui/contracts": "1.4.0",
|
|
19
|
+
"@revealui/core": "0.6.0",
|
|
20
|
+
"@revealui/db": "0.4.0",
|
|
21
|
+
"@revealui/security": "0.3.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@simplewebauthn/browser": "^13.3.0",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@types/node": "^25.5.2",
|
|
27
27
|
"@types/react": "^19.2.14",
|
|
28
28
|
"@vitest/coverage-v8": "^4.1.3",
|
|
29
|
-
"happy-dom": "^20.
|
|
29
|
+
"happy-dom": "^20.9.0",
|
|
30
30
|
"react": "^19.2.5",
|
|
31
31
|
"typescript": "^6.0.2",
|
|
32
32
|
"vitest": "^4.1.3",
|