@open-vibe-lab/open-sub-auth 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/LICENSE +21 -0
- package/README.md +218 -0
- package/dist/cli/claude-3WKImhqM.mjs +56 -0
- package/dist/cli/claude-3WKImhqM.mjs.map +1 -0
- package/dist/cli/index.d.mts +2 -0
- package/dist/cli/index.mjs +90 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/cli/login-_HdTW5J_.mjs +33 -0
- package/dist/cli/login-_HdTW5J_.mjs.map +1 -0
- package/dist/cli/logout-CZm-tSVH.mjs +23 -0
- package/dist/cli/logout-CZm-tSVH.mjs.map +1 -0
- package/dist/cli/manager-CKGbp7Yz.mjs +331 -0
- package/dist/cli/manager-CKGbp7Yz.mjs.map +1 -0
- package/dist/cli/oauth-pkce-Bi02-h23.mjs +282 -0
- package/dist/cli/oauth-pkce-Bi02-h23.mjs.map +1 -0
- package/dist/cli/openai-codex-DJi_Q6Zm.mjs +102 -0
- package/dist/cli/openai-codex-DJi_Q6Zm.mjs.map +1 -0
- package/dist/cli/registry-Cp-_Ipc6.mjs +96 -0
- package/dist/cli/registry-Cp-_Ipc6.mjs.map +1 -0
- package/dist/cli/status-C-vkcjVM.mjs +47 -0
- package/dist/cli/status-C-vkcjVM.mjs.map +1 -0
- package/dist/cli/token-DF_-h4Rb.mjs +23 -0
- package/dist/cli/token-DF_-h4Rb.mjs.map +1 -0
- package/dist/cli/ui-CdGEuLwh.mjs +34 -0
- package/dist/cli/ui-CdGEuLwh.mjs.map +1 -0
- package/dist/index.cjs +859 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +328 -0
- package/dist/index.d.mts +328 -0
- package/dist/index.mjs +827 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +65 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/** OAuth token set returned after successful authentication */
|
|
3
|
+
interface TokenSet {
|
|
4
|
+
accessToken: string;
|
|
5
|
+
refreshToken: string | null;
|
|
6
|
+
/** Unix timestamp in milliseconds when the access token expires */
|
|
7
|
+
expiresAt: number;
|
|
8
|
+
/** JWT id_token (present for OpenAI, contains email/plan info) */
|
|
9
|
+
idToken?: string;
|
|
10
|
+
tokenType: "bearer" | "api-key";
|
|
11
|
+
scopes?: string[];
|
|
12
|
+
/** Raw response from the token endpoint for extensibility */
|
|
13
|
+
raw?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
/** Configuration for an OAuth provider */
|
|
16
|
+
interface ProviderConfig {
|
|
17
|
+
/** Unique identifier: "claude", "openai-codex", "github-copilot" */
|
|
18
|
+
name: string;
|
|
19
|
+
/** Human-readable display name */
|
|
20
|
+
displayName: string;
|
|
21
|
+
/** Authorization endpoint URL (for PKCE flow) */
|
|
22
|
+
authorizationEndpoint?: string;
|
|
23
|
+
/** Token exchange endpoint URL */
|
|
24
|
+
tokenEndpoint: string;
|
|
25
|
+
/** OAuth client ID */
|
|
26
|
+
clientId: string;
|
|
27
|
+
/** Redirect URI for callback (for PKCE flow) */
|
|
28
|
+
redirectUri?: string;
|
|
29
|
+
/** OAuth scopes to request */
|
|
30
|
+
scopes?: string[];
|
|
31
|
+
/** Device code endpoint URL (for device code flow) */
|
|
32
|
+
deviceCodeEndpoint?: string;
|
|
33
|
+
/** OAuth grant type */
|
|
34
|
+
grantType: "authorization_code" | "device_code";
|
|
35
|
+
/** Token exchange request body format (default: "form") */
|
|
36
|
+
tokenBodyFormat?: "form" | "json";
|
|
37
|
+
/** Use PKCE verifier as state parameter (non-standard, required by some providers) */
|
|
38
|
+
stateIsVerifier?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Provider interface that all providers must implement */
|
|
41
|
+
interface Provider {
|
|
42
|
+
readonly config: ProviderConfig;
|
|
43
|
+
/** Run the full interactive login flow */
|
|
44
|
+
login(options?: LoginOptions): Promise<TokenSet>;
|
|
45
|
+
/** Refresh an expired access token */
|
|
46
|
+
refresh(refreshToken: string): Promise<TokenSet>;
|
|
47
|
+
/** Build auth headers for making API calls */
|
|
48
|
+
getAuthHeaders(accessToken: string): AuthHeaders;
|
|
49
|
+
/** Extract a stable account identifier from tokens */
|
|
50
|
+
getAccountId(tokenSet: TokenSet): string;
|
|
51
|
+
/** Optional: human-readable account label (e.g., email) */
|
|
52
|
+
getAccountLabel?(tokenSet: TokenSet): string | undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Options for the login flow */
|
|
55
|
+
interface LoginOptions {
|
|
56
|
+
/** Override port for the local callback server */
|
|
57
|
+
port?: number;
|
|
58
|
+
/** Timeout in ms for the entire login flow (default: 120000) */
|
|
59
|
+
timeout?: number;
|
|
60
|
+
/** Use manual code input mode instead of local callback server */
|
|
61
|
+
manual?: boolean;
|
|
62
|
+
/** Callback when the browser should be opened */
|
|
63
|
+
onOpenBrowser?: (url: string) => void;
|
|
64
|
+
/** Callback for device code flow: display code to user */
|
|
65
|
+
onDeviceCode?: (code: DeviceCodeInfo) => void;
|
|
66
|
+
}
|
|
67
|
+
/** Device code information displayed to the user */
|
|
68
|
+
interface DeviceCodeInfo {
|
|
69
|
+
userCode: string;
|
|
70
|
+
verificationUri: string;
|
|
71
|
+
expiresIn: number;
|
|
72
|
+
interval: number;
|
|
73
|
+
}
|
|
74
|
+
/** HTTP headers for authenticated API calls */
|
|
75
|
+
type AuthHeaders = Record<string, string>;
|
|
76
|
+
/** Stored credential with metadata */
|
|
77
|
+
interface StoredCredential {
|
|
78
|
+
tokenSet: TokenSet;
|
|
79
|
+
metadata: TokenMetadata;
|
|
80
|
+
}
|
|
81
|
+
/** Metadata about a stored credential */
|
|
82
|
+
interface TokenMetadata {
|
|
83
|
+
provider: string;
|
|
84
|
+
accountId: string;
|
|
85
|
+
accountLabel?: string;
|
|
86
|
+
createdAt: number;
|
|
87
|
+
lastRefreshedAt: number;
|
|
88
|
+
}
|
|
89
|
+
/** Token storage interface */
|
|
90
|
+
interface TokenStore {
|
|
91
|
+
get(provider: string, accountId: string): Promise<StoredCredential | null>;
|
|
92
|
+
set(provider: string, accountId: string, credential: StoredCredential): Promise<void>;
|
|
93
|
+
delete(provider: string, accountId: string): Promise<void>;
|
|
94
|
+
list(provider?: string): Promise<StoredCredential[]>;
|
|
95
|
+
}
|
|
96
|
+
/** Status of a stored credential */
|
|
97
|
+
interface CredentialStatus {
|
|
98
|
+
provider: string;
|
|
99
|
+
displayName: string;
|
|
100
|
+
accountId: string;
|
|
101
|
+
accountLabel?: string;
|
|
102
|
+
isExpired: boolean;
|
|
103
|
+
expiresAt: number;
|
|
104
|
+
hasRefreshToken: boolean;
|
|
105
|
+
}
|
|
106
|
+
/** PKCE parameters for OAuth flow */
|
|
107
|
+
interface PKCEParams {
|
|
108
|
+
codeVerifier: string;
|
|
109
|
+
codeChallenge: string;
|
|
110
|
+
}
|
|
111
|
+
/** Result from the callback server or manual code input */
|
|
112
|
+
interface AuthorizationResult {
|
|
113
|
+
code: string;
|
|
114
|
+
state: string;
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/errors.d.ts
|
|
118
|
+
declare class OpenSubAuthError extends Error {
|
|
119
|
+
constructor(message: string);
|
|
120
|
+
}
|
|
121
|
+
declare class AuthenticationError extends OpenSubAuthError {
|
|
122
|
+
readonly provider?: string | undefined;
|
|
123
|
+
constructor(message: string, provider?: string | undefined);
|
|
124
|
+
}
|
|
125
|
+
declare class TokenExpiredError extends OpenSubAuthError {
|
|
126
|
+
readonly provider: string;
|
|
127
|
+
constructor(provider: string);
|
|
128
|
+
}
|
|
129
|
+
declare class TokenRefreshError extends OpenSubAuthError {
|
|
130
|
+
readonly provider: string;
|
|
131
|
+
readonly cause_: unknown;
|
|
132
|
+
constructor(provider: string, cause_: unknown);
|
|
133
|
+
}
|
|
134
|
+
declare class ProviderNotFoundError extends OpenSubAuthError {
|
|
135
|
+
readonly providerName: string;
|
|
136
|
+
constructor(providerName: string);
|
|
137
|
+
}
|
|
138
|
+
declare class NoCredentialError extends OpenSubAuthError {
|
|
139
|
+
readonly provider: string;
|
|
140
|
+
readonly accountId?: string | undefined;
|
|
141
|
+
constructor(provider: string, accountId?: string | undefined);
|
|
142
|
+
}
|
|
143
|
+
declare class OAuthCallbackError extends OpenSubAuthError {
|
|
144
|
+
constructor(message: string);
|
|
145
|
+
}
|
|
146
|
+
declare class OAuthTimeoutError extends OpenSubAuthError {
|
|
147
|
+
readonly timeoutMs: number;
|
|
148
|
+
constructor(timeoutMs: number);
|
|
149
|
+
}
|
|
150
|
+
declare class StateMismatchError extends OpenSubAuthError {
|
|
151
|
+
constructor();
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/token/manager.d.ts
|
|
155
|
+
/** Central token lifecycle manager */
|
|
156
|
+
declare class TokenManager {
|
|
157
|
+
private readonly store;
|
|
158
|
+
/** Per-provider+account mutex to prevent concurrent refreshes */
|
|
159
|
+
private readonly refreshLocks;
|
|
160
|
+
constructor(store: TokenStore);
|
|
161
|
+
/** Run the interactive login flow for a provider, store the tokens */
|
|
162
|
+
login(providerName: string, options?: LoginOptions): Promise<StoredCredential>;
|
|
163
|
+
/** Get a valid access token, refreshing if needed */
|
|
164
|
+
getToken(providerName: string, accountId?: string): Promise<string>;
|
|
165
|
+
/** Get authenticated headers for API calls */
|
|
166
|
+
getAuthHeaders(providerName: string, accountId?: string): Promise<AuthHeaders>;
|
|
167
|
+
/** Remove stored tokens for a provider */
|
|
168
|
+
logout(providerName: string, accountId?: string): Promise<void>;
|
|
169
|
+
/** Get status of all stored credentials */
|
|
170
|
+
status(): Promise<CredentialStatus[]>;
|
|
171
|
+
private isTokenValid;
|
|
172
|
+
private resolveCredential;
|
|
173
|
+
private refreshWithLock;
|
|
174
|
+
private doRefresh;
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/storage/file-store.d.ts
|
|
178
|
+
/** Token store backed by an encrypted JSON file */
|
|
179
|
+
declare class FileStore implements TokenStore {
|
|
180
|
+
private readonly filePath;
|
|
181
|
+
constructor(filePath?: string);
|
|
182
|
+
get(provider: string, accountId: string): Promise<StoredCredential | null>;
|
|
183
|
+
set(provider: string, accountId: string, credential: StoredCredential): Promise<void>;
|
|
184
|
+
delete(provider: string, accountId: string): Promise<void>;
|
|
185
|
+
list(provider?: string): Promise<StoredCredential[]>;
|
|
186
|
+
private deriveKey;
|
|
187
|
+
private encrypt;
|
|
188
|
+
private decrypt;
|
|
189
|
+
private readFile;
|
|
190
|
+
private writeFile;
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/storage/keychain-store.d.ts
|
|
194
|
+
/** Token store backed by the OS keychain via cross-keychain */
|
|
195
|
+
declare class KeychainStore implements TokenStore {
|
|
196
|
+
private keychain;
|
|
197
|
+
private getKeychain;
|
|
198
|
+
private makeKey;
|
|
199
|
+
get(provider: string, accountId: string): Promise<StoredCredential | null>;
|
|
200
|
+
set(provider: string, accountId: string, credential: StoredCredential): Promise<void>;
|
|
201
|
+
delete(provider: string, accountId: string): Promise<void>;
|
|
202
|
+
list(provider?: string): Promise<StoredCredential[]>;
|
|
203
|
+
private getIndex;
|
|
204
|
+
private setIndex;
|
|
205
|
+
private addToIndex;
|
|
206
|
+
private removeFromIndex;
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/storage/store.d.ts
|
|
210
|
+
/**
|
|
211
|
+
* Create a token store, preferring the OS keychain with encrypted file fallback.
|
|
212
|
+
* @param preferKeychain - If true (default), try keychain first
|
|
213
|
+
*/
|
|
214
|
+
declare function createTokenStore(preferKeychain?: boolean): Promise<TokenStore>;
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/providers/registry.d.ts
|
|
217
|
+
/** Register a provider factory */
|
|
218
|
+
declare function registerProvider(name: string, factory: () => Provider): void;
|
|
219
|
+
/** Get a provider instance by name */
|
|
220
|
+
declare function getProvider(name: string): Provider;
|
|
221
|
+
/** List all registered provider names */
|
|
222
|
+
declare function listProviders(): string[];
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/providers/claude.d.ts
|
|
225
|
+
declare class ClaudeProvider implements Provider {
|
|
226
|
+
readonly config: ProviderConfig;
|
|
227
|
+
login(options?: LoginOptions): Promise<TokenSet>;
|
|
228
|
+
refresh(refreshToken: string): Promise<TokenSet>;
|
|
229
|
+
getAuthHeaders(accessToken: string): AuthHeaders;
|
|
230
|
+
getAccountId(tokenSet: TokenSet): string;
|
|
231
|
+
getAccountLabel(_tokenSet: TokenSet): string | undefined;
|
|
232
|
+
}
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/providers/openai-codex.d.ts
|
|
235
|
+
declare class OpenAICodexProvider implements Provider {
|
|
236
|
+
readonly config: ProviderConfig;
|
|
237
|
+
login(options?: LoginOptions): Promise<TokenSet>;
|
|
238
|
+
refresh(refreshToken: string): Promise<TokenSet>;
|
|
239
|
+
getAuthHeaders(accessToken: string): AuthHeaders;
|
|
240
|
+
getAccountId(tokenSet: TokenSet): string;
|
|
241
|
+
getAccountLabel(tokenSet: TokenSet): string | undefined;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Import tokens from an existing Codex CLI installation.
|
|
245
|
+
* Reads from ~/.codex/auth.json or $CODEX_HOME/auth.json.
|
|
246
|
+
*/
|
|
247
|
+
declare function importFromCodexCli(): TokenSet | null;
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/core/crypto.d.ts
|
|
250
|
+
/** Generate a cryptographically random PKCE code verifier (43-128 chars, base64url) */
|
|
251
|
+
declare function generateCodeVerifier(): string;
|
|
252
|
+
/** Generate a PKCE code challenge from a verifier using S256 method */
|
|
253
|
+
declare function generateCodeChallenge(verifier: string): string;
|
|
254
|
+
/** Generate both PKCE code verifier and challenge */
|
|
255
|
+
declare function generatePKCE(): PKCEParams;
|
|
256
|
+
/** Generate a random state parameter for CSRF protection */
|
|
257
|
+
declare function generateState(): string;
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/core/oauth-pkce.d.ts
|
|
260
|
+
/** Build the full OAuth authorization URL with PKCE and state params */
|
|
261
|
+
declare function buildAuthorizationUrl(config: ProviderConfig, codeChallenge: string, state: string, redirectUri: string): string;
|
|
262
|
+
/** Exchange an authorization code for tokens */
|
|
263
|
+
declare function exchangeCode(config: ProviderConfig, code: string, codeVerifier: string, redirectUri: string, state?: string): Promise<TokenSet>;
|
|
264
|
+
/** Refresh an access token using a refresh token */
|
|
265
|
+
declare function refreshAccessToken(config: ProviderConfig, refreshToken: string): Promise<TokenSet>;
|
|
266
|
+
interface PKCEFlowOptions {
|
|
267
|
+
config: ProviderConfig;
|
|
268
|
+
loginOptions?: LoginOptions;
|
|
269
|
+
/**
|
|
270
|
+
* Manual mode redirect URI (used when manual=true).
|
|
271
|
+
* If not provided, manual mode is not available.
|
|
272
|
+
*/
|
|
273
|
+
manualRedirectUri?: string;
|
|
274
|
+
}
|
|
275
|
+
/** Execute the full PKCE flow: generate params, open browser, wait for callback, exchange code */
|
|
276
|
+
declare function executePKCEFlow(options: PKCEFlowOptions): Promise<TokenSet>;
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/core/callback-server.d.ts
|
|
279
|
+
interface CallbackServerOptions {
|
|
280
|
+
/** Port to listen on (0 = random available port) */
|
|
281
|
+
port?: number;
|
|
282
|
+
/** Expected state parameter for CSRF validation */
|
|
283
|
+
expectedState: string;
|
|
284
|
+
/** Timeout in milliseconds (default: 120000) */
|
|
285
|
+
timeout?: number;
|
|
286
|
+
/** Path to listen on (default: "/callback") */
|
|
287
|
+
path?: string;
|
|
288
|
+
}
|
|
289
|
+
/** Start a local HTTP server to receive the OAuth callback redirect */
|
|
290
|
+
declare function startCallbackServer(options: CallbackServerOptions): Promise<{
|
|
291
|
+
result: Promise<AuthorizationResult>;
|
|
292
|
+
port: number;
|
|
293
|
+
close: () => void;
|
|
294
|
+
}>;
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region src/core/manual-code-input.d.ts
|
|
297
|
+
/**
|
|
298
|
+
* Parse a "code#state" string (Anthropic's manual paste format).
|
|
299
|
+
* Also supports a plain authorization code (state validated separately).
|
|
300
|
+
*/
|
|
301
|
+
declare function parseCodeAndState(input: string, expectedState: string): AuthorizationResult;
|
|
302
|
+
/** Prompt the user to paste the authorization code from their browser */
|
|
303
|
+
declare function promptForCode(expectedState: string): Promise<AuthorizationResult>;
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/core/browser.d.ts
|
|
306
|
+
/** Open a URL in the user's default browser. Does not throw on failure. */
|
|
307
|
+
declare function openBrowser(url: string): void;
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/token/jwt.d.ts
|
|
310
|
+
/** Decoded JWT claims (no signature verification) */
|
|
311
|
+
interface JWTClaims {
|
|
312
|
+
sub?: string;
|
|
313
|
+
email?: string;
|
|
314
|
+
name?: string;
|
|
315
|
+
iss?: string;
|
|
316
|
+
aud?: string | string[];
|
|
317
|
+
exp?: number;
|
|
318
|
+
iat?: number;
|
|
319
|
+
[key: string]: unknown;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Decode a JWT token's payload without verifying the signature.
|
|
323
|
+
* Used to extract user info from id_tokens (e.g., OpenAI).
|
|
324
|
+
*/
|
|
325
|
+
declare function decodeJWT(token: string): JWTClaims;
|
|
326
|
+
//#endregion
|
|
327
|
+
export { type AuthHeaders, AuthenticationError, type AuthorizationResult, ClaudeProvider, type CredentialStatus, type DeviceCodeInfo, FileStore, KeychainStore, type LoginOptions, NoCredentialError, OAuthCallbackError, OAuthTimeoutError, OpenAICodexProvider, OpenSubAuthError, type PKCEParams, type Provider, type ProviderConfig, ProviderNotFoundError, StateMismatchError, type StoredCredential, TokenExpiredError, TokenManager, type TokenMetadata, TokenRefreshError, type TokenSet, type TokenStore, buildAuthorizationUrl, createTokenStore, decodeJWT, exchangeCode, executePKCEFlow, generateCodeChallenge, generateCodeVerifier, generatePKCE, generateState, getProvider, importFromCodexCli, listProviders, openBrowser, parseCodeAndState, promptForCode, refreshAccessToken, registerProvider, startCallbackServer };
|
|
328
|
+
//# sourceMappingURL=index.d.mts.map
|