@hawcx/oauth-client 0.1.0 → 4.0.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/README.md +475 -204
- package/dist/delegation/credentials.d.ts +92 -0
- package/dist/delegation/credentials.d.ts.map +1 -0
- package/dist/delegation/credentials.js +215 -0
- package/dist/delegation/credentials.js.map +1 -0
- package/dist/delegation/crypto.d.ts +2 -2
- package/dist/delegation/crypto.d.ts.map +1 -1
- package/dist/delegation/crypto.js +41 -32
- package/dist/delegation/crypto.js.map +1 -1
- package/dist/delegation/exceptions.d.ts +12 -5
- package/dist/delegation/exceptions.d.ts.map +1 -1
- package/dist/delegation/exceptions.js +12 -14
- package/dist/delegation/exceptions.js.map +1 -1
- package/dist/delegation/factory.d.ts +20 -0
- package/dist/delegation/factory.d.ts.map +1 -0
- package/dist/delegation/factory.js +49 -0
- package/dist/delegation/factory.js.map +1 -0
- package/dist/delegation/hawcx.d.ts +67 -224
- package/dist/delegation/hawcx.d.ts.map +1 -1
- package/dist/delegation/hawcx.js +116 -299
- package/dist/delegation/hawcx.js.map +1 -1
- package/dist/delegation/index.d.ts +4 -9
- package/dist/delegation/index.d.ts.map +1 -1
- package/dist/delegation/index.js +5 -17
- package/dist/delegation/index.js.map +1 -1
- package/dist/delegation/transport.d.ts +40 -0
- package/dist/delegation/transport.d.ts.map +1 -0
- package/dist/delegation/transport.js +120 -0
- package/dist/delegation/transport.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -27
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +98 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +150 -0
- package/dist/oauth.js.map +1 -0
- package/dist/stepup/client.d.ts +26 -0
- package/dist/stepup/client.d.ts.map +1 -0
- package/dist/stepup/client.js +84 -0
- package/dist/stepup/client.js.map +1 -0
- package/dist/stepup/index.d.ts +3 -0
- package/dist/stepup/index.d.ts.map +1 -0
- package/dist/stepup/index.js +19 -0
- package/dist/stepup/index.js.map +1 -0
- package/dist/stepup/types.d.ts +36 -0
- package/dist/stepup/types.d.ts.map +1 -0
- package/dist/stepup/types.js +3 -0
- package/dist/stepup/types.js.map +1 -0
- package/package.json +16 -17
- package/LICENSE +0 -22
- package/dist/client.d.ts +0 -134
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -301
- package/dist/client.js.map +0 -1
- package/dist/delegation/client.d.ts +0 -116
- package/dist/delegation/client.d.ts.map +0 -1
- package/dist/delegation/client.js +0 -227
- package/dist/delegation/client.js.map +0 -1
- package/dist/exceptions.d.ts +0 -52
- package/dist/exceptions.d.ts.map +0 -1
- package/dist/exceptions.js +0 -81
- package/dist/exceptions.js.map +0 -1
- package/dist/utils.d.ts +0 -61
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -263
- package/dist/utils.js.map +0 -1
package/dist/client.js
DELETED
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Core OAuth client implementation
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.exchangeCodeForClaims = exchangeCodeForClaims;
|
|
43
|
-
exports.exchangeCodeForTokenAndClaims = exchangeCodeForTokenAndClaims;
|
|
44
|
-
exports.verifyJwt = verifyJwt;
|
|
45
|
-
const axios_1 = __importDefault(require("axios"));
|
|
46
|
-
const jwt = __importStar(require("jsonwebtoken"));
|
|
47
|
-
const utils_1 = require("./utils");
|
|
48
|
-
const exceptions_1 = require("./exceptions");
|
|
49
|
-
/**
|
|
50
|
-
* Internal helper to perform the code-for-token exchange with optional PKCE support
|
|
51
|
-
*/
|
|
52
|
-
async function exchangeForToken(code, oauthTokenUrl, clientId, timeout = 20, codeVerifier, redirectUri, apiKey) {
|
|
53
|
-
try {
|
|
54
|
-
// Build token request payload
|
|
55
|
-
const payload = {
|
|
56
|
-
grant_type: 'authorization_code',
|
|
57
|
-
code,
|
|
58
|
-
client_id: clientId,
|
|
59
|
-
};
|
|
60
|
-
// Add PKCE code_verifier if provided (RFC 7636)
|
|
61
|
-
if (codeVerifier) {
|
|
62
|
-
payload.code_verifier = codeVerifier;
|
|
63
|
-
}
|
|
64
|
-
// Add redirect_uri if provided (OAuth 2.0 standard)
|
|
65
|
-
if (redirectUri) {
|
|
66
|
-
payload.redirect_uri = redirectUri;
|
|
67
|
-
}
|
|
68
|
-
const headers = {
|
|
69
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
70
|
-
Accept: 'application/json',
|
|
71
|
-
};
|
|
72
|
-
// Add API key header if provided (for OAuth providers that require it)
|
|
73
|
-
if (apiKey) {
|
|
74
|
-
headers['apikey'] = apiKey;
|
|
75
|
-
}
|
|
76
|
-
const response = await axios_1.default.post(oauthTokenUrl, payload, {
|
|
77
|
-
timeout: timeout * 1000,
|
|
78
|
-
headers,
|
|
79
|
-
});
|
|
80
|
-
return response.data;
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
if (axios_1.default.isAxiosError(error)) {
|
|
84
|
-
const axiosError = error;
|
|
85
|
-
if (axiosError.response) {
|
|
86
|
-
const responseBody = axiosError.response.data;
|
|
87
|
-
const errorMsg = responseBody?.error_description ||
|
|
88
|
-
responseBody?.error ||
|
|
89
|
-
'Unknown server error';
|
|
90
|
-
throw new exceptions_1.OAuthExchangeError(`Code exchange failed: ${errorMsg}`, axiosError.response.status, responseBody);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
throw new exceptions_1.OAuthExchangeError(`Network error while exchanging code: ${error}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Exchange OAuth authorization code for verified JWT claims.
|
|
98
|
-
*
|
|
99
|
-
* Supports PKCE (Proof Key for Code Exchange) per RFC 7636 for enhanced security.
|
|
100
|
-
*
|
|
101
|
-
* @param options - Configuration options for code exchange
|
|
102
|
-
* @returns Dictionary containing the verified JWT claims
|
|
103
|
-
* @throws OAuthExchangeError - Code exchange failed
|
|
104
|
-
* @throws JWTVerificationError - JWT verification failed
|
|
105
|
-
* @throws InvalidPublicKeyError - Public key invalid
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```typescript
|
|
109
|
-
* // Basic usage
|
|
110
|
-
* const claims = await exchangeCodeForClaims({
|
|
111
|
-
* code: req.body.code,
|
|
112
|
-
* oauthTokenUrl: 'https://oauth.example.com/token',
|
|
113
|
-
* clientId: 'my-app',
|
|
114
|
-
* publicKey: '/path/to/public.pem'
|
|
115
|
-
* });
|
|
116
|
-
*
|
|
117
|
-
* // With PKCE (recommended)
|
|
118
|
-
* const claims = await exchangeCodeForClaims({
|
|
119
|
-
* code: req.body.code,
|
|
120
|
-
* oauthTokenUrl: 'https://oauth.example.com/token',
|
|
121
|
-
* clientId: 'my-app',
|
|
122
|
-
* publicKey: process.env.OAUTH_PUBLIC_KEY!,
|
|
123
|
-
* codeVerifier: session.pkceVerifier,
|
|
124
|
-
* redirectUri: 'https://myapp.com/callback',
|
|
125
|
-
* audience: 'my-app',
|
|
126
|
-
* issuer: 'https://oauth.example.com'
|
|
127
|
-
* });
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
async function exchangeCodeForClaims(options) {
|
|
131
|
-
const { code, oauthTokenUrl, clientId, publicKey, jwksUrl, apiKey, codeVerifier, redirectUri, timeout = 20, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
|
|
132
|
-
// Input validation
|
|
133
|
-
if (!code || typeof code !== 'string') {
|
|
134
|
-
throw new exceptions_1.OAuthExchangeError('Authorization code must be a non-empty string');
|
|
135
|
-
}
|
|
136
|
-
if (!oauthTokenUrl || typeof oauthTokenUrl !== 'string') {
|
|
137
|
-
throw new exceptions_1.OAuthExchangeError('OAuth token URL must be a non-empty string');
|
|
138
|
-
}
|
|
139
|
-
if (!clientId || typeof clientId !== 'string') {
|
|
140
|
-
throw new exceptions_1.OAuthExchangeError('Client ID must be a non-empty string');
|
|
141
|
-
}
|
|
142
|
-
// Exchange code for id_token (with PKCE support)
|
|
143
|
-
const responseBody = await exchangeForToken(code, oauthTokenUrl, clientId, timeout, codeVerifier, redirectUri, apiKey);
|
|
144
|
-
const idToken = responseBody.id_token;
|
|
145
|
-
if (!idToken) {
|
|
146
|
-
throw new exceptions_1.OAuthExchangeError("OAuth server response missing 'id_token' field", undefined, responseBody);
|
|
147
|
-
}
|
|
148
|
-
// Verify JWT
|
|
149
|
-
const claims = await verifyJwt({
|
|
150
|
-
token: idToken,
|
|
151
|
-
publicKey,
|
|
152
|
-
jwksUrl,
|
|
153
|
-
audience,
|
|
154
|
-
issuer,
|
|
155
|
-
verifyExp,
|
|
156
|
-
leeway,
|
|
157
|
-
algorithms,
|
|
158
|
-
});
|
|
159
|
-
return claims;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Exchange OAuth authorization code for verified JWT claims and the raw id_token.
|
|
163
|
-
*
|
|
164
|
-
* @param options - Configuration options for code exchange
|
|
165
|
-
* @returns Tuple containing [claims, idToken]
|
|
166
|
-
* @throws OAuthExchangeError - Code exchange failed
|
|
167
|
-
* @throws JWTVerificationError - JWT verification failed
|
|
168
|
-
* @throws InvalidPublicKeyError - Public key invalid
|
|
169
|
-
*/
|
|
170
|
-
async function exchangeCodeForTokenAndClaims(options) {
|
|
171
|
-
const { code, oauthTokenUrl, clientId, publicKey, jwksUrl, apiKey, codeVerifier, redirectUri, timeout = 20, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
|
|
172
|
-
const responseBody = await exchangeForToken(code, oauthTokenUrl, clientId, timeout, codeVerifier, redirectUri, apiKey);
|
|
173
|
-
const idToken = responseBody.id_token;
|
|
174
|
-
if (!idToken) {
|
|
175
|
-
throw new exceptions_1.OAuthExchangeError("OAuth server response missing 'id_token' field", undefined, responseBody);
|
|
176
|
-
}
|
|
177
|
-
const claims = await verifyJwt({
|
|
178
|
-
token: idToken,
|
|
179
|
-
publicKey,
|
|
180
|
-
jwksUrl,
|
|
181
|
-
audience,
|
|
182
|
-
issuer,
|
|
183
|
-
verifyExp,
|
|
184
|
-
leeway,
|
|
185
|
-
algorithms,
|
|
186
|
-
});
|
|
187
|
-
return [claims, idToken];
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Verify a JWT and return its claims.
|
|
191
|
-
*
|
|
192
|
-
* This function verifies the JWT signature using the provided public key
|
|
193
|
-
* and validates claims (audience, issuer, expiration).
|
|
194
|
-
*
|
|
195
|
-
* @param options - Configuration options for JWT verification
|
|
196
|
-
* @returns Dictionary containing the verified JWT claims
|
|
197
|
-
* @throws JWTVerificationError - JWT verification failed
|
|
198
|
-
* @throws InvalidPublicKeyError - Public key invalid
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* // Basic usage
|
|
203
|
-
* const claims = verifyJwt({
|
|
204
|
-
* token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
|
|
205
|
-
* publicKey: 'keys/public.pem'
|
|
206
|
-
* });
|
|
207
|
-
* console.log(`User: ${claims.sub}`);
|
|
208
|
-
*
|
|
209
|
-
* // With validation
|
|
210
|
-
* const claims = verifyJwt({
|
|
211
|
-
* token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
|
|
212
|
-
* publicKey: process.env.OAUTH_PUBLIC_KEY!,
|
|
213
|
-
* audience: 'my-app',
|
|
214
|
-
* issuer: 'https://oauth.example.com',
|
|
215
|
-
* leeway: 10 // Allow 10 seconds clock skew
|
|
216
|
-
* });
|
|
217
|
-
* ```
|
|
218
|
-
*/
|
|
219
|
-
async function verifyJwt(options) {
|
|
220
|
-
const { token, publicKey, jwksUrl, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
|
|
221
|
-
// Input validation
|
|
222
|
-
if (!token || typeof token !== 'string') {
|
|
223
|
-
throw new exceptions_1.JWTVerificationError('Token must be a non-empty string');
|
|
224
|
-
}
|
|
225
|
-
if (!publicKey && !jwksUrl) {
|
|
226
|
-
throw new exceptions_1.JWTVerificationError("Must provide either 'publicKey' or 'jwksUrl'");
|
|
227
|
-
}
|
|
228
|
-
// Load and validate public key
|
|
229
|
-
let pemKey;
|
|
230
|
-
try {
|
|
231
|
-
if (jwksUrl) {
|
|
232
|
-
// Use JWKS URL for dynamic key fetching
|
|
233
|
-
// First decode JWT header to get kid
|
|
234
|
-
const header = jwt.decode(token, { complete: true })?.header;
|
|
235
|
-
if (!header) {
|
|
236
|
-
throw new exceptions_1.JWTVerificationError('Failed to decode JWT header');
|
|
237
|
-
}
|
|
238
|
-
const kid = header.kid;
|
|
239
|
-
// Fetch JWKS (uses cache)
|
|
240
|
-
const jwks = await (0, utils_1.fetchJwks)(jwksUrl);
|
|
241
|
-
// Extract key from JWKS
|
|
242
|
-
pemKey = (0, utils_1.getKeyFromJwks)(jwks, kid);
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// Use static public key
|
|
246
|
-
pemKey = (0, utils_1.loadPublicKey)(publicKey);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
catch (error) {
|
|
250
|
-
if (error instanceof exceptions_1.InvalidPublicKeyError) {
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
throw new exceptions_1.InvalidPublicKeyError(`Unexpected error loading public key: ${error}`);
|
|
254
|
-
}
|
|
255
|
-
// Build verification options
|
|
256
|
-
const verifyOptions = {
|
|
257
|
-
algorithms: algorithms || ['RS256', 'ES256', 'ES384', 'ES512', 'EdDSA'],
|
|
258
|
-
clockTolerance: leeway,
|
|
259
|
-
ignoreExpiration: !verifyExp,
|
|
260
|
-
};
|
|
261
|
-
if (audience) {
|
|
262
|
-
verifyOptions.audience = audience;
|
|
263
|
-
}
|
|
264
|
-
if (issuer) {
|
|
265
|
-
verifyOptions.issuer = issuer;
|
|
266
|
-
}
|
|
267
|
-
// Decode and verify
|
|
268
|
-
try {
|
|
269
|
-
const claims = jwt.verify(token, pemKey, verifyOptions);
|
|
270
|
-
// jwt.verify can return string or object, ensure we have an object
|
|
271
|
-
if (typeof claims === 'string') {
|
|
272
|
-
throw new exceptions_1.JWTVerificationError('Unexpected JWT format: claims is a string');
|
|
273
|
-
}
|
|
274
|
-
return claims;
|
|
275
|
-
}
|
|
276
|
-
catch (error) {
|
|
277
|
-
if (error instanceof jwt.TokenExpiredError) {
|
|
278
|
-
throw new exceptions_1.JWTVerificationError('Token has expired. Please re-authenticate.', error);
|
|
279
|
-
}
|
|
280
|
-
if (error instanceof jwt.JsonWebTokenError) {
|
|
281
|
-
if (error.message.includes('audience')) {
|
|
282
|
-
throw new exceptions_1.JWTVerificationError(`Token audience validation failed. Expected: ${audience}`, error);
|
|
283
|
-
}
|
|
284
|
-
if (error.message.includes('issuer')) {
|
|
285
|
-
throw new exceptions_1.JWTVerificationError(`Token issuer validation failed. Expected: ${issuer}`, error);
|
|
286
|
-
}
|
|
287
|
-
if (error.message.includes('signature')) {
|
|
288
|
-
throw new exceptions_1.JWTVerificationError('Token signature verification failed. Token may have been tampered with.', error);
|
|
289
|
-
}
|
|
290
|
-
if (error.message.includes('jwt malformed')) {
|
|
291
|
-
throw new exceptions_1.JWTVerificationError('Token has invalid structure or encoding', error);
|
|
292
|
-
}
|
|
293
|
-
throw new exceptions_1.JWTVerificationError(`Token validation failed: ${error.message}`, error);
|
|
294
|
-
}
|
|
295
|
-
if (error instanceof jwt.NotBeforeError) {
|
|
296
|
-
throw new exceptions_1.JWTVerificationError('Token not yet valid (nbf claim). Check server clock synchronization.', error);
|
|
297
|
-
}
|
|
298
|
-
throw new exceptions_1.JWTVerificationError(`Unexpected error during JWT verification: ${error}`, error);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client for sending secure, ECIES-encrypted and signed delegation requests to an IDP
|
|
3
|
-
*/
|
|
4
|
-
import { Verifier, EciesX25519Encryptor, EciesX25519Decryptor, Ed25519Signer, RsaPssSigner } from './crypto';
|
|
5
|
-
export type Signer = Ed25519Signer | RsaPssSigner;
|
|
6
|
-
/**
|
|
7
|
-
* Options for sending secure delegation requests
|
|
8
|
-
*/
|
|
9
|
-
export interface SecureRequestOptions {
|
|
10
|
-
/** API endpoint path (e.g., "/mfa/update" or "/device/revoke") */
|
|
11
|
-
endpoint: string;
|
|
12
|
-
/** Request payload dictionary to be encrypted and sent */
|
|
13
|
-
payload: Record<string, any>;
|
|
14
|
-
/** If true, prepends base_url to endpoint (default: true) */
|
|
15
|
-
includeBaseUrl?: boolean;
|
|
16
|
-
/** Optional additional HTTP headers (e.g., API keys) */
|
|
17
|
-
extraHeaders?: Record<string, string>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Client for sending secure, ECIES-encrypted and signed delegation requests to an IDP.
|
|
21
|
-
*/
|
|
22
|
-
export declare class IdpDelegationClient {
|
|
23
|
-
private baseUrl;
|
|
24
|
-
private signer;
|
|
25
|
-
private verifier;
|
|
26
|
-
private encryptor;
|
|
27
|
-
private decryptor;
|
|
28
|
-
private spId;
|
|
29
|
-
private timeout;
|
|
30
|
-
constructor(options: {
|
|
31
|
-
baseUrl: string;
|
|
32
|
-
signer: Signer;
|
|
33
|
-
verifier: Verifier;
|
|
34
|
-
encryptor: EciesX25519Encryptor;
|
|
35
|
-
decryptor: EciesX25519Decryptor;
|
|
36
|
-
spId: string;
|
|
37
|
-
timeout?: number;
|
|
38
|
-
});
|
|
39
|
-
/**
|
|
40
|
-
* Send an encrypted and signed delegation request to the IDP.
|
|
41
|
-
*
|
|
42
|
-
* This method automatically handles all cryptographic operations:
|
|
43
|
-
* - ECIES (X25519 + AES-GCM) encryption of the request payload
|
|
44
|
-
* - Ed25519/RSA-PSS detached signature generation
|
|
45
|
-
* - HTTP header construction with delegation metadata
|
|
46
|
-
* - Response signature verification
|
|
47
|
-
* - ECIES decryption of the response
|
|
48
|
-
*
|
|
49
|
-
* @param options - Request configuration options
|
|
50
|
-
* @returns Decrypted and verified response dictionary from the IDP
|
|
51
|
-
* @throws DelegationRequestError - If request preparation or sending fails
|
|
52
|
-
* @throws DelegationResponseError - If response verification or decryption fails
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```typescript
|
|
56
|
-
* // Initialize client
|
|
57
|
-
* const client = new IdpDelegationClient({
|
|
58
|
-
* baseUrl: "https://idp.example.com",
|
|
59
|
-
* signer, verifier,
|
|
60
|
-
* encryptor, decryptor,
|
|
61
|
-
* spId: "my-sp"
|
|
62
|
-
* });
|
|
63
|
-
*
|
|
64
|
-
* // Send secure request with automatic crypto
|
|
65
|
-
* const response = await client.sendSecureRequest({
|
|
66
|
-
* endpoint: "/mfa/update",
|
|
67
|
-
* payload: {
|
|
68
|
-
* userid: "user@example.com",
|
|
69
|
-
* mfa_method: "sms",
|
|
70
|
-
* contact: "+15551234567"
|
|
71
|
-
* }
|
|
72
|
-
* });
|
|
73
|
-
* console.log(response); // { success: true, session_id: '...' }
|
|
74
|
-
* ```
|
|
75
|
-
*
|
|
76
|
-
* Security Notes:
|
|
77
|
-
* - All requests are encrypted with ECIES (X25519 + AES-GCM)
|
|
78
|
-
* - All requests include a detached signature (Ed25519 or RSA-PSS)
|
|
79
|
-
* - All responses are verified and decrypted automatically
|
|
80
|
-
* - Timestamps are included to prevent replay attacks
|
|
81
|
-
*/
|
|
82
|
-
sendSecureRequest(options: SecureRequestOptions): Promise<Record<string, any>>;
|
|
83
|
-
/**
|
|
84
|
-
* Request an MFA method update for a user.
|
|
85
|
-
*
|
|
86
|
-
* @param options - MFA update configuration
|
|
87
|
-
* @returns The decrypted acknowledgment response from the IDP
|
|
88
|
-
*/
|
|
89
|
-
mfaUpdate(options: {
|
|
90
|
-
userId: string;
|
|
91
|
-
method: string;
|
|
92
|
-
enabled: boolean;
|
|
93
|
-
reason: string;
|
|
94
|
-
requestedBy?: string;
|
|
95
|
-
}): Promise<Record<string, any>>;
|
|
96
|
-
/**
|
|
97
|
-
* Request the current MFA status for a user.
|
|
98
|
-
*
|
|
99
|
-
* @param userId - The ID of the user to query
|
|
100
|
-
* @returns The decrypted acknowledgment response from the IDP containing the MFA status
|
|
101
|
-
*/
|
|
102
|
-
mfaGetStatus(userId: string): Promise<Record<string, any>>;
|
|
103
|
-
/**
|
|
104
|
-
* Request to revoke a user's device.
|
|
105
|
-
*
|
|
106
|
-
* @param options - Device revocation configuration
|
|
107
|
-
* @returns The decrypted acknowledgment response from the IDP
|
|
108
|
-
*/
|
|
109
|
-
deviceRevoke(options: {
|
|
110
|
-
userId: string;
|
|
111
|
-
deviceId: string;
|
|
112
|
-
reason: string;
|
|
113
|
-
requestedBy?: string;
|
|
114
|
-
}): Promise<Record<string, any>>;
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/delegation/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAEL,QAAQ,EACR,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,YAAY,EACb,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,MAAM,GAAG,aAAa,GAAG,YAAY,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,QAAQ,CAAC;QACnB,SAAS,EAAE,oBAAoB,CAAC;QAChC,SAAS,EAAE,oBAAoB,CAAC;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;IAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACG,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAyGpF;;;;;OAKG;IACG,SAAS,CAAC,OAAO,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAqBhC;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAmBhE;;;;;OAKG;IACG,YAAY,CAAC,OAAO,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAoBjC"}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Client for sending secure, ECIES-encrypted and signed delegation requests to an IDP
|
|
4
|
-
*/
|
|
5
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
-
};
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.IdpDelegationClient = void 0;
|
|
10
|
-
const axios_1 = __importDefault(require("axios"));
|
|
11
|
-
const uuid_1 = require("uuid");
|
|
12
|
-
const crypto_1 = require("./crypto");
|
|
13
|
-
const exceptions_1 = require("./exceptions");
|
|
14
|
-
/**
|
|
15
|
-
* Client for sending secure, ECIES-encrypted and signed delegation requests to an IDP.
|
|
16
|
-
*/
|
|
17
|
-
class IdpDelegationClient {
|
|
18
|
-
constructor(options) {
|
|
19
|
-
this.baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
20
|
-
this.signer = options.signer;
|
|
21
|
-
this.verifier = options.verifier;
|
|
22
|
-
this.encryptor = options.encryptor;
|
|
23
|
-
this.decryptor = options.decryptor;
|
|
24
|
-
this.spId = options.spId;
|
|
25
|
-
this.timeout = options.timeout || 15;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Send an encrypted and signed delegation request to the IDP.
|
|
29
|
-
*
|
|
30
|
-
* This method automatically handles all cryptographic operations:
|
|
31
|
-
* - ECIES (X25519 + AES-GCM) encryption of the request payload
|
|
32
|
-
* - Ed25519/RSA-PSS detached signature generation
|
|
33
|
-
* - HTTP header construction with delegation metadata
|
|
34
|
-
* - Response signature verification
|
|
35
|
-
* - ECIES decryption of the response
|
|
36
|
-
*
|
|
37
|
-
* @param options - Request configuration options
|
|
38
|
-
* @returns Decrypted and verified response dictionary from the IDP
|
|
39
|
-
* @throws DelegationRequestError - If request preparation or sending fails
|
|
40
|
-
* @throws DelegationResponseError - If response verification or decryption fails
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* // Initialize client
|
|
45
|
-
* const client = new IdpDelegationClient({
|
|
46
|
-
* baseUrl: "https://idp.example.com",
|
|
47
|
-
* signer, verifier,
|
|
48
|
-
* encryptor, decryptor,
|
|
49
|
-
* spId: "my-sp"
|
|
50
|
-
* });
|
|
51
|
-
*
|
|
52
|
-
* // Send secure request with automatic crypto
|
|
53
|
-
* const response = await client.sendSecureRequest({
|
|
54
|
-
* endpoint: "/mfa/update",
|
|
55
|
-
* payload: {
|
|
56
|
-
* userid: "user@example.com",
|
|
57
|
-
* mfa_method: "sms",
|
|
58
|
-
* contact: "+15551234567"
|
|
59
|
-
* }
|
|
60
|
-
* });
|
|
61
|
-
* console.log(response); // { success: true, session_id: '...' }
|
|
62
|
-
* ```
|
|
63
|
-
*
|
|
64
|
-
* Security Notes:
|
|
65
|
-
* - All requests are encrypted with ECIES (X25519 + AES-GCM)
|
|
66
|
-
* - All requests include a detached signature (Ed25519 or RSA-PSS)
|
|
67
|
-
* - All responses are verified and decrypted automatically
|
|
68
|
-
* - Timestamps are included to prevent replay attacks
|
|
69
|
-
*/
|
|
70
|
-
async sendSecureRequest(options) {
|
|
71
|
-
const { endpoint, payload, includeBaseUrl = true, extraHeaders = {} } = options;
|
|
72
|
-
let encryptedEnv;
|
|
73
|
-
let headers;
|
|
74
|
-
try {
|
|
75
|
-
// Step 1: Serialize and encrypt the payload
|
|
76
|
-
const body = Buffer.from(JSON.stringify(payload));
|
|
77
|
-
encryptedEnv = this.encryptor.encrypt(body);
|
|
78
|
-
// Step 2: Generate timestamp and signature
|
|
79
|
-
const ts = (0, crypto_1.nowS)();
|
|
80
|
-
const sig = this.signer.signDetached(encryptedEnv, ts);
|
|
81
|
-
// Step 3: Build delegation headers
|
|
82
|
-
headers = {
|
|
83
|
-
'Content-Type': 'application/json',
|
|
84
|
-
'X-Enc-Alg': 'x25519-aesgcm',
|
|
85
|
-
'X-SP-Id': this.spId,
|
|
86
|
-
'X-Timestamp': String(ts),
|
|
87
|
-
'X-Signature-Alg': sig.alg,
|
|
88
|
-
'X-Signature': sig.signatureB64,
|
|
89
|
-
};
|
|
90
|
-
if (sig.kid) {
|
|
91
|
-
headers['X-Key-Id'] = sig.kid;
|
|
92
|
-
}
|
|
93
|
-
// Merge extra headers (e.g., API authentication headers)
|
|
94
|
-
Object.assign(headers, extraHeaders);
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
throw new exceptions_1.DelegationRequestError(`Failed to prepare secure request: ${error}`);
|
|
98
|
-
}
|
|
99
|
-
// Step 4: Send encrypted request to IDP
|
|
100
|
-
let response;
|
|
101
|
-
try {
|
|
102
|
-
const url = includeBaseUrl ? this.baseUrl + endpoint : endpoint;
|
|
103
|
-
response = await axios_1.default.post(url, encryptedEnv, {
|
|
104
|
-
headers,
|
|
105
|
-
timeout: this.timeout * 1000,
|
|
106
|
-
validateStatus: () => true, // Don't throw on any status
|
|
107
|
-
responseType: 'arraybuffer',
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
if (axios_1.default.isAxiosError(error)) {
|
|
112
|
-
throw new exceptions_1.DelegationRequestError(`Request to IDP failed: ${error.message}`);
|
|
113
|
-
}
|
|
114
|
-
throw new exceptions_1.DelegationRequestError(`Request to IDP failed: ${error}`);
|
|
115
|
-
}
|
|
116
|
-
// Step 5: Verify and decrypt response (even for error statuses)
|
|
117
|
-
try {
|
|
118
|
-
const respTs = parseInt(response.headers['x-timestamp'] || String((0, crypto_1.nowS)()));
|
|
119
|
-
const respSig = response.headers['x-signature'];
|
|
120
|
-
const respAlg = response.headers['x-signature-alg'];
|
|
121
|
-
const respKid = response.headers['x-key-id'];
|
|
122
|
-
if (!respSig || !respAlg) {
|
|
123
|
-
throw new exceptions_1.DelegationResponseError('Missing signature headers in IDP response');
|
|
124
|
-
}
|
|
125
|
-
this.verifier.verify(Buffer.from(response.data), respTs, respSig, respAlg, respKid);
|
|
126
|
-
// Step 6: Verify encryption and decrypt response
|
|
127
|
-
if (response.headers['x-enc-alg'] !== 'x25519-aesgcm') {
|
|
128
|
-
throw new exceptions_1.DelegationResponseError('IDP response must be ECIES encrypted');
|
|
129
|
-
}
|
|
130
|
-
const plaintext = this.decryptor.decrypt(Buffer.from(response.data));
|
|
131
|
-
const decryptedData = JSON.parse(plaintext.toString('utf-8'));
|
|
132
|
-
// Now check HTTP status and include decrypted error message if available
|
|
133
|
-
if (response.status >= 400) {
|
|
134
|
-
const errorDetail = decryptedData.detail || JSON.stringify(decryptedData);
|
|
135
|
-
throw new exceptions_1.DelegationRequestError(`IDP returned ${response.status}: ${errorDetail}`, response.status, errorDetail);
|
|
136
|
-
}
|
|
137
|
-
return decryptedData;
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
if (error instanceof exceptions_1.DelegationRequestError) {
|
|
141
|
-
throw error;
|
|
142
|
-
}
|
|
143
|
-
if (error instanceof exceptions_1.DelegationResponseError) {
|
|
144
|
-
throw error;
|
|
145
|
-
}
|
|
146
|
-
// If we can't decrypt, fall back to raw response
|
|
147
|
-
if (response.status >= 400) {
|
|
148
|
-
const responseText = Buffer.from(response.data).toString('utf-8').substring(0, 500);
|
|
149
|
-
throw new exceptions_1.DelegationRequestError(`IDP returned ${response.status}: ${responseText}`, response.status);
|
|
150
|
-
}
|
|
151
|
-
throw new exceptions_1.DelegationResponseError(`Failed to process secure response: ${error}`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Request an MFA method update for a user.
|
|
156
|
-
*
|
|
157
|
-
* @param options - MFA update configuration
|
|
158
|
-
* @returns The decrypted acknowledgment response from the IDP
|
|
159
|
-
*/
|
|
160
|
-
async mfaUpdate(options) {
|
|
161
|
-
const { userId, method, enabled, reason, requestedBy } = options;
|
|
162
|
-
const payload = {
|
|
163
|
-
v: '1',
|
|
164
|
-
type: 'delegation.request',
|
|
165
|
-
action: 'mfa.update',
|
|
166
|
-
sp: { id: this.spId, kid: this.signer.kid },
|
|
167
|
-
subject: { user_id: userId },
|
|
168
|
-
params: { method, enabled: Boolean(enabled) },
|
|
169
|
-
audit: { reason, requested_by: requestedBy || userId },
|
|
170
|
-
jti: (0, uuid_1.v4)().replace(/-/g, ''),
|
|
171
|
-
iat: (0, crypto_1.nowS)(),
|
|
172
|
-
};
|
|
173
|
-
return this.sendSecureRequest({
|
|
174
|
-
endpoint: '/mfa/update',
|
|
175
|
-
payload,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Request the current MFA status for a user.
|
|
180
|
-
*
|
|
181
|
-
* @param userId - The ID of the user to query
|
|
182
|
-
* @returns The decrypted acknowledgment response from the IDP containing the MFA status
|
|
183
|
-
*/
|
|
184
|
-
async mfaGetStatus(userId) {
|
|
185
|
-
const payload = {
|
|
186
|
-
v: '1',
|
|
187
|
-
type: 'delegation.request',
|
|
188
|
-
action: 'mfa.get_status',
|
|
189
|
-
sp: { id: this.spId, kid: this.signer.kid },
|
|
190
|
-
subject: { user_id: userId },
|
|
191
|
-
params: {},
|
|
192
|
-
audit: { reason: 'User status query', requested_by: userId },
|
|
193
|
-
jti: (0, uuid_1.v4)().replace(/-/g, ''),
|
|
194
|
-
iat: (0, crypto_1.nowS)(),
|
|
195
|
-
};
|
|
196
|
-
return this.sendSecureRequest({
|
|
197
|
-
endpoint: '/mfa/get',
|
|
198
|
-
payload,
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Request to revoke a user's device.
|
|
203
|
-
*
|
|
204
|
-
* @param options - Device revocation configuration
|
|
205
|
-
* @returns The decrypted acknowledgment response from the IDP
|
|
206
|
-
*/
|
|
207
|
-
async deviceRevoke(options) {
|
|
208
|
-
const { userId, deviceId, reason, requestedBy } = options;
|
|
209
|
-
const payload = {
|
|
210
|
-
v: '1',
|
|
211
|
-
type: 'delegation.request',
|
|
212
|
-
action: 'device.revoke',
|
|
213
|
-
sp: { id: this.spId, kid: this.signer.kid },
|
|
214
|
-
subject: { user_id: userId, device_id: deviceId },
|
|
215
|
-
params: {},
|
|
216
|
-
audit: { reason, requested_by: requestedBy || userId },
|
|
217
|
-
jti: (0, uuid_1.v4)().replace(/-/g, ''),
|
|
218
|
-
iat: (0, crypto_1.nowS)(),
|
|
219
|
-
};
|
|
220
|
-
return this.sendSecureRequest({
|
|
221
|
-
endpoint: '/device/revoke',
|
|
222
|
-
payload,
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
exports.IdpDelegationClient = IdpDelegationClient;
|
|
227
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/delegation/client.ts"],"names":[],"mappings":"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"}
|