@x12i/authx-token-sdk 1.0.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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @x12i/authx-token-sdk
2
+
3
+ AuthX Token Infrastructure — standalone package.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @x12i/authx-token-sdk
9
+ ```
10
+
11
+ ## Build
12
+
13
+ ```bash
14
+ npm install
15
+ npm run build
16
+ npm test
17
+ ```
18
+
19
+ ## Links
20
+
21
+ - Repository: https://github.com/x12i/authx-token-sdk
@@ -0,0 +1,12 @@
1
+ export declare class AuthxTokenError extends Error {
2
+ readonly code: string;
3
+ readonly details?: Record<string, unknown> | undefined;
4
+ constructor(message: string, code: string, details?: Record<string, unknown> | undefined);
5
+ }
6
+ export declare class AuthxInvalidTokenError extends AuthxTokenError {
7
+ constructor(message?: string, details?: Record<string, unknown>);
8
+ }
9
+ export declare class AuthxRevokedTokenError extends AuthxTokenError {
10
+ constructor(message?: string);
11
+ }
12
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,IAAI,EAAE,MAAM;aACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAFjD,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAKpD;AAED,qBAAa,sBAAuB,SAAQ,eAAe;gBAC7C,OAAO,SAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAIzE;AAED,qBAAa,sBAAuB,SAAQ,eAAe;gBAC7C,OAAO,SAAkB;CAItC"}
package/dist/errors.js ADDED
@@ -0,0 +1,23 @@
1
+ export class AuthxTokenError extends Error {
2
+ code;
3
+ details;
4
+ constructor(message, code, details) {
5
+ super(message);
6
+ this.code = code;
7
+ this.details = details;
8
+ this.name = "AuthxTokenError";
9
+ }
10
+ }
11
+ export class AuthxInvalidTokenError extends AuthxTokenError {
12
+ constructor(message = "Invalid token", details) {
13
+ super(message, "INVALID_TOKEN", details);
14
+ this.name = "AuthxInvalidTokenError";
15
+ }
16
+ }
17
+ export class AuthxRevokedTokenError extends AuthxTokenError {
18
+ constructor(message = "Token revoked") {
19
+ super(message, "REVOKED_TOKEN");
20
+ this.name = "AuthxRevokedTokenError";
21
+ }
22
+ }
23
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGtB;IACA;IAHlB,YACE,OAAe,EACC,IAAY,EACZ,OAAiC;QAEjD,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAA0B;QAGjD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,eAAe;IACzD,YAAY,OAAO,GAAG,eAAe,EAAE,OAAiC;QACtE,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,eAAe;IACzD,YAAY,OAAO,GAAG,eAAe;QACnC,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { AuthxTokenFeature, AuthxTokenPayload, AuthxTokenScope } from "@x12i/authx-token-types";
2
+ export declare function hasFeature(payload: AuthxTokenPayload, featureId: string): boolean;
3
+ export declare function getFeature(payload: AuthxTokenPayload, featureId: string): AuthxTokenFeature | undefined;
4
+ export declare function hasScopeId(scope: AuthxTokenScope | undefined, field: keyof AuthxTokenScope, id: string): boolean;
5
+ export declare function hasDomainAccess(payload: AuthxTokenPayload, domainId: string): boolean;
6
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAErG,wBAAgB,UAAU,CACxB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAKT;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,MAAM,GAChB,iBAAiB,GAAG,SAAS,CAE/B;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,eAAe,GAAG,SAAS,EAClC,KAAK,EAAE,MAAM,eAAe,EAC5B,EAAE,EAAE,MAAM,GACT,OAAO,CAKT;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,MAAM,GACf,OAAO,CAET"}
@@ -0,0 +1,19 @@
1
+ export function hasFeature(payload, featureId) {
2
+ return (payload.features?.some((f) => f.featureId === featureId && f.enabled) ??
3
+ false);
4
+ }
5
+ export function getFeature(payload, featureId) {
6
+ return payload.features?.find((f) => f.featureId === featureId);
7
+ }
8
+ export function hasScopeId(scope, field, id) {
9
+ if (!scope)
10
+ return false;
11
+ const list = scope[field];
12
+ if (!Array.isArray(list))
13
+ return false;
14
+ return list.includes(id);
15
+ }
16
+ export function hasDomainAccess(payload, domainId) {
17
+ return hasScopeId(payload.scope, "domainIds", domainId);
18
+ }
19
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CACxB,OAA0B,EAC1B,SAAiB;IAEjB,OAAO,CACL,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC;QACrE,KAAK,CACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,OAA0B,EAC1B,SAAiB;IAEjB,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAAkC,EAClC,KAA4B,EAC5B,EAAU;IAEV,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAQ,IAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,OAA0B,EAC1B,QAAgB;IAEhB,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { AuthxInvalidTokenError, AuthxRevokedTokenError, AuthxTokenError, } from "./errors.js";
2
+ export { getFeature, hasDomainAccess, hasFeature, hasScopeId, } from "./helpers.js";
3
+ export { createAuthxTokenVerifier, type AuthxTokenVerifier, type AuthxVerifierConfig, } from "./verifier.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { AuthxInvalidTokenError, AuthxRevokedTokenError, AuthxTokenError, } from "./errors.js";
2
+ export { getFeature, hasDomainAccess, hasFeature, hasScopeId, } from "./helpers.js";
3
+ export { createAuthxTokenVerifier, } from "./verifier.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAGzB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { NextFunction, Request, Response } from "express";
2
+ import type { AuthxTokenPayload } from "@x12i/authx-token-types";
3
+ import { type AuthxVerifierConfig } from "../verifier.js";
4
+ declare global {
5
+ namespace Express {
6
+ interface Request {
7
+ authxToken?: AuthxTokenPayload;
8
+ }
9
+ }
10
+ }
11
+ export type AuthxExpressMiddlewareOptions = AuthxVerifierConfig & {
12
+ optional?: boolean;
13
+ };
14
+ export declare function authxTokenMiddleware(options: AuthxExpressMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
15
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAKjE,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAExB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,UAAU,CAAC,EAAE,iBAAiB,CAAC;SAChC;KACF;CACF;AAED,MAAM,MAAM,6BAA6B,GAAG,mBAAmB,GAAG;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAQF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,6BAA6B,IAE3D,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,wDAmB9D"}
@@ -0,0 +1,33 @@
1
+ import { AuthxInvalidTokenError, AuthxRevokedTokenError, } from "../errors.js";
2
+ import { createAuthxTokenVerifier, } from "../verifier.js";
3
+ function extractBearer(req) {
4
+ const header = req.headers.authorization;
5
+ if (!header?.startsWith("Bearer "))
6
+ return undefined;
7
+ return header.slice(7);
8
+ }
9
+ export function authxTokenMiddleware(options) {
10
+ const verifier = createAuthxTokenVerifier(options);
11
+ return async (req, res, next) => {
12
+ const token = extractBearer(req);
13
+ if (!token) {
14
+ if (options.optional)
15
+ return next();
16
+ return res.status(401).json({ error: "Missing bearer token" });
17
+ }
18
+ try {
19
+ req.authxToken = await verifier.assertValid(token);
20
+ return next();
21
+ }
22
+ catch (err) {
23
+ if (err instanceof AuthxRevokedTokenError) {
24
+ return res.status(401).json({ error: err.message, code: err.code });
25
+ }
26
+ if (err instanceof AuthxInvalidTokenError) {
27
+ return res.status(401).json({ error: err.message, code: err.code });
28
+ }
29
+ return next(err);
30
+ }
31
+ };
32
+ }
33
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,gBAAgB,CAAC;AAcxB,SAAS,aAAa,CAAC,GAAY;IACjC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACrD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAsC;IACzE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC/D,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,OAAO,CAAC,QAAQ;gBAAE,OAAO,IAAI,EAAE,CAAC;YACpC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC;YACH,GAAG,CAAC,UAAU,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACnD,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC1C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC1C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC;YACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FastifyPluginAsync } from "fastify";
2
+ import type { AuthxTokenPayload } from "@x12i/authx-token-types";
3
+ import { type AuthxVerifierConfig } from "../verifier.js";
4
+ declare module "fastify" {
5
+ interface FastifyRequest {
6
+ authxToken?: AuthxTokenPayload;
7
+ }
8
+ }
9
+ export type AuthxFastifyPluginOptions = AuthxVerifierConfig & {
10
+ optional?: boolean;
11
+ };
12
+ export declare const authxTokenFastifyPlugin: FastifyPluginAsync<AuthxFastifyPluginOptions>;
13
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAKjE,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAExB,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAChC;CACF;AAED,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,GAAG;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAUF,eAAO,MAAM,uBAAuB,EAAE,kBAAkB,CACtD,yBAAyB,CAsB1B,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { AuthxInvalidTokenError, AuthxRevokedTokenError, } from "../errors.js";
2
+ import { createAuthxTokenVerifier, } from "../verifier.js";
3
+ function extractBearer(request) {
4
+ const header = request.headers.authorization;
5
+ if (typeof header !== "string" || !header.startsWith("Bearer ")) {
6
+ return undefined;
7
+ }
8
+ return header.slice(7);
9
+ }
10
+ export const authxTokenFastifyPlugin = async (fastify, options) => {
11
+ const verifier = createAuthxTokenVerifier(options);
12
+ fastify.addHook("onRequest", async (request, reply) => {
13
+ const token = extractBearer(request);
14
+ if (!token) {
15
+ if (options.optional)
16
+ return;
17
+ return reply.status(401).send({ error: "Missing bearer token" });
18
+ }
19
+ try {
20
+ request.authxToken = await verifier.assertValid(token);
21
+ }
22
+ catch (err) {
23
+ if (err instanceof AuthxInvalidTokenError ||
24
+ err instanceof AuthxRevokedTokenError) {
25
+ return reply.status(401).send({ error: err.message, code: err.code });
26
+ }
27
+ throw err;
28
+ }
29
+ });
30
+ };
31
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,gBAAgB,CAAC;AAYxB,SAAS,aAAa,CAAC,OAAuB;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAEhC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC7B,MAAM,QAAQ,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAEnD,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,OAAO,CAAC,QAAQ;gBAAE,OAAO;YAC7B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,UAAU,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IACE,GAAG,YAAY,sBAAsB;gBACrC,GAAG,YAAY,sBAAsB,EACrC,CAAC;gBACD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACxE,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { AuthxTokenIntrospectResponse, AuthxTokenPayload, AuthxTokenVerifyResponse } from "@x12i/authx-token-types";
2
+ export interface AuthxVerifierConfig {
3
+ appId: string;
4
+ appSecretKey: string;
5
+ keyVersion?: number;
6
+ previousAppSecretKey?: string;
7
+ previousKeyVersion?: number;
8
+ issuer?: string;
9
+ audience?: string[];
10
+ /** Remote introspection URL (e.g. https://authx/v1/tokens/introspect) */
11
+ introspectUrl?: string;
12
+ apiKey?: string;
13
+ }
14
+ export interface AuthxTokenVerifier {
15
+ verify(token: string): Promise<AuthxTokenVerifyResponse>;
16
+ decrypt(token: string): Promise<AuthxTokenVerifyResponse>;
17
+ introspect(token: string): Promise<AuthxTokenIntrospectResponse>;
18
+ assertValid(token: string): Promise<AuthxTokenPayload>;
19
+ hasFeature(payload: AuthxTokenPayload, featureId: string): boolean;
20
+ hasScopeId(payload: AuthxTokenPayload, field: keyof NonNullable<AuthxTokenPayload["scope"]>, id: string): boolean;
21
+ }
22
+ export declare function createAuthxTokenVerifier(config: AuthxVerifierConfig): AuthxTokenVerifier;
23
+ //# sourceMappingURL=verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../src/verifier.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,4BAA4B,EAC5B,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC1D,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACjE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACvD,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,UAAU,CACR,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,MAAM,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,EACpD,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;CACZ;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,GAC1B,kBAAkB,CAqGpB"}
@@ -0,0 +1,97 @@
1
+ import { decryptToken, verifyToken, } from "@x12i/authx-token-core";
2
+ import { AuthxInvalidTokenError, AuthxRevokedTokenError } from "./errors.js";
3
+ import { hasFeature, hasScopeId } from "./helpers.js";
4
+ export function createAuthxTokenVerifier(config) {
5
+ const cryptoOptions = {
6
+ appSecretKey: config.appSecretKey,
7
+ keyVersion: config.keyVersion,
8
+ previousAppSecretKey: config.previousAppSecretKey,
9
+ previousKeyVersion: config.previousKeyVersion,
10
+ expectedAppId: config.appId,
11
+ expectedIssuer: config.issuer,
12
+ expectedAudience: config.audience,
13
+ };
14
+ async function remoteIntrospect(token) {
15
+ if (!config.introspectUrl) {
16
+ throw new Error("introspectUrl not configured");
17
+ }
18
+ const headers = {
19
+ "content-type": "application/json",
20
+ };
21
+ if (config.apiKey) {
22
+ headers["x-authx-api-key"] = config.apiKey;
23
+ }
24
+ const res = await fetch(config.introspectUrl, {
25
+ method: "POST",
26
+ headers,
27
+ body: JSON.stringify({ token }),
28
+ });
29
+ if (!res.ok) {
30
+ throw new AuthxInvalidTokenError(`Introspection failed: ${res.status}`);
31
+ }
32
+ return res.json();
33
+ }
34
+ function wrapResult(result) {
35
+ if (!result.valid) {
36
+ return {
37
+ valid: false,
38
+ error: result.error,
39
+ expired: result.expired,
40
+ };
41
+ }
42
+ return { valid: true, payload: result.payload };
43
+ }
44
+ return {
45
+ async verify(token) {
46
+ const local = wrapResult(verifyToken(token, cryptoOptions));
47
+ if (!local.valid)
48
+ return local;
49
+ if (config.introspectUrl) {
50
+ const remote = await remoteIntrospect(token);
51
+ if (!remote.active || remote.revoked) {
52
+ return {
53
+ valid: false,
54
+ revoked: remote.revoked,
55
+ expired: remote.expired,
56
+ error: "token inactive",
57
+ };
58
+ }
59
+ }
60
+ return local;
61
+ },
62
+ async decrypt(token) {
63
+ return wrapResult(decryptToken(token, cryptoOptions));
64
+ },
65
+ async introspect(token) {
66
+ if (config.introspectUrl) {
67
+ return remoteIntrospect(token);
68
+ }
69
+ const verified = await this.verify(token);
70
+ return {
71
+ active: verified.valid,
72
+ tokenId: verified.payload?.tokenId,
73
+ appId: verified.payload?.appId,
74
+ payload: verified.payload,
75
+ revoked: Boolean(verified.revoked),
76
+ expired: Boolean(verified.expired),
77
+ expiresAt: verified.payload?.expiresAt,
78
+ };
79
+ },
80
+ async assertValid(token) {
81
+ const result = await this.verify(token);
82
+ if (result.revoked)
83
+ throw new AuthxRevokedTokenError();
84
+ if (!result.valid || !result.payload) {
85
+ throw new AuthxInvalidTokenError(result.error ?? "Invalid token", {
86
+ expired: result.expired,
87
+ });
88
+ }
89
+ return result.payload;
90
+ },
91
+ hasFeature,
92
+ hasScopeId(payload, field, id) {
93
+ return hasScopeId(payload.scope, field, id);
94
+ },
95
+ };
96
+ }
97
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../src/verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verifier.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.test.d.ts","sourceRoot":"","sources":["../src/verifier.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { createToken } from "@x12i/authx-token-core";
2
+ import { describe, expect, it } from "vitest";
3
+ import { createAuthxTokenVerifier } from "./verifier.js";
4
+ const secret = "sdk-test-secret-key-32chars-min!!";
5
+ const appId = "sdk-app";
6
+ describe("authx-token-sdk", () => {
7
+ const verifier = createAuthxTokenVerifier({
8
+ appId,
9
+ appSecretKey: secret,
10
+ });
11
+ it("verifies valid tokens", async () => {
12
+ const { token } = createToken({
13
+ appId,
14
+ appSecretKey: secret,
15
+ subject: { identityId: "u1", identityType: "user" },
16
+ features: [{ featureId: "catalog.read", enabled: true }],
17
+ scope: { domainIds: ["sales"] },
18
+ });
19
+ const result = await verifier.verify(token);
20
+ expect(result.valid).toBe(true);
21
+ expect(verifier.hasFeature(result.payload, "catalog.read")).toBe(true);
22
+ expect(verifier.hasScopeId(result.payload, "domainIds", "sales")).toBe(true);
23
+ });
24
+ it("rejects invalid scope check", async () => {
25
+ const { token } = createToken({
26
+ appId,
27
+ appSecretKey: secret,
28
+ subject: { identityId: "u1", identityType: "user" },
29
+ });
30
+ const result = await verifier.verify(token);
31
+ expect(verifier.hasScopeId(result.payload, "domainIds", "finance")).toBe(false);
32
+ });
33
+ it("rejects invalid tokens", async () => {
34
+ const result = await verifier.verify("not-a-token");
35
+ expect(result.valid).toBe(false);
36
+ });
37
+ });
38
+ //# sourceMappingURL=verifier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.test.js","sourceRoot":"","sources":["../src/verifier.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,MAAM,GAAG,mCAAmC,CAAC;AACnD,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,KAAK;QACL,YAAY,EAAE,MAAM;KACrB,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACrC,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC;YAC5B,KAAK;YACL,YAAY,EAAE,MAAM;YACpB,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE;YACnD,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACxD,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;SAChC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,OAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,OAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CACrE,IAAI,CACL,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC;YAC5B,KAAK;YACL,YAAY,EAAE,MAAM;YACpB,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE;SACpD,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,OAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CACvE,KAAK,CACN,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@x12i/authx-token-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Consumer SDK for verifying and introspecting AuthX tokens",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/x12i/authx-token-sdk.git"
8
+ },
9
+ "bugs": "https://github.com/x12i/authx-token-sdk/issues",
10
+ "homepage": "https://github.com/x12i/authx-token-sdk#readme",
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ },
19
+ "./express": {
20
+ "types": "./dist/middleware/express.d.ts",
21
+ "import": "./dist/middleware/express.js"
22
+ },
23
+ "./fastify": {
24
+ "types": "./dist/middleware/fastify.d.ts",
25
+ "import": "./dist/middleware/fastify.js"
26
+ }
27
+ },
28
+ "files": ["dist"],
29
+ "scripts": {
30
+ "build": "tsc -p tsconfig.json",
31
+ "test": "vitest run",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit",
33
+ "lint": "echo ok"
34
+ },
35
+ "dependencies": {
36
+ "@x12i/authx-token-core": "1.0.0",
37
+ "@x12i/authx-token-types": "1.0.0"
38
+ },
39
+ "peerDependencies": {
40
+ "express": ">=4",
41
+ "fastify": ">=4"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "express": { "optional": true },
45
+ "fastify": { "optional": true }
46
+ },
47
+ "devDependencies": {
48
+ "@types/express": "^5.0.2",
49
+ "express": "^5.1.0",
50
+ "fastify": "^5.3.3",
51
+ "typescript": "^5.8.3",
52
+ "vitest": "^3.2.1"
53
+ },
54
+ "publishConfig": {
55
+ "access": "restricted"
56
+ }
57
+ }