@vybestack/llxprt-code-auth 0.10.0-nightly.260613.1adad3b34

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 (71) hide show
  1. package/dist/.last_build +0 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.js +11 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/src/auth-precedence-resolver.d.ts +147 -0
  6. package/dist/src/auth-precedence-resolver.js +542 -0
  7. package/dist/src/auth-precedence-resolver.js.map +1 -0
  8. package/dist/src/flows/anthropic-device-flow.d.ts +57 -0
  9. package/dist/src/flows/anthropic-device-flow.js +231 -0
  10. package/dist/src/flows/anthropic-device-flow.js.map +1 -0
  11. package/dist/src/flows/codex-device-flow.d.ts +114 -0
  12. package/dist/src/flows/codex-device-flow.js +437 -0
  13. package/dist/src/flows/codex-device-flow.js.map +1 -0
  14. package/dist/src/flows/qwen-device-flow.d.ts +45 -0
  15. package/dist/src/flows/qwen-device-flow.js +183 -0
  16. package/dist/src/flows/qwen-device-flow.js.map +1 -0
  17. package/dist/src/index.d.ts +34 -0
  18. package/dist/src/index.js +26 -0
  19. package/dist/src/index.js.map +1 -0
  20. package/dist/src/interfaces/debug-logger.d.ts +31 -0
  21. package/dist/src/interfaces/debug-logger.js +6 -0
  22. package/dist/src/interfaces/debug-logger.js.map +1 -0
  23. package/dist/src/interfaces/index.d.ts +18 -0
  24. package/dist/src/interfaces/index.js +10 -0
  25. package/dist/src/interfaces/index.js.map +1 -0
  26. package/dist/src/interfaces/provider-key-storage.d.ts +26 -0
  27. package/dist/src/interfaces/provider-key-storage.js +6 -0
  28. package/dist/src/interfaces/provider-key-storage.js.map +1 -0
  29. package/dist/src/interfaces/runtime-context.d.ts +37 -0
  30. package/dist/src/interfaces/runtime-context.js +6 -0
  31. package/dist/src/interfaces/runtime-context.js.map +1 -0
  32. package/dist/src/interfaces/secure-store.d.ts +47 -0
  33. package/dist/src/interfaces/secure-store.js +6 -0
  34. package/dist/src/interfaces/secure-store.js.map +1 -0
  35. package/dist/src/interfaces/settings-service.d.ts +25 -0
  36. package/dist/src/interfaces/settings-service.js +6 -0
  37. package/dist/src/interfaces/settings-service.js.map +1 -0
  38. package/dist/src/keyring-token-store.d.ts +96 -0
  39. package/dist/src/keyring-token-store.js +391 -0
  40. package/dist/src/keyring-token-store.js.map +1 -0
  41. package/dist/src/oauth-errors.d.ts +173 -0
  42. package/dist/src/oauth-errors.js +465 -0
  43. package/dist/src/oauth-errors.js.map +1 -0
  44. package/dist/src/precedence.d.ts +115 -0
  45. package/dist/src/precedence.js +278 -0
  46. package/dist/src/precedence.js.map +1 -0
  47. package/dist/src/proxy/framing.d.ts +35 -0
  48. package/dist/src/proxy/framing.js +86 -0
  49. package/dist/src/proxy/framing.js.map +1 -0
  50. package/dist/src/proxy/proxy-provider-key-storage.d.ts +23 -0
  51. package/dist/src/proxy/proxy-provider-key-storage.js +41 -0
  52. package/dist/src/proxy/proxy-provider-key-storage.js.map +1 -0
  53. package/dist/src/proxy/proxy-socket-client.d.ts +43 -0
  54. package/dist/src/proxy/proxy-socket-client.js +219 -0
  55. package/dist/src/proxy/proxy-socket-client.js.map +1 -0
  56. package/dist/src/proxy/proxy-token-store.d.ts +39 -0
  57. package/dist/src/proxy/proxy-token-store.js +87 -0
  58. package/dist/src/proxy/proxy-token-store.js.map +1 -0
  59. package/dist/src/token-merge.d.ts +16 -0
  60. package/dist/src/token-merge.js +13 -0
  61. package/dist/src/token-merge.js.map +1 -0
  62. package/dist/src/token-sanitization.d.ts +16 -0
  63. package/dist/src/token-sanitization.js +10 -0
  64. package/dist/src/token-sanitization.js.map +1 -0
  65. package/dist/src/token-store.d.ts +93 -0
  66. package/dist/src/token-store.js +7 -0
  67. package/dist/src/token-store.js.map +1 -0
  68. package/dist/src/types.d.ts +204 -0
  69. package/dist/src/types.js +86 -0
  70. package/dist/src/types.js.map +1 -0
  71. package/package.json +42 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Anthropic OAuth 2.0 Device Flow Implementation
3
+ *
4
+ * Implements OAuth 2.0 device authorization grant flow for Anthropic Claude API.
5
+ * Based on the OAuth 2.0 Device Authorization Grant specification (RFC 8628).
6
+ */
7
+ import { createHash, randomBytes } from 'crypto';
8
+ import { URL } from 'node:url';
9
+ /**
10
+ * Anthropic-specific OAuth 2.0 device flow implementation.
11
+ * Handles authentication for Claude API access.
12
+ */
13
+ export class AnthropicDeviceFlow {
14
+ config;
15
+ codeVerifier;
16
+ _codeChallenge;
17
+ state;
18
+ redirectUri;
19
+ revokeToken;
20
+ constructor(config) {
21
+ const defaultConfig = {
22
+ clientId: '9d1c250a-e61b-44d9-88ed-5944d1962f5e', // Anthropic's public OAuth client ID
23
+ authorizationEndpoint: 'https://claude.ai/oauth/authorize', // Use claude.ai like OpenCode's "max" mode
24
+ tokenEndpoint: 'https://console.anthropic.com/v1/oauth/token',
25
+ scopes: ['org:create_api_key', 'user:profile', 'user:inference'],
26
+ };
27
+ this.config = { ...defaultConfig, ...config };
28
+ this.redirectUri = 'https://console.anthropic.com/oauth/code/callback';
29
+ }
30
+ /**
31
+ * Generates PKCE code verifier and challenge using S256 method
32
+ */
33
+ generatePKCE() {
34
+ // Generate a random code verifier (43-128 characters)
35
+ const _verifier = randomBytes(32).toString('base64url');
36
+ this.codeVerifier = _verifier;
37
+ // Generate code challenge using S256 (SHA256 hash)
38
+ const challenge = createHash('sha256')
39
+ .update(_verifier)
40
+ .digest('base64url');
41
+ this._codeChallenge = challenge;
42
+ // Store challenge for potential future use
43
+ void this._codeChallenge;
44
+ return { verifier: _verifier, challenge };
45
+ }
46
+ /**
47
+ * Initiates the OAuth flow by constructing the authorization URL.
48
+ * Since Anthropic doesn't have a device flow, we simulate it with authorization code flow.
49
+ */
50
+ async initiateDeviceFlow(redirectUri) {
51
+ // Generate PKCE parameters
52
+ const { verifier, challenge } = this.generatePKCE();
53
+ // Use verifier as state like OpenCode does
54
+ this.state = verifier; // Store for later use in token exchange
55
+ this.redirectUri =
56
+ redirectUri ?? 'https://console.anthropic.com/oauth/code/callback';
57
+ // Build authorization URL with PKCE parameters
58
+ const params = new URLSearchParams({
59
+ code: 'true',
60
+ client_id: this.config.clientId,
61
+ response_type: 'code',
62
+ redirect_uri: this.redirectUri,
63
+ scope: this.config.scopes.join(' '),
64
+ code_challenge: challenge,
65
+ code_challenge_method: 'S256',
66
+ state: verifier, // Use verifier as state like OpenCode
67
+ });
68
+ const authUrl = `${this.config.authorizationEndpoint}?${params.toString()}`;
69
+ // Return a simulated device code response with the authorization URL
70
+ // The user will need to manually visit this URL and authorize
71
+ return {
72
+ device_code: verifier, // Use verifier as a tracking ID
73
+ user_code: 'ANTHROPIC', // Display code for user
74
+ verification_uri: 'https://console.anthropic.com/oauth/authorize',
75
+ verification_uri_complete: authUrl,
76
+ expires_in: 1800, // 30 minutes
77
+ interval: 5, // 5 seconds polling interval
78
+ };
79
+ }
80
+ /**
81
+ * Exchange authorization code for access token (PKCE flow)
82
+ */
83
+ async exchangeCodeForToken(authCodeWithState) {
84
+ if (!this.codeVerifier) {
85
+ throw new Error('No PKCE code verifier found - OAuth flow not initialized');
86
+ }
87
+ // OpenCode splits the code and state - format: code#state
88
+ const splits = authCodeWithState.split('#');
89
+ const authCode = splits[0];
90
+ const stateFromResponse = splits[1] || this.state; // Use state from response if available
91
+ // OpenCode sends JSON, not form-encoded!
92
+ const requestBody = {
93
+ grant_type: 'authorization_code',
94
+ code: authCode,
95
+ state: stateFromResponse, // Include state in the request
96
+ client_id: this.config.clientId,
97
+ redirect_uri: this.redirectUri,
98
+ code_verifier: this.codeVerifier,
99
+ };
100
+ const response = await fetch(this.config.tokenEndpoint, {
101
+ method: 'POST',
102
+ headers: {
103
+ 'Content-Type': 'application/json', // JSON, not form-encoded!
104
+ },
105
+ body: JSON.stringify(requestBody), // Send as JSON
106
+ });
107
+ if (!response.ok) {
108
+ const error = await response.text();
109
+ throw new Error(`Failed to exchange authorization code: ${error}`);
110
+ }
111
+ const data = (await response.json());
112
+ return this.mapTokenResponse(data);
113
+ }
114
+ getState() {
115
+ if (!this.state) {
116
+ throw new Error('OAuth flow not initialized');
117
+ }
118
+ return this.state;
119
+ }
120
+ buildAuthorizationUrl(redirectUri) {
121
+ if (!this._codeChallenge || !this.state) {
122
+ throw new Error('OAuth flow not initialized');
123
+ }
124
+ const redirect = new URL(redirectUri);
125
+ if (redirect.hostname !== '127.0.0.1' &&
126
+ redirect.hostname !== 'localhost') {
127
+ throw new Error('Only localhost redirect URIs are supported for Anthropic OAuth');
128
+ }
129
+ this.redirectUri = redirectUri;
130
+ const params = new URLSearchParams({
131
+ code: 'true',
132
+ client_id: this.config.clientId,
133
+ response_type: 'code',
134
+ redirect_uri: redirectUri,
135
+ scope: this.config.scopes.join(' '),
136
+ code_challenge: this._codeChallenge,
137
+ code_challenge_method: 'S256',
138
+ state: this.state,
139
+ });
140
+ return `${this.config.authorizationEndpoint}?${params.toString()}`;
141
+ }
142
+ /**
143
+ * Polls for the access token after user authorization.
144
+ */
145
+ async pollForToken(deviceCode) {
146
+ const startTime = Date.now();
147
+ const expiresIn = 1800 * 1000; // 30 minutes in milliseconds
148
+ const interval = 5000; // 5 seconds default polling interval
149
+ while (Date.now() - startTime < expiresIn) {
150
+ try {
151
+ const response = await fetch(this.config.tokenEndpoint, {
152
+ method: 'POST',
153
+ headers: {
154
+ 'Content-Type': 'application/x-www-form-urlencoded',
155
+ },
156
+ body: new URLSearchParams({
157
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
158
+ device_code: deviceCode,
159
+ client_id: this.config.clientId,
160
+ }),
161
+ });
162
+ if (response.ok) {
163
+ const data = (await response.json());
164
+ return this.mapTokenResponse(data);
165
+ }
166
+ const error = (await response.json());
167
+ // Handle polling errors
168
+ let sleepMs = interval;
169
+ if (error.error === 'authorization_pending') {
170
+ // Continue polling
171
+ }
172
+ else if (error.error === 'slow_down') {
173
+ sleepMs = interval * 2;
174
+ }
175
+ else {
176
+ // Handle other errors
177
+ throw new Error(`Token polling failed: ${error.error_description ?? error.error}`);
178
+ }
179
+ await new Promise((resolve) => setTimeout(resolve, sleepMs));
180
+ }
181
+ catch (error) {
182
+ if (error instanceof Error &&
183
+ error.message.includes('Token polling failed')) {
184
+ throw error;
185
+ }
186
+ // Network errors - continue polling
187
+ await new Promise((resolve) => setTimeout(resolve, interval));
188
+ }
189
+ }
190
+ throw new Error('Authorization timeout - user did not complete authentication');
191
+ }
192
+ /**
193
+ * Refreshes an expired access token using a refresh token.
194
+ */
195
+ async refreshToken(refreshToken) {
196
+ const response = await fetch(this.config.tokenEndpoint, {
197
+ method: 'POST',
198
+ headers: {
199
+ 'Content-Type': 'application/x-www-form-urlencoded',
200
+ },
201
+ body: new URLSearchParams({
202
+ grant_type: 'refresh_token',
203
+ refresh_token: refreshToken,
204
+ client_id: this.config.clientId,
205
+ }),
206
+ });
207
+ if (!response.ok) {
208
+ const error = await response.text();
209
+ throw new Error(`Failed to refresh Anthropic token: ${error}`);
210
+ }
211
+ const data = (await response.json());
212
+ return this.mapTokenResponse(data);
213
+ }
214
+ /**
215
+ * Maps Anthropic's token response to our standard OAuthToken format.
216
+ */
217
+ mapTokenResponse(data) {
218
+ const expiresIn = data.expires_in;
219
+ const expiresInSeconds = typeof expiresIn === 'number' && !isNaN(expiresIn) && expiresIn > 0
220
+ ? expiresIn
221
+ : 3600;
222
+ return {
223
+ access_token: data.access_token,
224
+ expiry: Math.floor(Date.now() / 1000) + expiresInSeconds,
225
+ refresh_token: data.refresh_token,
226
+ scope: data.scope,
227
+ token_type: 'Bearer',
228
+ };
229
+ }
230
+ }
231
+ //# sourceMappingURL=anthropic-device-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-device-flow.js","sourceRoot":"","sources":["../../../src/flows/anthropic-device-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IDebugLogger } from '../interfaces/debug-logger.js';
7
+ import { type CodexOAuthToken } from '../types.js';
8
+ /**
9
+ * Codex-specific OAuth configuration
10
+ * Exported for reuse by CLI and other consumers to ensure single source of truth
11
+ */
12
+ export declare const CODEX_CONFIG: {
13
+ readonly clientId: "app_EMoamEEZ73f0CkXaXp7hrann";
14
+ readonly issuer: "https://auth.openai.com";
15
+ readonly tokenEndpoint: "https://auth.openai.com/oauth/token";
16
+ readonly authorizationEndpoint: "https://auth.openai.com/oauth/authorize";
17
+ readonly deviceAuthUserCodeEndpoint: "https://auth.openai.com/api/accounts/deviceauth/usercode";
18
+ readonly deviceAuthTokenEndpoint: "https://auth.openai.com/api/accounts/deviceauth/token";
19
+ readonly deviceAuthCallbackUri: "https://auth.openai.com/deviceauth/callback";
20
+ readonly scopes: readonly ["openid", "profile", "email", "offline_access"];
21
+ readonly originator: "codex_cli_rs";
22
+ };
23
+ /**
24
+ * Codex OAuth PKCE flow implementation
25
+ * Implements OAuth 2.0 Authorization Code flow with PKCE for Codex authentication
26
+ */
27
+ export declare class CodexDeviceFlow {
28
+ private logger;
29
+ private codeVerifiers;
30
+ private static readonly NO_OP_LOGGER;
31
+ constructor(options?: {
32
+ logger?: IDebugLogger;
33
+ });
34
+ /**
35
+ * Build authorization URL for browser-based OAuth flow
36
+ * @param redirectUri Callback URL for OAuth redirect
37
+ * @param state Random state parameter for CSRF protection
38
+ * @returns Authorization URL to open in browser
39
+ */
40
+ buildAuthorizationUrl(redirectUri: string, state: string): string;
41
+ /**
42
+ * Exchange authorization code for OAuth tokens
43
+ * @param authCode Authorization code from OAuth callback
44
+ * @param redirectUri Callback URL (must match the one used in authorization request)
45
+ * @param state State parameter from OAuth callback
46
+ * @returns Validated CodexOAuthToken with account_id
47
+ * @throws Error if code verifier not found for state or token exchange fails
48
+ */
49
+ exchangeCodeForToken(authCode: string, redirectUri: string, state: string): Promise<CodexOAuthToken>;
50
+ /**
51
+ * POST to the token endpoint and return a validated CodexTokenResponse.
52
+ * @throws Error if the HTTP request fails or the response is not OK
53
+ */
54
+ private performTokenExchange;
55
+ /**
56
+ * Validate token response, extract account_id, and build a CodexOAuthToken.
57
+ * @throws Error if id_token is missing or account_id cannot be extracted
58
+ */
59
+ private buildCodexToken;
60
+ /**
61
+ * Refresh an expired access token using refresh token
62
+ * @param refreshToken Valid refresh token
63
+ * @returns New CodexOAuthToken with updated expiry
64
+ * @throws Error if refresh fails or id_token missing
65
+ */
66
+ refreshToken(refreshToken: string): Promise<CodexOAuthToken>;
67
+ /**
68
+ * Extract account_id from id_token JWT without external libraries
69
+ * JWT format: header.payload.signature (base64url encoded)
70
+ * @param idToken JWT id_token from OAuth response
71
+ * @returns account_id extracted from JWT claims
72
+ * @throws Error if JWT format invalid or account_id not found
73
+ */
74
+ private extractAccountIdFromIdToken;
75
+ /**
76
+ * Helper to throw error when id_token is missing
77
+ * @throws Error indicating id_token required
78
+ */
79
+ private throwMissingAccountId;
80
+ /**
81
+ * Request a user code for device authorization flow (browserless authentication)
82
+ * @returns Device code response with user_code and device_auth_id
83
+ */
84
+ requestDeviceCode(): Promise<{
85
+ device_auth_id: string;
86
+ user_code: string;
87
+ interval: number;
88
+ }>;
89
+ /**
90
+ * Poll for token using device authorization
91
+ * @param deviceAuthId Device authorization ID
92
+ * @param userCode User code from device flow
93
+ * @param intervalSeconds Polling interval in seconds
94
+ * @returns Authorization code and PKCE codes for token exchange
95
+ */
96
+ pollForDeviceToken(deviceAuthId: string, userCode: string, intervalSeconds?: number): Promise<{
97
+ authorization_code: string;
98
+ code_verifier: string;
99
+ code_challenge: string;
100
+ }>;
101
+ /**
102
+ * Complete device authorization flow by exchanging authorization code for tokens
103
+ * @param authorizationCode Authorization code from polling response
104
+ * @param codeVerifier PKCE code verifier from polling response
105
+ * @param redirectUri OAuth redirect URI
106
+ * @returns Complete OAuth token with access_token, refresh_token, etc.
107
+ */
108
+ completeDeviceAuth(authorizationCode: string, codeVerifier: string, redirectUri: string): Promise<CodexOAuthToken>;
109
+ /**
110
+ * Generate PKCE code verifier and challenge
111
+ * @returns Object containing verifier and challenge strings
112
+ */
113
+ private generatePKCE;
114
+ }