@tidecloak/verify 0.9.11 → 0.9.13

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TideCloak Verify SDK
2
2
 
3
- A lightweight utility for server-side verification of TideCloak-issued JSON Web Tokens (JWTs).
3
+ A lightweight utility for serverside verification of TideCloakissued JSON Web Tokens (JWTs).
4
4
 
5
5
  This package exports a single function, `verifyTideCloakToken`, which you can use in your Next.js API routes, Node.js servers, or any backend to verify the authenticity, issuer, audience, and roles of a JWT issued by your TideCloak realm.
6
6
 
@@ -0,0 +1,53 @@
1
+ import { jwtVerify, createLocalJWKSet, createRemoteJWKSet } from "jose";
2
+ /**
3
+ * Verify a TideCloak-issued JWT on the server side using your imported config object.
4
+ *
5
+ * @param {object} config - Imported TideCloak configuration (parsed JSON).
6
+ * @param {string} token - access token to verify.
7
+ * @param {string[]} [allowedRoles] - Array of Keycloak realm or client roles; user must have at least one.
8
+ * @returns {Promise<object|null>} - The token payload if valid and role-check passes, otherwise null.
9
+ */
10
+ export async function verifyTideCloakToken(config, token, allowedRoles = []) {
11
+ var _a, _b, _c;
12
+ try {
13
+ // Ensure token is provided
14
+ if (!token) {
15
+ throw new Error("No token provided");
16
+ }
17
+ // Ensure config is provided
18
+ if (!config || Object.keys(config).length === 0) {
19
+ throw new Error("Could not load TideCloak configuration");
20
+ }
21
+ // Construct issuer URL (ensure slash before 'realms')
22
+ const baseUrl = config["auth-server-url"];
23
+ const sep = baseUrl.endsWith("/") ? "" : "/";
24
+ const issuer = `${baseUrl}${sep}realms/${config.realm}`;
25
+ // Determine JWK set (use local JWKs if provided, otherwise fetch remotely)
26
+ const jwkSet = config.jwk
27
+ ? createLocalJWKSet(config.jwk)
28
+ : createRemoteJWKSet(new URL(`${issuer}/protocol/openid-connect/certs`));
29
+ // Verify token signature and issuer
30
+ const { payload } = await jwtVerify(token, jwkSet, { issuer });
31
+ // Verify authorized party (client)
32
+ const client = config["resource"];
33
+ if (payload.azp !== client) {
34
+ throw new Error(`AZP mismatch: expected '${config.resource}', got '${payload.azp}'`);
35
+ }
36
+ // Gather all user roles from realm and client roles for the specified resource from the config.
37
+ const realmRoles = ((_a = payload.realm_access) === null || _a === void 0 ? void 0 : _a.roles) || [];
38
+ const clientRoles = ((_c = (_b = payload.resource_access) === null || _b === void 0 ? void 0 : _b[client]) === null || _c === void 0 ? void 0 : _c.roles) || [];
39
+ const allRoles = new Set([...realmRoles, ...clientRoles]);
40
+ // If allowedRoles specified, ensure at least one match
41
+ if (allowedRoles.length > 0) {
42
+ const hasAllowed = allowedRoles.some(role => allRoles.has(role));
43
+ if (!hasAllowed) {
44
+ throw new Error(`Role match failed: user roles [${[...allRoles].join(", ")}] do not include any of [${allowedRoles.join(", ")}]`);
45
+ }
46
+ }
47
+ return payload;
48
+ }
49
+ catch (err) {
50
+ console.error("[TideJWT] Token verification failed:", err);
51
+ return null;
52
+ }
53
+ }
@@ -0,0 +1,53 @@
1
+ import { jwtVerify, createLocalJWKSet, createRemoteJWKSet } from "jose";
2
+ /**
3
+ * Verify a TideCloak-issued JWT on the server side using your imported config object.
4
+ *
5
+ * @param {object} config - Imported TideCloak configuration (parsed JSON).
6
+ * @param {string} token - access token to verify.
7
+ * @param {string[]} [allowedRoles] - Array of Keycloak realm or client roles; user must have at least one.
8
+ * @returns {Promise<object|null>} - The token payload if valid and role-check passes, otherwise null.
9
+ */
10
+ export async function verifyTideCloakToken(config, token, allowedRoles = []) {
11
+ var _a, _b, _c;
12
+ try {
13
+ // Ensure token is provided
14
+ if (!token) {
15
+ throw new Error("No token provided");
16
+ }
17
+ // Ensure config is provided
18
+ if (!config || Object.keys(config).length === 0) {
19
+ throw new Error("Could not load TideCloak configuration");
20
+ }
21
+ // Construct issuer URL (ensure slash before 'realms')
22
+ const baseUrl = config["auth-server-url"];
23
+ const sep = baseUrl.endsWith("/") ? "" : "/";
24
+ const issuer = `${baseUrl}${sep}realms/${config.realm}`;
25
+ // Determine JWK set (use local JWKs if provided, otherwise fetch remotely)
26
+ const jwkSet = config.jwk
27
+ ? createLocalJWKSet(config.jwk)
28
+ : createRemoteJWKSet(new URL(`${issuer}/protocol/openid-connect/certs`));
29
+ // Verify token signature and issuer
30
+ const { payload } = await jwtVerify(token, jwkSet, { issuer });
31
+ // Verify authorized party (client)
32
+ const client = config["resource"];
33
+ if (payload.azp !== client) {
34
+ throw new Error(`AZP mismatch: expected '${config.resource}', got '${payload.azp}'`);
35
+ }
36
+ // Gather all user roles from realm and client roles for the specified resource from the config.
37
+ const realmRoles = ((_a = payload.realm_access) === null || _a === void 0 ? void 0 : _a.roles) || [];
38
+ const clientRoles = ((_c = (_b = payload.resource_access) === null || _b === void 0 ? void 0 : _b[client]) === null || _c === void 0 ? void 0 : _c.roles) || [];
39
+ const allRoles = new Set([...realmRoles, ...clientRoles]);
40
+ // If allowedRoles specified, ensure at least one match
41
+ if (allowedRoles.length > 0) {
42
+ const hasAllowed = allowedRoles.some(role => allRoles.has(role));
43
+ if (!hasAllowed) {
44
+ throw new Error(`Role match failed: user roles [${[...allRoles].join(", ")}] do not include any of [${allowedRoles.join(", ")}]`);
45
+ }
46
+ }
47
+ return payload;
48
+ }
49
+ catch (err) {
50
+ console.error("[TideJWT] Token verification failed:", err);
51
+ return null;
52
+ }
53
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Verify a TideCloak-issued JWT on the server side using your imported config object.
3
+ *
4
+ * @param {object} config - Imported TideCloak configuration (parsed JSON).
5
+ * @param {string} token - access token to verify.
6
+ * @param {string[]} [allowedRoles] - Array of Keycloak realm or client roles; user must have at least one.
7
+ * @returns {Promise<object|null>} - The token payload if valid and role-check passes, otherwise null.
8
+ */
9
+ export function verifyTideCloakToken(config: object, token: string, allowedRoles?: string[]): Promise<object | null>;
10
+ //# sourceMappingURL=TideJWT.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TideJWT.d.ts","sourceRoot":"","sources":["../../src/TideJWT.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,6CALW,MAAM,SACN,MAAM,iBACN,MAAM,EAAE,GACN,OAAO,CAAC,MAAM,GAAC,IAAI,CAAC,CAsDhC"}
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@tidecloak/verify",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "description": "A lightweight utility for server-side verification of TideCloak-issued JSON Web Tokens (JWTs).",
5
5
  "exports": {
6
6
  ".": {
7
- "types": "./src/TideJWT.d.ts",
8
- "default": "./src/TideJWT.js"
7
+ "import": "./dist/esm/TideJWT.js",
8
+ "types": "./dist/types/TideJWT.d.ts",
9
+ "require": "./dist/cjs/TideJWT.js"
9
10
  }
10
11
  },
11
12
  "files": [
12
- "src"
13
+ "dist"
13
14
  ],
14
15
  "scripts": {
15
16
  "build:cjs": "tsc -p tsconfig.cjs.json",
package/src/TideJWT.js DELETED
@@ -1,63 +0,0 @@
1
- import { jwtVerify, createLocalJWKSet, createRemoteJWKSet } from "jose";
2
-
3
- /**
4
- * Verify a TideCloak-issued JWT on the server side using your imported config object.
5
- *
6
- * @param {object} config - Imported TideCloak configuration (parsed JSON).
7
- * @param {string} token - access token to verify.
8
- * @param {string[]} [allowedRoles] - Array of Keycloak realm or client roles; user must have at least one.
9
- * @returns {Promise<object|null>} - The token payload if valid and role-check passes, otherwise null.
10
- */
11
- export async function verifyTideCloakToken(config, token, allowedRoles = []) {
12
- try {
13
-
14
- // Ensure token is provided
15
- if (!token) {
16
- throw new Error("No token provided");
17
- }
18
-
19
- // Ensure config is provided
20
- if (!config || Object.keys(config).length === 0) {
21
- throw new Error("Could not load TideCloak configuration");
22
- }
23
-
24
- // Construct issuer URL (ensure slash before 'realms')
25
- const baseUrl = config["auth-server-url"];
26
- const sep = baseUrl.endsWith("/") ? "" : "/";
27
- const issuer = `${baseUrl}${sep}realms/${config.realm}`;
28
-
29
- // Determine JWK set (use local JWKs if provided, otherwise fetch remotely)
30
- const jwkSet = config.jwk
31
- ? createLocalJWKSet(config.jwk)
32
- : createRemoteJWKSet(new URL(`${issuer}/protocol/openid-connect/certs`));
33
-
34
- // Verify token signature and issuer
35
- const { payload } = await jwtVerify(token, jwkSet, { issuer });
36
-
37
- // Verify authorized party (client)
38
- const client = config["resource"];
39
- if (payload.azp !== client) {
40
- throw new Error(`AZP mismatch: expected '${config.resource}', got '${payload.azp}'`);
41
- }
42
-
43
- // Gather all user roles from realm and client roles for the specified resource from the config.
44
- const realmRoles = payload.realm_access?.roles || [];
45
- const clientRoles = payload.resource_access?.[client]?.roles || [];
46
- const allRoles = new Set([...realmRoles, ...clientRoles]);
47
-
48
- // If allowedRoles specified, ensure at least one match
49
- if (allowedRoles.length > 0) {
50
- const hasAllowed = allowedRoles.some(role => allRoles.has(role));
51
- if (!hasAllowed) {
52
- throw new Error(
53
- `Role match failed: user roles [${[...allRoles].join(", ")}] do not include any of [${allowedRoles.join(", ")}]`
54
- );
55
- }
56
- }
57
-
58
- return payload;
59
- } catch (err) {
60
- console.error("[TideJWT] Token verification failed:", err);
61
- return null;
62
- }
63
- }