@drmhse/authos-node 0.1.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/express.d.mts +24 -0
- package/dist/express.d.ts +24 -0
- package/dist/express.js +395 -0
- package/dist/express.mjs +373 -0
- package/dist/index.d.mts +67 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +296 -0
- package/dist/index.mjs +269 -0
- package/dist/types-C4aDSNcp.d.mts +98 -0
- package/dist/types-C4aDSNcp.d.ts +98 -0
- package/package.json +81 -0
package/dist/express.mjs
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
|
|
3
|
+
// src/jwks.ts
|
|
4
|
+
var jwksCache = /* @__PURE__ */ new Map();
|
|
5
|
+
var DEFAULT_CACHE_TTL = 60 * 60 * 1e3;
|
|
6
|
+
function base64UrlDecode(input) {
|
|
7
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
8
|
+
const pad = base64.length % 4;
|
|
9
|
+
const padded = pad ? base64 + "=".repeat(4 - pad) : base64;
|
|
10
|
+
return Buffer.from(padded, "base64");
|
|
11
|
+
}
|
|
12
|
+
function jwkToPem(jwk) {
|
|
13
|
+
if (jwk.kty !== "RSA" || !jwk.n || !jwk.e) {
|
|
14
|
+
throw new Error("Only RSA keys are supported");
|
|
15
|
+
}
|
|
16
|
+
const n = base64UrlDecode(jwk.n);
|
|
17
|
+
const e = base64UrlDecode(jwk.e);
|
|
18
|
+
const nInt = encodeASN1Integer(n);
|
|
19
|
+
const eInt = encodeASN1Integer(e);
|
|
20
|
+
const rsaPublicKey = encodeASN1Sequence(Buffer.concat([nInt, eInt]));
|
|
21
|
+
const bitString = Buffer.concat([
|
|
22
|
+
Buffer.from([3]),
|
|
23
|
+
encodeASN1Length(rsaPublicKey.length + 1),
|
|
24
|
+
Buffer.from([0]),
|
|
25
|
+
// no unused bits
|
|
26
|
+
rsaPublicKey
|
|
27
|
+
]);
|
|
28
|
+
const algorithmIdentifier = Buffer.from([
|
|
29
|
+
48,
|
|
30
|
+
13,
|
|
31
|
+
// SEQUENCE
|
|
32
|
+
6,
|
|
33
|
+
9,
|
|
34
|
+
// OID
|
|
35
|
+
42,
|
|
36
|
+
134,
|
|
37
|
+
72,
|
|
38
|
+
134,
|
|
39
|
+
247,
|
|
40
|
+
13,
|
|
41
|
+
1,
|
|
42
|
+
1,
|
|
43
|
+
1,
|
|
44
|
+
// 1.2.840.113549.1.1.1
|
|
45
|
+
5,
|
|
46
|
+
0
|
|
47
|
+
// NULL
|
|
48
|
+
]);
|
|
49
|
+
const subjectPublicKeyInfo = encodeASN1Sequence(
|
|
50
|
+
Buffer.concat([algorithmIdentifier, bitString])
|
|
51
|
+
);
|
|
52
|
+
const base64Key = subjectPublicKeyInfo.toString("base64");
|
|
53
|
+
const lines = base64Key.match(/.{1,64}/g) || [];
|
|
54
|
+
return `-----BEGIN PUBLIC KEY-----
|
|
55
|
+
${lines.join("\n")}
|
|
56
|
+
-----END PUBLIC KEY-----`;
|
|
57
|
+
}
|
|
58
|
+
function encodeASN1Length(length) {
|
|
59
|
+
if (length < 128) {
|
|
60
|
+
return Buffer.from([length]);
|
|
61
|
+
}
|
|
62
|
+
const bytes = [];
|
|
63
|
+
let len = length;
|
|
64
|
+
while (len > 0) {
|
|
65
|
+
bytes.unshift(len & 255);
|
|
66
|
+
len = len >> 8;
|
|
67
|
+
}
|
|
68
|
+
return Buffer.from([128 | bytes.length, ...bytes]);
|
|
69
|
+
}
|
|
70
|
+
function encodeASN1Integer(value) {
|
|
71
|
+
const needsPadding = value[0] & 128;
|
|
72
|
+
const content = needsPadding ? Buffer.concat([Buffer.from([0]), value]) : value;
|
|
73
|
+
return Buffer.concat([
|
|
74
|
+
Buffer.from([2]),
|
|
75
|
+
// INTEGER tag
|
|
76
|
+
encodeASN1Length(content.length),
|
|
77
|
+
content
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
function encodeASN1Sequence(content) {
|
|
81
|
+
return Buffer.concat([
|
|
82
|
+
Buffer.from([48]),
|
|
83
|
+
// SEQUENCE tag
|
|
84
|
+
encodeASN1Length(content.length),
|
|
85
|
+
content
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
async function fetchJWKS(baseURL) {
|
|
89
|
+
const url = `${baseURL.replace(/\/$/, "")}/.well-known/jwks.json`;
|
|
90
|
+
const response = await fetch(url);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`Failed to fetch JWKS: ${response.status} ${response.statusText}`);
|
|
93
|
+
}
|
|
94
|
+
return response.json();
|
|
95
|
+
}
|
|
96
|
+
async function getJWKS(baseURL, cacheTTL) {
|
|
97
|
+
const cached = jwksCache.get(baseURL);
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
if (cached && now - cached.fetchedAt < cacheTTL) {
|
|
100
|
+
return cached.jwks;
|
|
101
|
+
}
|
|
102
|
+
const jwks = await fetchJWKS(baseURL);
|
|
103
|
+
jwksCache.set(baseURL, { jwks, fetchedAt: now });
|
|
104
|
+
return jwks;
|
|
105
|
+
}
|
|
106
|
+
function findKey(jwks, kid) {
|
|
107
|
+
return jwks.keys.find((key) => key.kid === kid) || null;
|
|
108
|
+
}
|
|
109
|
+
var TokenVerificationError = class extends Error {
|
|
110
|
+
constructor(message, code) {
|
|
111
|
+
super(message);
|
|
112
|
+
this.code = code;
|
|
113
|
+
this.name = "TokenVerificationError";
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
function parseJWT(token) {
|
|
117
|
+
const parts = token.split(".");
|
|
118
|
+
if (parts.length !== 3) {
|
|
119
|
+
throw new TokenVerificationError("Invalid JWT format", "INVALID_TOKEN_FORMAT");
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const header = JSON.parse(base64UrlDecode(parts[0]).toString("utf8"));
|
|
123
|
+
const payload = JSON.parse(base64UrlDecode(parts[1]).toString("utf8"));
|
|
124
|
+
return { header, payload };
|
|
125
|
+
} catch {
|
|
126
|
+
throw new TokenVerificationError("Invalid JWT encoding", "INVALID_TOKEN_FORMAT");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function createTokenVerifier(options) {
|
|
130
|
+
const { baseURL, jwksCacheTTL = DEFAULT_CACHE_TTL } = options;
|
|
131
|
+
async function verifyToken(token, verifyOptions = {}) {
|
|
132
|
+
const { audience, issuer, clockTolerance = 0 } = verifyOptions;
|
|
133
|
+
const { header, payload } = parseJWT(token);
|
|
134
|
+
if (header.alg !== "RS256") {
|
|
135
|
+
throw new TokenVerificationError(
|
|
136
|
+
`Unsupported algorithm: ${header.alg}. Only RS256 is supported.`,
|
|
137
|
+
"INVALID_ALGORITHM"
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const kid = header.kid;
|
|
141
|
+
if (!kid) {
|
|
142
|
+
throw new TokenVerificationError("Token missing kid header", "MISSING_KID");
|
|
143
|
+
}
|
|
144
|
+
const jwks = await getJWKS(baseURL, jwksCacheTTL);
|
|
145
|
+
const jwk = findKey(jwks, kid);
|
|
146
|
+
if (!jwk) {
|
|
147
|
+
const freshJwks = await fetchJWKS(baseURL);
|
|
148
|
+
jwksCache.set(baseURL, { jwks: freshJwks, fetchedAt: Date.now() });
|
|
149
|
+
const freshJwk = findKey(freshJwks, kid);
|
|
150
|
+
if (!freshJwk) {
|
|
151
|
+
throw new TokenVerificationError(
|
|
152
|
+
`No matching key found for kid: ${kid}`,
|
|
153
|
+
"KEY_NOT_FOUND"
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return verifyWithKey(token, freshJwk, payload, { audience, issuer, clockTolerance });
|
|
157
|
+
}
|
|
158
|
+
return verifyWithKey(token, jwk, payload, { audience, issuer, clockTolerance });
|
|
159
|
+
}
|
|
160
|
+
return { verifyToken };
|
|
161
|
+
}
|
|
162
|
+
function verifyWithKey(token, jwk, payload, options) {
|
|
163
|
+
const { audience, issuer, clockTolerance } = options;
|
|
164
|
+
const pem = jwkToPem(jwk);
|
|
165
|
+
const parts = token.split(".");
|
|
166
|
+
const signatureInput = `${parts[0]}.${parts[1]}`;
|
|
167
|
+
const signature = base64UrlDecode(parts[2]);
|
|
168
|
+
const verifier = crypto.createVerify("RSA-SHA256");
|
|
169
|
+
verifier.update(signatureInput);
|
|
170
|
+
if (!verifier.verify(pem, signature)) {
|
|
171
|
+
throw new TokenVerificationError("Invalid token signature", "INVALID_SIGNATURE");
|
|
172
|
+
}
|
|
173
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
174
|
+
if (payload.exp && payload.exp + clockTolerance < now) {
|
|
175
|
+
throw new TokenVerificationError("Token has expired", "TOKEN_EXPIRED");
|
|
176
|
+
}
|
|
177
|
+
if (payload.iat && payload.iat - clockTolerance > now) {
|
|
178
|
+
throw new TokenVerificationError("Token is not yet valid", "TOKEN_NOT_YET_VALID");
|
|
179
|
+
}
|
|
180
|
+
if (audience) {
|
|
181
|
+
const tokenAud = payload.aud;
|
|
182
|
+
const validAud = Array.isArray(tokenAud) ? tokenAud.includes(audience) : tokenAud === audience;
|
|
183
|
+
if (!validAud) {
|
|
184
|
+
throw new TokenVerificationError("Invalid token audience", "INVALID_AUDIENCE");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (issuer) {
|
|
188
|
+
const tokenIss = payload.iss;
|
|
189
|
+
if (tokenIss !== issuer) {
|
|
190
|
+
throw new TokenVerificationError("Invalid token issuer", "INVALID_ISSUER");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return { claims: payload, token };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/express/middleware.ts
|
|
197
|
+
function extractBearerToken(req) {
|
|
198
|
+
const authHeader = req.headers.authorization;
|
|
199
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return authHeader.slice(7);
|
|
203
|
+
}
|
|
204
|
+
function createAuthMiddleware(options) {
|
|
205
|
+
const verifier = createTokenVerifier(options);
|
|
206
|
+
function requireAuth(authOptions = {}) {
|
|
207
|
+
const { getToken, ...verifyOptions } = authOptions;
|
|
208
|
+
return async (req, res, next) => {
|
|
209
|
+
try {
|
|
210
|
+
const token = getToken ? getToken(req) : extractBearerToken(req);
|
|
211
|
+
if (!token) {
|
|
212
|
+
res.status(401).json({
|
|
213
|
+
error: "Unauthorized",
|
|
214
|
+
message: "Missing authentication token",
|
|
215
|
+
code: "MISSING_TOKEN"
|
|
216
|
+
});
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const verified = await verifier.verifyToken(token, verifyOptions);
|
|
220
|
+
req.auth = verified;
|
|
221
|
+
next();
|
|
222
|
+
} catch (err) {
|
|
223
|
+
if (err instanceof TokenVerificationError) {
|
|
224
|
+
res.status(401).json({
|
|
225
|
+
error: "Unauthorized",
|
|
226
|
+
message: err.message,
|
|
227
|
+
code: err.code
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
console.error("Auth middleware error:", err);
|
|
232
|
+
res.status(500).json({
|
|
233
|
+
error: "Internal Server Error",
|
|
234
|
+
message: "Authentication verification failed"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function requirePermission(permission, permOptions = {}) {
|
|
240
|
+
const { message = "Insufficient permissions" } = permOptions;
|
|
241
|
+
return (req, res, next) => {
|
|
242
|
+
if (!req.auth) {
|
|
243
|
+
res.status(401).json({
|
|
244
|
+
error: "Unauthorized",
|
|
245
|
+
message: "Authentication required",
|
|
246
|
+
code: "NOT_AUTHENTICATED"
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const permissions = req.auth.claims.permissions || [];
|
|
251
|
+
const hasPermission = permissions.includes(permission);
|
|
252
|
+
if (!hasPermission) {
|
|
253
|
+
res.status(403).json({
|
|
254
|
+
error: "Forbidden",
|
|
255
|
+
message,
|
|
256
|
+
code: "PERMISSION_DENIED",
|
|
257
|
+
required: permission
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
next();
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function requireAnyPermission(permissions, permOptions = {}) {
|
|
265
|
+
const { message = "Insufficient permissions" } = permOptions;
|
|
266
|
+
return (req, res, next) => {
|
|
267
|
+
if (!req.auth) {
|
|
268
|
+
res.status(401).json({
|
|
269
|
+
error: "Unauthorized",
|
|
270
|
+
message: "Authentication required",
|
|
271
|
+
code: "NOT_AUTHENTICATED"
|
|
272
|
+
});
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const userPermissions = req.auth.claims.permissions || [];
|
|
276
|
+
const hasAny = permissions.some((p) => userPermissions.includes(p));
|
|
277
|
+
if (!hasAny) {
|
|
278
|
+
res.status(403).json({
|
|
279
|
+
error: "Forbidden",
|
|
280
|
+
message,
|
|
281
|
+
code: "PERMISSION_DENIED",
|
|
282
|
+
required: permissions
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
next();
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function requireAllPermissions(permissions, permOptions = {}) {
|
|
290
|
+
const { message = "Insufficient permissions" } = permOptions;
|
|
291
|
+
return (req, res, next) => {
|
|
292
|
+
if (!req.auth) {
|
|
293
|
+
res.status(401).json({
|
|
294
|
+
error: "Unauthorized",
|
|
295
|
+
message: "Authentication required",
|
|
296
|
+
code: "NOT_AUTHENTICATED"
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const userPermissions = req.auth.claims.permissions || [];
|
|
301
|
+
const hasAll = permissions.every((p) => userPermissions.includes(p));
|
|
302
|
+
if (!hasAll) {
|
|
303
|
+
const missing = permissions.filter((p) => !userPermissions.includes(p));
|
|
304
|
+
res.status(403).json({
|
|
305
|
+
error: "Forbidden",
|
|
306
|
+
message,
|
|
307
|
+
code: "PERMISSION_DENIED",
|
|
308
|
+
required: permissions,
|
|
309
|
+
missing
|
|
310
|
+
});
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
next();
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function requirePlatformOwner(permOptions = {}) {
|
|
317
|
+
const { message = "Platform owner access required" } = permOptions;
|
|
318
|
+
return (req, res, next) => {
|
|
319
|
+
if (!req.auth) {
|
|
320
|
+
res.status(401).json({
|
|
321
|
+
error: "Unauthorized",
|
|
322
|
+
message: "Authentication required",
|
|
323
|
+
code: "NOT_AUTHENTICATED"
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (!req.auth.claims.is_platform_owner) {
|
|
328
|
+
res.status(403).json({
|
|
329
|
+
error: "Forbidden",
|
|
330
|
+
message,
|
|
331
|
+
code: "NOT_PLATFORM_OWNER"
|
|
332
|
+
});
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
next();
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function requireOrganization(getOrgSlug, permOptions = {}) {
|
|
339
|
+
const { message = "Organization access required" } = permOptions;
|
|
340
|
+
return (req, res, next) => {
|
|
341
|
+
if (!req.auth) {
|
|
342
|
+
res.status(401).json({
|
|
343
|
+
error: "Unauthorized",
|
|
344
|
+
message: "Authentication required",
|
|
345
|
+
code: "NOT_AUTHENTICATED"
|
|
346
|
+
});
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const requiredOrg = typeof getOrgSlug === "function" ? getOrgSlug(req) : getOrgSlug;
|
|
350
|
+
const userOrg = req.auth.claims.org;
|
|
351
|
+
if (!userOrg || userOrg !== requiredOrg) {
|
|
352
|
+
res.status(403).json({
|
|
353
|
+
error: "Forbidden",
|
|
354
|
+
message,
|
|
355
|
+
code: "WRONG_ORGANIZATION",
|
|
356
|
+
required: requiredOrg
|
|
357
|
+
});
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
next();
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
requireAuth,
|
|
365
|
+
requirePermission,
|
|
366
|
+
requireAnyPermission,
|
|
367
|
+
requireAllPermissions,
|
|
368
|
+
requirePlatformOwner,
|
|
369
|
+
requireOrganization
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export { createAuthMiddleware };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { A as AuthOSNodeOptions, V as VerifyTokenOptions, a as VerifiedToken, W as WebhookVerifyOptions } from './types-C4aDSNcp.mjs';
|
|
2
|
+
export { c as AuthenticatedRequest, J as JWK, b as JWKS, R as RequireAuthOptions, d as RequirePermissionOptions } from './types-C4aDSNcp.mjs';
|
|
3
|
+
export { JwtClaims } from '@drmhse/sso-sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Error class for token verification failures
|
|
7
|
+
*/
|
|
8
|
+
declare class TokenVerificationError extends Error {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
constructor(message: string, code: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a token verifier instance
|
|
14
|
+
*/
|
|
15
|
+
declare function createTokenVerifier(options: AuthOSNodeOptions): {
|
|
16
|
+
verifyToken: (token: string, verifyOptions?: VerifyTokenOptions) => Promise<VerifiedToken>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Clear the JWKS cache (useful for testing)
|
|
20
|
+
*/
|
|
21
|
+
declare function clearJWKSCache(): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Error class for webhook verification failures
|
|
25
|
+
*/
|
|
26
|
+
declare class WebhookVerificationError extends Error {
|
|
27
|
+
readonly code: string;
|
|
28
|
+
constructor(message: string, code: string);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Verify a webhook signature from AuthOS
|
|
32
|
+
*
|
|
33
|
+
* @param signatureHeader - The signature header value (e.g., from 'X-AuthOS-Signature' or 'Webhook-Signature')
|
|
34
|
+
* @param payload - The raw request body as a string
|
|
35
|
+
* @param secret - The webhook signing secret
|
|
36
|
+
* @param options - Verification options
|
|
37
|
+
* @returns true if signature is valid
|
|
38
|
+
* @throws WebhookVerificationError if verification fails
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
|
|
43
|
+
* const signature = req.headers['x-authos-signature'] as string;
|
|
44
|
+
* const payload = req.body.toString();
|
|
45
|
+
*
|
|
46
|
+
* try {
|
|
47
|
+
* verifyWebhookSignature(signature, payload, process.env.WEBHOOK_SECRET!);
|
|
48
|
+
* // Process webhook...
|
|
49
|
+
* res.status(200).send('OK');
|
|
50
|
+
* } catch (err) {
|
|
51
|
+
* res.status(400).send('Invalid signature');
|
|
52
|
+
* }
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function verifyWebhookSignature(signatureHeader: string, payload: string, secret: string, options?: WebhookVerifyOptions): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Create a webhook signature for testing purposes
|
|
59
|
+
*
|
|
60
|
+
* @param payload - The payload to sign
|
|
61
|
+
* @param secret - The signing secret
|
|
62
|
+
* @param timestamp - Optional timestamp (defaults to current time)
|
|
63
|
+
* @returns The signature header value
|
|
64
|
+
*/
|
|
65
|
+
declare function createWebhookSignature(payload: string, secret: string, timestamp?: number): string;
|
|
66
|
+
|
|
67
|
+
export { AuthOSNodeOptions, TokenVerificationError, VerifiedToken, VerifyTokenOptions, WebhookVerificationError, WebhookVerifyOptions, clearJWKSCache, createTokenVerifier, createWebhookSignature, verifyWebhookSignature };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { A as AuthOSNodeOptions, V as VerifyTokenOptions, a as VerifiedToken, W as WebhookVerifyOptions } from './types-C4aDSNcp.js';
|
|
2
|
+
export { c as AuthenticatedRequest, J as JWK, b as JWKS, R as RequireAuthOptions, d as RequirePermissionOptions } from './types-C4aDSNcp.js';
|
|
3
|
+
export { JwtClaims } from '@drmhse/sso-sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Error class for token verification failures
|
|
7
|
+
*/
|
|
8
|
+
declare class TokenVerificationError extends Error {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
constructor(message: string, code: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a token verifier instance
|
|
14
|
+
*/
|
|
15
|
+
declare function createTokenVerifier(options: AuthOSNodeOptions): {
|
|
16
|
+
verifyToken: (token: string, verifyOptions?: VerifyTokenOptions) => Promise<VerifiedToken>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Clear the JWKS cache (useful for testing)
|
|
20
|
+
*/
|
|
21
|
+
declare function clearJWKSCache(): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Error class for webhook verification failures
|
|
25
|
+
*/
|
|
26
|
+
declare class WebhookVerificationError extends Error {
|
|
27
|
+
readonly code: string;
|
|
28
|
+
constructor(message: string, code: string);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Verify a webhook signature from AuthOS
|
|
32
|
+
*
|
|
33
|
+
* @param signatureHeader - The signature header value (e.g., from 'X-AuthOS-Signature' or 'Webhook-Signature')
|
|
34
|
+
* @param payload - The raw request body as a string
|
|
35
|
+
* @param secret - The webhook signing secret
|
|
36
|
+
* @param options - Verification options
|
|
37
|
+
* @returns true if signature is valid
|
|
38
|
+
* @throws WebhookVerificationError if verification fails
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
|
|
43
|
+
* const signature = req.headers['x-authos-signature'] as string;
|
|
44
|
+
* const payload = req.body.toString();
|
|
45
|
+
*
|
|
46
|
+
* try {
|
|
47
|
+
* verifyWebhookSignature(signature, payload, process.env.WEBHOOK_SECRET!);
|
|
48
|
+
* // Process webhook...
|
|
49
|
+
* res.status(200).send('OK');
|
|
50
|
+
* } catch (err) {
|
|
51
|
+
* res.status(400).send('Invalid signature');
|
|
52
|
+
* }
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function verifyWebhookSignature(signatureHeader: string, payload: string, secret: string, options?: WebhookVerifyOptions): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Create a webhook signature for testing purposes
|
|
59
|
+
*
|
|
60
|
+
* @param payload - The payload to sign
|
|
61
|
+
* @param secret - The signing secret
|
|
62
|
+
* @param timestamp - Optional timestamp (defaults to current time)
|
|
63
|
+
* @returns The signature header value
|
|
64
|
+
*/
|
|
65
|
+
declare function createWebhookSignature(payload: string, secret: string, timestamp?: number): string;
|
|
66
|
+
|
|
67
|
+
export { AuthOSNodeOptions, TokenVerificationError, VerifiedToken, VerifyTokenOptions, WebhookVerificationError, WebhookVerifyOptions, clearJWKSCache, createTokenVerifier, createWebhookSignature, verifyWebhookSignature };
|