@nevermined-io/ui-widgets-server 0.4.6 → 0.5.1
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/create-init-token.js +10 -11
- package/dist/create-init-token.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize-email.js +4 -4
- package/dist/normalize-email.js.map +1 -0
- package/dist/types.js +3 -1
- package/dist/types.js.map +1 -0
- package/package.json +21 -1
|
@@ -4,20 +4,19 @@ const WIDGET_AUDIENCE = 'nvm:widgets';
|
|
|
4
4
|
const DEFAULT_EXPIRES_IN = '5m';
|
|
5
5
|
export async function createInitToken(options) {
|
|
6
6
|
const { email, orgId, secretKey, expiresIn = DEFAULT_EXPIRES_IN } = options;
|
|
7
|
-
if (!secretKey?.trim())
|
|
8
|
-
|
|
9
|
-
if (!orgId?.trim())
|
|
10
|
-
throw new Error('orgId is required');
|
|
7
|
+
if (!secretKey?.trim()) throw new Error('secretKey is required');
|
|
8
|
+
if (!orgId?.trim()) throw new Error('orgId is required');
|
|
11
9
|
const normalizedEmail = normalizeEmail(email);
|
|
12
10
|
const secret = new TextEncoder().encode(secretKey);
|
|
13
11
|
// `sub` is set to the email so the API's existence check on the claim
|
|
14
12
|
// continues to pass without a parallel API change. The downstream
|
|
15
13
|
// identity resolution uses the explicit `email` claim, not `sub`.
|
|
16
|
-
return new SignJWT({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.sign(secret);
|
|
14
|
+
return new SignJWT({
|
|
15
|
+
orgId,
|
|
16
|
+
email: normalizedEmail
|
|
17
|
+
}).setProtectedHeader({
|
|
18
|
+
alg: 'HS256'
|
|
19
|
+
}).setSubject(normalizedEmail).setAudience(WIDGET_AUDIENCE).setIssuedAt().setExpirationTime(expiresIn).sign(secret);
|
|
23
20
|
}
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=create-init-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/create-init-token.ts"],"sourcesContent":["import { SignJWT } from 'jose'\nimport { normalizeEmail } from './normalize-email.js'\nimport type { CreateInitTokenOptions } from './types.js'\n\nconst WIDGET_AUDIENCE = 'nvm:widgets'\nconst DEFAULT_EXPIRES_IN = '5m'\n\nexport async function createInitToken(options: CreateInitTokenOptions): Promise<string> {\n const { email, orgId, secretKey, expiresIn = DEFAULT_EXPIRES_IN } = options\n\n if (!secretKey?.trim()) throw new Error('secretKey is required')\n if (!orgId?.trim()) throw new Error('orgId is required')\n\n const normalizedEmail = normalizeEmail(email)\n\n const secret = new TextEncoder().encode(secretKey)\n\n // `sub` is set to the email so the API's existence check on the claim\n // continues to pass without a parallel API change. The downstream\n // identity resolution uses the explicit `email` claim, not `sub`.\n return new SignJWT({ orgId, email: normalizedEmail })\n .setProtectedHeader({ alg: 'HS256' })\n .setSubject(normalizedEmail)\n .setAudience(WIDGET_AUDIENCE)\n .setIssuedAt()\n .setExpirationTime(expiresIn)\n .sign(secret)\n}\n"],"names":["SignJWT","normalizeEmail","WIDGET_AUDIENCE","DEFAULT_EXPIRES_IN","createInitToken","options","email","orgId","secretKey","expiresIn","trim","Error","normalizedEmail","secret","TextEncoder","encode","setProtectedHeader","alg","setSubject","setAudience","setIssuedAt","setExpirationTime","sign"],"mappings":"AAAA,SAASA,OAAO,QAAQ,OAAM;AAC9B,SAASC,cAAc,QAAQ,uBAAsB;AAGrD,MAAMC,kBAAkB;AACxB,MAAMC,qBAAqB;AAE3B,OAAO,eAAeC,gBAAgBC,OAA+B;IACnE,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAEC,SAAS,EAAEC,YAAYN,kBAAkB,EAAE,GAAGE;IAEpE,IAAI,CAACG,WAAWE,QAAQ,MAAM,IAAIC,MAAM;IACxC,IAAI,CAACJ,OAAOG,QAAQ,MAAM,IAAIC,MAAM;IAEpC,MAAMC,kBAAkBX,eAAeK;IAEvC,MAAMO,SAAS,IAAIC,cAAcC,MAAM,CAACP;IAExC,sEAAsE;IACtE,kEAAkE;IAClE,kEAAkE;IAClE,OAAO,IAAIR,QAAQ;QAAEO;QAAOD,OAAOM;IAAgB,GAChDI,kBAAkB,CAAC;QAAEC,KAAK;IAAQ,GAClCC,UAAU,CAACN,iBACXO,WAAW,CAACjB,iBACZkB,WAAW,GACXC,iBAAiB,CAACZ,WAClBa,IAAI,CAACT;AACV"}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createInitToken } from './create-init-token.js'\nexport type { CreateInitTokenOptions, InitTokenPayload } from './types.js'\n"],"names":["createInitToken"],"mappings":"AAAA,SAASA,eAAe,QAAQ,yBAAwB"}
|
package/dist/normalize-email.js
CHANGED
|
@@ -16,10 +16,8 @@ const EMAIL_MAX_LENGTH = 254;
|
|
|
16
16
|
*
|
|
17
17
|
* Throws with caller-friendly messages — the SDK is the first boundary that
|
|
18
18
|
* knows the value is supposed to be an email.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
if (!email?.trim())
|
|
22
|
-
throw new Error('email is required');
|
|
19
|
+
*/ export function normalizeEmail(email) {
|
|
20
|
+
if (!email?.trim()) throw new Error('email is required');
|
|
23
21
|
const normalized = email.trim().toLowerCase();
|
|
24
22
|
if (normalized.length > EMAIL_MAX_LENGTH) {
|
|
25
23
|
throw new Error(`email is too long (max ${EMAIL_MAX_LENGTH} chars per RFC 5321)`);
|
|
@@ -29,3 +27,5 @@ export function normalizeEmail(email) {
|
|
|
29
27
|
}
|
|
30
28
|
return normalized;
|
|
31
29
|
}
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=normalize-email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/normalize-email.ts"],"sourcesContent":["// Matches the regex behind <input type=\"email\"> and what RFC 5322 implementations\n// accept in practice. Intentionally permissive — strict RFC validation belongs in\n// the integrator's auth layer, not here.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n// RFC 5321 caps email addresses at 254 chars. Enforcing here prevents a broken\n// upstream integrator from ballooning the JWT and the server-side decode path.\nconst EMAIL_MAX_LENGTH = 254\n\n/**\n * Validates and normalizes an email to a canonical form: trimmed and lowercased,\n * capped at 254 chars (RFC 5321), and matched against a permissive format regex.\n *\n * Normalization is implicit so `Alice@Example.COM` and `alice@example.com` map\n * to the same Nevermined identity downstream (#1520 — \"one email = one user,\n * one wallet, one widget profile\"). Callers should not rely on the original\n * case being preserved.\n *\n * Throws with caller-friendly messages — the SDK is the first boundary that\n * knows the value is supposed to be an email.\n */\nexport function normalizeEmail(email: string | undefined): string {\n if (!email?.trim()) throw new Error('email is required')\n\n const normalized = email.trim().toLowerCase()\n\n if (normalized.length > EMAIL_MAX_LENGTH) {\n throw new Error(`email is too long (max ${EMAIL_MAX_LENGTH} chars per RFC 5321)`)\n }\n if (!EMAIL_RE.test(normalized)) {\n throw new Error('email must be a valid email address')\n }\n\n return normalized\n}\n"],"names":["EMAIL_RE","EMAIL_MAX_LENGTH","normalizeEmail","email","trim","Error","normalized","toLowerCase","length","test"],"mappings":"AAAA,kFAAkF;AAClF,kFAAkF;AAClF,yCAAyC;AACzC,MAAMA,WAAW;AACjB,+EAA+E;AAC/E,+EAA+E;AAC/E,MAAMC,mBAAmB;AAEzB;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,eAAeC,KAAyB;IACtD,IAAI,CAACA,OAAOC,QAAQ,MAAM,IAAIC,MAAM;IAEpC,MAAMC,aAAaH,MAAMC,IAAI,GAAGG,WAAW;IAE3C,IAAID,WAAWE,MAAM,GAAGP,kBAAkB;QACxC,MAAM,IAAII,MAAM,CAAC,uBAAuB,EAAEJ,iBAAiB,oBAAoB,CAAC;IAClF;IACA,IAAI,CAACD,SAASS,IAAI,CAACH,aAAa;QAC9B,MAAM,IAAID,MAAM;IAClB;IAEA,OAAOC;AACT"}
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export interface CreateInitTokenOptions {\n /**\n * The end user's email — the canonical Nevermined identity (#1520). The\n * widget session API uses this to resolve or provision the Privy user.\n *\n * Validated and normalized at the SDK boundary: trimmed, lowercased, capped\n * at 254 chars (RFC 5321), and matched against a basic format regex. The\n * normalized value is what ends up in the JWT — callers should not rely on\n * case being preserved.\n */\n email: string\n orgId: string\n secretKey: string\n expiresIn?: string // default '5m'\n}\n\nexport interface InitTokenPayload {\n /**\n * Mirrors `email` so the widget session API's non-empty existence check on\n * `sub` passes without a parallel API change. Do NOT read `sub` for identity\n * downstream — read `email` instead. This claim will be dropped once the\n * API stops reading `sub` (follow-up to #1520).\n *\n * @deprecated Read `email` instead. Kept temporarily for API compatibility.\n */\n sub: string\n email: string\n orgId: string\n aud: string // 'nvm:widgets'\n iat: number\n exp: number\n}\n"],"names":[],"mappings":"AAgBA,WAeC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nevermined-io/ui-widgets-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -19,5 +19,25 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"jose": "4.15.9"
|
|
22
|
+
},
|
|
23
|
+
"nx": {
|
|
24
|
+
"targets": {
|
|
25
|
+
"build": {
|
|
26
|
+
"executor": "nx:run-commands",
|
|
27
|
+
"outputs": [
|
|
28
|
+
"{projectRoot}/dist"
|
|
29
|
+
],
|
|
30
|
+
"cache": true,
|
|
31
|
+
"inputs": [
|
|
32
|
+
"production",
|
|
33
|
+
"^production",
|
|
34
|
+
"{workspaceRoot}/.swcrc.lib.json"
|
|
35
|
+
],
|
|
36
|
+
"options": {
|
|
37
|
+
"cwd": "packages/ui-widgets-server",
|
|
38
|
+
"command": "pnpm exec swc src -d dist --strip-leading-paths --config-file ../../.swcrc.lib.json"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
22
42
|
}
|
|
23
43
|
}
|