@hawcx/oauth-client 0.2.0 → 5.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.
Files changed (74) hide show
  1. package/README.md +587 -204
  2. package/dist/client-assertion.d.ts +45 -0
  3. package/dist/client-assertion.d.ts.map +1 -0
  4. package/dist/client-assertion.js +141 -0
  5. package/dist/client-assertion.js.map +1 -0
  6. package/dist/delegation/credentials.d.ts +92 -0
  7. package/dist/delegation/credentials.d.ts.map +1 -0
  8. package/dist/delegation/credentials.js +215 -0
  9. package/dist/delegation/credentials.js.map +1 -0
  10. package/dist/delegation/crypto.d.ts +2 -2
  11. package/dist/delegation/crypto.d.ts.map +1 -1
  12. package/dist/delegation/crypto.js +41 -32
  13. package/dist/delegation/crypto.js.map +1 -1
  14. package/dist/delegation/exceptions.d.ts +12 -5
  15. package/dist/delegation/exceptions.d.ts.map +1 -1
  16. package/dist/delegation/exceptions.js +12 -14
  17. package/dist/delegation/exceptions.js.map +1 -1
  18. package/dist/delegation/factory.d.ts +20 -0
  19. package/dist/delegation/factory.d.ts.map +1 -0
  20. package/dist/delegation/factory.js +49 -0
  21. package/dist/delegation/factory.js.map +1 -0
  22. package/dist/delegation/hawcx.d.ts +59 -224
  23. package/dist/delegation/hawcx.d.ts.map +1 -1
  24. package/dist/delegation/hawcx.js +99 -299
  25. package/dist/delegation/hawcx.js.map +1 -1
  26. package/dist/delegation/index.d.ts +4 -9
  27. package/dist/delegation/index.d.ts.map +1 -1
  28. package/dist/delegation/index.js +5 -17
  29. package/dist/delegation/index.js.map +1 -1
  30. package/dist/delegation/transport.d.ts +40 -0
  31. package/dist/delegation/transport.d.ts.map +1 -0
  32. package/dist/delegation/transport.js +120 -0
  33. package/dist/delegation/transport.js.map +1 -0
  34. package/dist/errors.d.ts +62 -0
  35. package/dist/errors.d.ts.map +1 -0
  36. package/dist/errors.js +73 -0
  37. package/dist/errors.js.map +1 -0
  38. package/dist/index.d.ts +12 -15
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +20 -27
  41. package/dist/index.js.map +1 -1
  42. package/dist/oauth.d.ts +265 -0
  43. package/dist/oauth.d.ts.map +1 -0
  44. package/dist/oauth.js +497 -0
  45. package/dist/oauth.js.map +1 -0
  46. package/dist/stepup/client.d.ts +26 -0
  47. package/dist/stepup/client.d.ts.map +1 -0
  48. package/dist/stepup/client.js +78 -0
  49. package/dist/stepup/client.js.map +1 -0
  50. package/dist/stepup/index.d.ts +3 -0
  51. package/dist/stepup/index.d.ts.map +1 -0
  52. package/dist/stepup/index.js +19 -0
  53. package/dist/stepup/index.js.map +1 -0
  54. package/dist/stepup/types.d.ts +35 -0
  55. package/dist/stepup/types.d.ts.map +1 -0
  56. package/dist/stepup/types.js +3 -0
  57. package/dist/stepup/types.js.map +1 -0
  58. package/package.json +13 -16
  59. package/dist/client.d.ts +0 -134
  60. package/dist/client.d.ts.map +0 -1
  61. package/dist/client.js +0 -300
  62. package/dist/client.js.map +0 -1
  63. package/dist/delegation/client.d.ts +0 -116
  64. package/dist/delegation/client.d.ts.map +0 -1
  65. package/dist/delegation/client.js +0 -227
  66. package/dist/delegation/client.js.map +0 -1
  67. package/dist/exceptions.d.ts +0 -52
  68. package/dist/exceptions.d.ts.map +0 -1
  69. package/dist/exceptions.js +0 -81
  70. package/dist/exceptions.js.map +0 -1
  71. package/dist/utils.d.ts +0 -61
  72. package/dist/utils.d.ts.map +0 -1
  73. package/dist/utils.js +0 -263
  74. package/dist/utils.js.map +0 -1
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stepup/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,0CAAwB"}
@@ -0,0 +1,35 @@
1
+ export type StepUpPurpose = 'change_mfa_method';
2
+ export type HxAuthMfaMethod = 'sms_otp' | 'email_otp' | 'totp';
3
+ export interface StepUpStartTokenResponse {
4
+ start_token: string;
5
+ expires_in: number;
6
+ }
7
+ export interface StepUpConsumeResponse {
8
+ ok: boolean;
9
+ }
10
+ export interface StepUpStartOptions {
11
+ userId: string;
12
+ purpose: StepUpPurpose;
13
+ newMfaMethod: HxAuthMfaMethod;
14
+ }
15
+ export interface StepUpConsumeOptions {
16
+ receipt: string;
17
+ }
18
+ export interface StepUpClientBaseOptions {
19
+ /** Base URL to hx_auth, e.g. http://localhost:8000 */
20
+ baseUrl: string;
21
+ /** API version prefix (default: /v1) */
22
+ apiPrefix?: string;
23
+ /** Required by hx_auth for tenant routing in most deployments (forwarded via headers). */
24
+ tenantHeaderName?: string;
25
+ tenantHeaderValue?: string;
26
+ /** Required by hx_auth relying party validation. */
27
+ relyingParty?: string;
28
+ /** Optional additional headers (e.g., apikey) */
29
+ extraHeaders?: Record<string, string>;
30
+ /** Request timeout in seconds (default: 15) */
31
+ timeoutSeconds?: number;
32
+ /** Allowed response timestamp skew in seconds (default: 300) */
33
+ clockSkewSeconds?: number;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/stepup/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;AAE/D,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stepup/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,40 +1,38 @@
1
1
  {
2
2
  "name": "@hawcx/oauth-client",
3
- "version": "0.2.0",
4
- "description": "Lightweight OAuth client for exchanging authorization codes and verifying JWT claims with Hawcx delegation support",
3
+ "version": "5.1.0",
4
+ "description": "Simple OAuth client for Hawcx authentication with delegation support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
9
  "test": "jest",
10
- "test:coverage": "jest --coverage",
11
- "lint": "eslint 'src/**/*.ts'",
12
- "format": "prettier --write 'src/**/*.ts'",
10
+ "lint": "eslint \"src/**/*.ts\"",
11
+ "format": "prettier --write \"src/**/*.ts\"",
13
12
  "prepublishOnly": "npm run build"
14
13
  },
15
14
  "keywords": [
16
15
  "oauth",
17
16
  "jwt",
18
17
  "authentication",
19
- "oauth2",
20
- "verification",
21
18
  "hawcx",
19
+ "pkce",
22
20
  "mfa",
23
- "delegation",
24
- "pkce"
21
+ "delegation"
25
22
  ],
26
23
  "author": "Hawcx Team",
27
24
  "license": "MIT",
28
25
  "dependencies": {
29
- "jsonwebtoken": "^9.0.2",
30
- "axios": "^1.6.0",
31
- "uuid": "^9.0.0"
26
+ "jose": "^5.10.0"
27
+ },
28
+ "overrides": {
29
+ "@typescript-eslint/typescript-estree": {
30
+ "minimatch": ">=9.0.7"
31
+ }
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/jest": "^29.5.0",
35
- "@types/jsonwebtoken": "^9.0.5",
36
35
  "@types/node": "^20.10.0",
37
- "@types/uuid": "^9.0.0",
38
36
  "@typescript-eslint/eslint-plugin": "^6.0.0",
39
37
  "@typescript-eslint/parser": "^6.0.0",
40
38
  "eslint": "^8.50.0",
@@ -44,7 +42,7 @@
44
42
  "typescript": "^5.3.0"
45
43
  },
46
44
  "engines": {
47
- "node": ">=16.0.0"
45
+ "node": ">=18.0.0"
48
46
  },
49
47
  "files": [
50
48
  "dist",
@@ -52,4 +50,3 @@
52
50
  "LICENSE"
53
51
  ]
54
52
  }
55
-
package/dist/client.d.ts DELETED
@@ -1,134 +0,0 @@
1
- /**
2
- * Core OAuth client implementation
3
- */
4
- /**
5
- * Options for exchanging authorization code for claims
6
- */
7
- export interface ExchangeCodeOptions {
8
- /** Authorization code from OAuth flow */
9
- code: string;
10
- /** Token endpoint URL */
11
- oauthTokenUrl: string;
12
- /** OAuth client identifier */
13
- clientId: string;
14
- /** Ed25519 public key (PEM string or file path) - optional if jwksUrl provided */
15
- publicKey?: string;
16
- /** JWKS URL for dynamic key fetching (alternative to publicKey) */
17
- jwksUrl?: string;
18
- /** API key for OAuth provider (required for Hawcx) */
19
- apiKey: string;
20
- /** PKCE code verifier (optional, recommended for security) */
21
- codeVerifier?: string;
22
- /** OAuth redirect URI (optional, required by some providers) */
23
- redirectUri?: string;
24
- /** Request timeout in seconds (default: 20) */
25
- timeout?: number;
26
- /** Expected 'aud' claim (optional but recommended) */
27
- audience?: string;
28
- /** Expected 'iss' claim (optional but recommended) */
29
- issuer?: string;
30
- /** Verify token expiration (default: true) */
31
- verifyExp?: boolean;
32
- /** Clock skew tolerance in seconds (default: 0) */
33
- leeway?: number;
34
- /** List of allowed signing algorithms (default: RS256, ES256/384/512, EdDSA) */
35
- algorithms?: string[];
36
- }
37
- /**
38
- * Options for verifying JWT tokens
39
- */
40
- export interface VerifyJwtOptions {
41
- /** JWT token to verify */
42
- token: string;
43
- /** Public key for JWT verification (PEM string or file path) - optional if jwksUrl provided */
44
- publicKey?: string;
45
- /** JWKS URL for dynamic key fetching (alternative to publicKey) */
46
- jwksUrl?: string;
47
- /** Expected 'aud' claim (optional but recommended) */
48
- audience?: string;
49
- /** Expected 'iss' claim (optional but recommended) */
50
- issuer?: string;
51
- /** Verify token expiration (default: true) */
52
- verifyExp?: boolean;
53
- /** Clock skew tolerance in seconds (default: 0) */
54
- leeway?: number;
55
- /** List of allowed signing algorithms (default: RS256, ES256/384/512, EdDSA) */
56
- algorithms?: string[];
57
- }
58
- /**
59
- * Exchange OAuth authorization code for verified JWT claims.
60
- *
61
- * Supports PKCE (Proof Key for Code Exchange) per RFC 7636 for enhanced security.
62
- *
63
- * @param options - Configuration options for code exchange
64
- * @returns Dictionary containing the verified JWT claims
65
- * @throws OAuthExchangeError - Code exchange failed
66
- * @throws JWTVerificationError - JWT verification failed
67
- * @throws InvalidPublicKeyError - Public key invalid
68
- *
69
- * @example
70
- * ```typescript
71
- * // Basic usage
72
- * const claims = await exchangeCodeForClaims({
73
- * code: req.body.code,
74
- * oauthTokenUrl: 'https://oauth.example.com/token',
75
- * clientId: 'my-app',
76
- * publicKey: '/path/to/public.pem'
77
- * });
78
- *
79
- * // With PKCE (recommended)
80
- * const claims = await exchangeCodeForClaims({
81
- * code: req.body.code,
82
- * oauthTokenUrl: 'https://oauth.example.com/token',
83
- * clientId: 'my-app',
84
- * publicKey: process.env.OAUTH_PUBLIC_KEY!,
85
- * codeVerifier: session.pkceVerifier,
86
- * redirectUri: 'https://myapp.com/callback',
87
- * audience: 'my-app',
88
- * issuer: 'https://oauth.example.com'
89
- * });
90
- * ```
91
- */
92
- export declare function exchangeCodeForClaims(options: ExchangeCodeOptions): Promise<Record<string, any>>;
93
- /**
94
- * Exchange OAuth authorization code for verified JWT claims and the raw id_token.
95
- *
96
- * @param options - Configuration options for code exchange
97
- * @returns Tuple containing [claims, idToken]
98
- * @throws OAuthExchangeError - Code exchange failed
99
- * @throws JWTVerificationError - JWT verification failed
100
- * @throws InvalidPublicKeyError - Public key invalid
101
- */
102
- export declare function exchangeCodeForTokenAndClaims(options: ExchangeCodeOptions): Promise<[Record<string, any>, string]>;
103
- /**
104
- * Verify a JWT and return its claims.
105
- *
106
- * This function verifies the JWT signature using the provided public key
107
- * and validates claims (audience, issuer, expiration).
108
- *
109
- * @param options - Configuration options for JWT verification
110
- * @returns Dictionary containing the verified JWT claims
111
- * @throws JWTVerificationError - JWT verification failed
112
- * @throws InvalidPublicKeyError - Public key invalid
113
- *
114
- * @example
115
- * ```typescript
116
- * // Basic usage
117
- * const claims = verifyJwt({
118
- * token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
119
- * publicKey: 'keys/public.pem'
120
- * });
121
- * console.log(`User: ${claims.sub}`);
122
- *
123
- * // With validation
124
- * const claims = verifyJwt({
125
- * token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
126
- * publicKey: process.env.OAUTH_PUBLIC_KEY!,
127
- * audience: 'my-app',
128
- * issuer: 'https://oauth.example.com',
129
- * leeway: 10 // Allow 10 seconds clock skew
130
- * });
131
- * ```
132
- */
133
- export declare function verifyJwt(options: VerifyJwtOptions): Promise<Record<string, any>>;
134
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAgED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAwE9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAiDxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkHvF"}
package/dist/client.js DELETED
@@ -1,300 +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, apiKey, timeout = 20, codeVerifier, redirectUri) {
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
- apikey: apiKey,
72
- };
73
- const response = await axios_1.default.post(oauthTokenUrl, payload, {
74
- timeout: timeout * 1000,
75
- headers,
76
- });
77
- return response.data;
78
- }
79
- catch (error) {
80
- if (axios_1.default.isAxiosError(error)) {
81
- const axiosError = error;
82
- if (axiosError.response) {
83
- const responseBody = axiosError.response.data;
84
- const errorMsg = responseBody?.error_description ||
85
- responseBody?.error ||
86
- 'Unknown server error';
87
- throw new exceptions_1.OAuthExchangeError(`Code exchange failed: ${errorMsg}`, axiosError.response.status, responseBody);
88
- }
89
- }
90
- throw new exceptions_1.OAuthExchangeError(`Network error while exchanging code: ${error}`);
91
- }
92
- }
93
- /**
94
- * Exchange OAuth authorization code for verified JWT claims.
95
- *
96
- * Supports PKCE (Proof Key for Code Exchange) per RFC 7636 for enhanced security.
97
- *
98
- * @param options - Configuration options for code exchange
99
- * @returns Dictionary containing the verified JWT claims
100
- * @throws OAuthExchangeError - Code exchange failed
101
- * @throws JWTVerificationError - JWT verification failed
102
- * @throws InvalidPublicKeyError - Public key invalid
103
- *
104
- * @example
105
- * ```typescript
106
- * // Basic usage
107
- * const claims = await exchangeCodeForClaims({
108
- * code: req.body.code,
109
- * oauthTokenUrl: 'https://oauth.example.com/token',
110
- * clientId: 'my-app',
111
- * publicKey: '/path/to/public.pem'
112
- * });
113
- *
114
- * // With PKCE (recommended)
115
- * const claims = await exchangeCodeForClaims({
116
- * code: req.body.code,
117
- * oauthTokenUrl: 'https://oauth.example.com/token',
118
- * clientId: 'my-app',
119
- * publicKey: process.env.OAUTH_PUBLIC_KEY!,
120
- * codeVerifier: session.pkceVerifier,
121
- * redirectUri: 'https://myapp.com/callback',
122
- * audience: 'my-app',
123
- * issuer: 'https://oauth.example.com'
124
- * });
125
- * ```
126
- */
127
- async function exchangeCodeForClaims(options) {
128
- const { code, oauthTokenUrl, clientId, publicKey, jwksUrl, apiKey, codeVerifier, redirectUri, timeout = 20, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
129
- // Input validation
130
- if (!code || typeof code !== 'string') {
131
- throw new exceptions_1.OAuthExchangeError('Authorization code must be a non-empty string');
132
- }
133
- if (!oauthTokenUrl || typeof oauthTokenUrl !== 'string') {
134
- throw new exceptions_1.OAuthExchangeError('OAuth token URL must be a non-empty string');
135
- }
136
- if (!clientId || typeof clientId !== 'string') {
137
- throw new exceptions_1.OAuthExchangeError('Client ID must be a non-empty string');
138
- }
139
- if (!apiKey || typeof apiKey !== 'string') {
140
- throw new exceptions_1.OAuthExchangeError('API key must be a non-empty string');
141
- }
142
- if (!publicKey && !jwksUrl) {
143
- throw new exceptions_1.OAuthExchangeError("Must provide either 'publicKey' or 'jwksUrl' for JWT verification");
144
- }
145
- // Exchange code for id_token (with PKCE support)
146
- const responseBody = await exchangeForToken(code, oauthTokenUrl, clientId, apiKey, timeout, codeVerifier, redirectUri);
147
- const idToken = responseBody.id_token;
148
- if (!idToken) {
149
- throw new exceptions_1.OAuthExchangeError("OAuth server response missing 'id_token' field", undefined, responseBody);
150
- }
151
- // Verify JWT
152
- const claims = await verifyJwt({
153
- token: idToken,
154
- publicKey,
155
- jwksUrl,
156
- audience,
157
- issuer,
158
- verifyExp,
159
- leeway,
160
- algorithms,
161
- });
162
- return claims;
163
- }
164
- /**
165
- * Exchange OAuth authorization code for verified JWT claims and the raw id_token.
166
- *
167
- * @param options - Configuration options for code exchange
168
- * @returns Tuple containing [claims, idToken]
169
- * @throws OAuthExchangeError - Code exchange failed
170
- * @throws JWTVerificationError - JWT verification failed
171
- * @throws InvalidPublicKeyError - Public key invalid
172
- */
173
- async function exchangeCodeForTokenAndClaims(options) {
174
- const { code, oauthTokenUrl, clientId, publicKey, jwksUrl, apiKey, codeVerifier, redirectUri, timeout = 20, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
175
- const responseBody = await exchangeForToken(code, oauthTokenUrl, clientId, apiKey, timeout, codeVerifier, redirectUri);
176
- const idToken = responseBody.id_token;
177
- if (!idToken) {
178
- throw new exceptions_1.OAuthExchangeError("OAuth server response missing 'id_token' field", undefined, responseBody);
179
- }
180
- const claims = await verifyJwt({
181
- token: idToken,
182
- publicKey,
183
- jwksUrl,
184
- audience,
185
- issuer,
186
- verifyExp,
187
- leeway,
188
- algorithms,
189
- });
190
- return [claims, idToken];
191
- }
192
- /**
193
- * Verify a JWT and return its claims.
194
- *
195
- * This function verifies the JWT signature using the provided public key
196
- * and validates claims (audience, issuer, expiration).
197
- *
198
- * @param options - Configuration options for JWT verification
199
- * @returns Dictionary containing the verified JWT claims
200
- * @throws JWTVerificationError - JWT verification failed
201
- * @throws InvalidPublicKeyError - Public key invalid
202
- *
203
- * @example
204
- * ```typescript
205
- * // Basic usage
206
- * const claims = verifyJwt({
207
- * token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
208
- * publicKey: 'keys/public.pem'
209
- * });
210
- * console.log(`User: ${claims.sub}`);
211
- *
212
- * // With validation
213
- * const claims = verifyJwt({
214
- * token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...',
215
- * publicKey: process.env.OAUTH_PUBLIC_KEY!,
216
- * audience: 'my-app',
217
- * issuer: 'https://oauth.example.com',
218
- * leeway: 10 // Allow 10 seconds clock skew
219
- * });
220
- * ```
221
- */
222
- async function verifyJwt(options) {
223
- const { token, publicKey, jwksUrl, audience, issuer, verifyExp = true, leeway = 0, algorithms, } = options;
224
- // Input validation
225
- if (!token || typeof token !== 'string') {
226
- throw new exceptions_1.JWTVerificationError('Token must be a non-empty string');
227
- }
228
- if (!publicKey && !jwksUrl) {
229
- throw new exceptions_1.JWTVerificationError("Must provide either 'publicKey' or 'jwksUrl'");
230
- }
231
- // Load and validate public key - jwksUrl takes precedence
232
- let pemKey;
233
- try {
234
- if (jwksUrl) {
235
- // First decode JWT header to get kid
236
- const header = jwt.decode(token, { complete: true })?.header;
237
- if (!header) {
238
- throw new exceptions_1.JWTVerificationError('Failed to decode JWT header');
239
- }
240
- const kid = header.kid;
241
- const jwks = await (0, utils_1.fetchJwks)(jwksUrl);
242
- pemKey = (0, utils_1.getKeyFromJwks)(jwks, kid);
243
- }
244
- else {
245
- pemKey = (0, utils_1.loadPublicKey)(publicKey);
246
- }
247
- }
248
- catch (error) {
249
- if (error instanceof exceptions_1.InvalidPublicKeyError) {
250
- throw error;
251
- }
252
- throw new exceptions_1.InvalidPublicKeyError(`Unexpected error loading public key: ${error}`);
253
- }
254
- // Build verification options
255
- const verifyOptions = {
256
- algorithms: algorithms || ['RS256', 'ES256', 'ES384', 'ES512', 'EdDSA'],
257
- clockTolerance: leeway,
258
- ignoreExpiration: !verifyExp,
259
- };
260
- if (audience) {
261
- verifyOptions.audience = audience;
262
- }
263
- if (issuer) {
264
- verifyOptions.issuer = issuer;
265
- }
266
- // Decode and verify
267
- try {
268
- const claims = jwt.verify(token, pemKey, verifyOptions);
269
- // jwt.verify can return string or object, ensure we have an object
270
- if (typeof claims === 'string') {
271
- throw new exceptions_1.JWTVerificationError('Unexpected JWT format: claims is a string');
272
- }
273
- return claims;
274
- }
275
- catch (error) {
276
- if (error instanceof jwt.TokenExpiredError) {
277
- throw new exceptions_1.JWTVerificationError('Token has expired. Please re-authenticate.', error);
278
- }
279
- if (error instanceof jwt.JsonWebTokenError) {
280
- if (error.message.includes('audience')) {
281
- throw new exceptions_1.JWTVerificationError(`Token audience validation failed. Expected: ${audience}`, error);
282
- }
283
- if (error.message.includes('issuer')) {
284
- throw new exceptions_1.JWTVerificationError(`Token issuer validation failed. Expected: ${issuer}`, error);
285
- }
286
- if (error.message.includes('signature')) {
287
- throw new exceptions_1.JWTVerificationError('Token signature verification failed. Token may have been tampered with.', error);
288
- }
289
- if (error.message.includes('jwt malformed')) {
290
- throw new exceptions_1.JWTVerificationError('Token has invalid structure or encoding', error);
291
- }
292
- throw new exceptions_1.JWTVerificationError(`Token validation failed: ${error.message}`, error);
293
- }
294
- if (error instanceof jwt.NotBeforeError) {
295
- throw new exceptions_1.JWTVerificationError('Token not yet valid (nbf claim). Check server clock synchronization.', error);
296
- }
297
- throw new exceptions_1.JWTVerificationError(`Unexpected error during JWT verification: ${error}`, error);
298
- }
299
- }
300
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}