axauth 2.0.0 → 3.0.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/README.md +10 -4
- package/dist/auth/adapter.d.ts +60 -20
- package/dist/auth/agents/claude-install.d.ts +11 -0
- package/dist/auth/agents/claude-install.js +80 -0
- package/dist/auth/agents/claude-storage.d.ts +13 -5
- package/dist/auth/agents/claude-storage.js +11 -16
- package/dist/auth/agents/claude.js +14 -89
- package/dist/auth/agents/codex-auth-check.d.ts +6 -5
- package/dist/auth/agents/codex-auth-check.js +34 -20
- package/dist/auth/agents/codex-install.js +1 -2
- package/dist/auth/agents/codex-storage.d.ts +0 -1
- package/dist/auth/agents/codex-storage.js +4 -5
- package/dist/auth/agents/codex.js +4 -4
- package/dist/auth/agents/copilot-install.js +2 -3
- package/dist/auth/agents/copilot.js +11 -6
- package/dist/auth/agents/gemini-install.d.ts +1 -1
- package/dist/auth/agents/gemini-install.js +3 -3
- package/dist/auth/agents/gemini.js +19 -17
- package/dist/auth/agents/opencode-credentials.d.ts +25 -37
- package/dist/auth/agents/opencode-credentials.js +48 -122
- package/dist/auth/agents/opencode-remove-provider.d.ts +25 -0
- package/dist/auth/agents/opencode-remove-provider.js +86 -0
- package/dist/auth/agents/opencode-storage.js +18 -22
- package/dist/auth/agents/opencode.d.ts +1 -1
- package/dist/auth/agents/opencode.js +59 -41
- package/dist/auth/build-refreshed-credentials.d.ts +6 -4
- package/dist/auth/build-refreshed-credentials.js +34 -19
- package/dist/auth/extract-creds-from-directory.d.ts +7 -3
- package/dist/auth/extract-creds-from-directory.js +4 -1
- package/dist/auth/is-token-expired.d.ts +52 -2
- package/dist/auth/is-token-expired.js +71 -5
- package/dist/auth/refresh-credentials.d.ts +38 -12
- package/dist/auth/refresh-credentials.js +49 -18
- package/dist/auth/registry.d.ts +18 -15
- package/dist/auth/registry.js +35 -18
- package/dist/auth/resolve-refresh-credentials.d.ts +11 -8
- package/dist/auth/resolve-refresh-credentials.js +12 -48
- package/dist/auth/types.d.ts +3 -35
- package/dist/auth/types.js +2 -47
- package/dist/auth/wait-for-refreshed-credentials.d.ts +5 -1
- package/dist/auth/wait-for-refreshed-credentials.js +7 -4
- package/dist/commands/auth-export.js +24 -46
- package/dist/commands/auth.js +13 -3
- package/dist/commands/copy-to-clipboard.d.ts +6 -0
- package/dist/commands/copy-to-clipboard.js +48 -0
- package/dist/commands/vault.js +16 -15
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/vault/vault-client.js +21 -2
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ axauth list --json
|
|
|
38
38
|
|
|
39
39
|
# Get access token for an agent (outputs raw token for piping)
|
|
40
40
|
axauth token --agent claude
|
|
41
|
+
axauth token --agent opencode --provider anthropic # OpenCode requires --provider
|
|
41
42
|
|
|
42
43
|
# Export credentials to encrypted file
|
|
43
44
|
axauth export --agent claude --output creds.json
|
|
@@ -87,7 +88,7 @@ import {
|
|
|
87
88
|
checkAuth, // Check single agent auth status
|
|
88
89
|
checkAllAuth, // Check all agents' auth status
|
|
89
90
|
getAgentAccessToken, // Get access token for an agent
|
|
90
|
-
|
|
91
|
+
findCredentials, // Find credentials from storage or environment
|
|
91
92
|
installCredentials, // Install credentials to storage
|
|
92
93
|
removeCredentials, // Remove credentials from storage
|
|
93
94
|
|
|
@@ -125,11 +126,16 @@ if (status.authenticated) {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
// Get access token for API calls
|
|
128
|
-
const token = getAgentAccessToken("claude");
|
|
129
|
+
const token = await getAgentAccessToken("claude");
|
|
129
130
|
if (token) {
|
|
130
131
|
// Use token for API calls
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
// OpenCode requires explicit provider (multi-provider agent)
|
|
135
|
+
const openCodeToken = await getAgentAccessToken("opencode", {
|
|
136
|
+
provider: "anthropic",
|
|
137
|
+
});
|
|
138
|
+
|
|
133
139
|
// Check adapter capabilities
|
|
134
140
|
const caps = getCapabilities("gemini");
|
|
135
141
|
if (!caps.keychain) {
|
|
@@ -146,9 +152,9 @@ import { getAdapter } from "axauth";
|
|
|
146
152
|
|
|
147
153
|
const adapter = getAdapter("claude");
|
|
148
154
|
|
|
149
|
-
// All adapters have the same interface
|
|
155
|
+
// All adapters have the same interface (OpenCode requires { provider } option)
|
|
150
156
|
const status = adapter.checkAuth();
|
|
151
|
-
const creds = adapter.
|
|
157
|
+
const creds = adapter.findStoredCredentials(); // OpenCode: findStoredCredentials({ provider: "anthropic" })
|
|
152
158
|
const token = adapter.getAccessToken(creds);
|
|
153
159
|
const envVars = adapter.credentialsToEnvironment(creds);
|
|
154
160
|
|
package/dist/auth/adapter.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ interface OperationResult {
|
|
|
13
13
|
ok: boolean;
|
|
14
14
|
message: string;
|
|
15
15
|
}
|
|
16
|
+
/** Result of finding stored credentials */
|
|
17
|
+
interface StoredCredentials {
|
|
18
|
+
credentials: Credentials;
|
|
19
|
+
source: "keychain" | "file";
|
|
20
|
+
}
|
|
16
21
|
/**
|
|
17
22
|
* Options for credential installation.
|
|
18
23
|
*
|
|
@@ -22,7 +27,7 @@ interface OperationResult {
|
|
|
22
27
|
* When no directories are provided, `storage` controls where credentials go:
|
|
23
28
|
* - `"keychain"`: Store in macOS Keychain (if supported)
|
|
24
29
|
* - `"file"`: Store in agent's default file location
|
|
25
|
-
* - `undefined`:
|
|
30
|
+
* - `undefined`: Default to file storage
|
|
26
31
|
*
|
|
27
32
|
* **Agents without separation** (Claude, Codex, Gemini, Copilot):
|
|
28
33
|
* - Config and data are stored in the same directory
|
|
@@ -36,7 +41,11 @@ interface OperationResult {
|
|
|
36
41
|
* - If only `dataDir` provided, config uses default location
|
|
37
42
|
*/
|
|
38
43
|
interface InstallOptions {
|
|
39
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Storage type for default location.
|
|
46
|
+
* Required when re-installing refreshed credentials to preserve original location.
|
|
47
|
+
* Ignored if configDir/dataDir is set.
|
|
48
|
+
*/
|
|
40
49
|
storage?: StorageType;
|
|
41
50
|
/** Custom config directory for settings/preferences */
|
|
42
51
|
configDir?: string;
|
|
@@ -65,7 +74,21 @@ interface RemoveOptions {
|
|
|
65
74
|
dataDir?: string;
|
|
66
75
|
}
|
|
67
76
|
/**
|
|
68
|
-
* Options for
|
|
77
|
+
* Options for finding stored credentials.
|
|
78
|
+
*
|
|
79
|
+
* **Multi-provider agents** (OpenCode):
|
|
80
|
+
* - `provider` is required to specify which provider's credentials to return
|
|
81
|
+
* - Throws an error if provider is not specified
|
|
82
|
+
*
|
|
83
|
+
* **Single-provider agents** (Claude, Codex, Gemini, Copilot):
|
|
84
|
+
* - `provider` is ignored
|
|
85
|
+
*/
|
|
86
|
+
interface FindStoredCredentialsOptions {
|
|
87
|
+
/** Provider ID for multi-provider agents (required for OpenCode) */
|
|
88
|
+
provider?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Options for loading credentials from a custom directory.
|
|
69
92
|
*
|
|
70
93
|
* **Agents without separation** (Claude, Codex, Gemini, Copilot):
|
|
71
94
|
* - `configDir` and `dataDir` are interchangeable
|
|
@@ -73,13 +96,16 @@ interface RemoveOptions {
|
|
|
73
96
|
*
|
|
74
97
|
* **Agents with separation** (OpenCode):
|
|
75
98
|
* - `dataDir` must be provided to specify where credentials are stored
|
|
76
|
-
* - If only `configDir` is provided, returns undefined (use
|
|
99
|
+
* - If only `configDir` is provided, returns undefined (use findStoredCredentials() for default location)
|
|
100
|
+
* - `provider` filters to a specific provider's credentials
|
|
77
101
|
*/
|
|
78
102
|
interface ExtractOptions {
|
|
79
103
|
/** Custom config directory for settings/preferences */
|
|
80
104
|
configDir?: string;
|
|
81
105
|
/** Custom data directory for credentials */
|
|
82
106
|
dataDir?: string;
|
|
107
|
+
/** Provider ID for multi-provider agents (OpenCode) - filters to specific provider */
|
|
108
|
+
provider?: string;
|
|
83
109
|
}
|
|
84
110
|
/**
|
|
85
111
|
* Options for token extraction.
|
|
@@ -94,6 +120,8 @@ interface TokenOptions {
|
|
|
94
120
|
skipRefresh?: boolean;
|
|
95
121
|
/** Timeout for refresh operation in ms (default: 30000) */
|
|
96
122
|
refreshTimeout?: number;
|
|
123
|
+
/** Storage location for persisting refreshed credentials (default: "file") */
|
|
124
|
+
storage?: "keychain" | "file";
|
|
97
125
|
}
|
|
98
126
|
/** Capabilities that an adapter supports */
|
|
99
127
|
interface AdapterCapabilities {
|
|
@@ -116,9 +144,9 @@ interface AdapterCapabilities {
|
|
|
116
144
|
*
|
|
117
145
|
* When resolving credentials, sources are checked in this order:
|
|
118
146
|
*
|
|
119
|
-
* 1. **Environment variables** (via `
|
|
147
|
+
* 1. **Environment variables** (via `getEnvironmentCredentials`)
|
|
120
148
|
* 2. **Vault** (external, via axvault server when configured)
|
|
121
|
-
* 3. **Local storage** (keychain/file via `
|
|
149
|
+
* 3. **Local storage** (keychain/file via `findStoredCredentials`)
|
|
122
150
|
*
|
|
123
151
|
* Environment variables always take precedence to allow easy overrides
|
|
124
152
|
* in CI/CD and development. Vault provides centralized credential
|
|
@@ -137,7 +165,7 @@ interface AuthAdapter {
|
|
|
137
165
|
*/
|
|
138
166
|
checkAuth(): AuthStatus;
|
|
139
167
|
/**
|
|
140
|
-
*
|
|
168
|
+
* Get credentials from environment variables only.
|
|
141
169
|
*
|
|
142
170
|
* This is called before checking vault or local storage to ensure
|
|
143
171
|
* environment variables have highest priority. Returns undefined if
|
|
@@ -145,22 +173,33 @@ interface AuthAdapter {
|
|
|
145
173
|
*
|
|
146
174
|
* @example
|
|
147
175
|
* // For Claude, checks CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY
|
|
148
|
-
* const envCreds = adapter.
|
|
176
|
+
* const envCreds = adapter.getEnvironmentCredentials?.();
|
|
149
177
|
* if (envCreds) return envCreds; // Env vars win over vault
|
|
150
178
|
*/
|
|
151
|
-
|
|
179
|
+
getEnvironmentCredentials?(): Credentials | undefined;
|
|
152
180
|
/**
|
|
153
|
-
*
|
|
181
|
+
* Find stored credentials and their source.
|
|
182
|
+
*
|
|
183
|
+
* Returns the full credential data from the first available storage location
|
|
184
|
+
* (keychain or file), along with the source it was found in. Returns undefined
|
|
185
|
+
* if not authenticated. Does not check environment variables.
|
|
186
|
+
*
|
|
187
|
+
* The returned `source` should be passed to `installCredentials()` when
|
|
188
|
+
* re-installing refreshed credentials to preserve the original storage location.
|
|
189
|
+
*
|
|
190
|
+
* **Multi-provider agents** (OpenCode):
|
|
191
|
+
* - `options.provider` is required - throws if not specified
|
|
192
|
+
* - Returns credentials for the specified provider only
|
|
154
193
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
194
|
+
* **Single-provider agents** (Claude, Codex, Gemini, Copilot):
|
|
195
|
+
* - `options` is ignored
|
|
157
196
|
*
|
|
158
197
|
* Note: The `data` field format is agent-specific and not standardized.
|
|
159
198
|
* Use {@link getAccessToken} to extract the token in a uniform way.
|
|
160
199
|
*/
|
|
161
|
-
|
|
200
|
+
findStoredCredentials(options?: FindStoredCredentialsOptions): StoredCredentials | undefined;
|
|
162
201
|
/**
|
|
163
|
-
*
|
|
202
|
+
* Load credentials from a custom directory.
|
|
164
203
|
*
|
|
165
204
|
* Used by token refresh and CI/CD to read credentials from temp directories.
|
|
166
205
|
* Returns undefined if no credentials found at the specified location.
|
|
@@ -168,15 +207,16 @@ interface AuthAdapter {
|
|
|
168
207
|
* **Agents without separation**: Look in `configDir` or `dataDir` (interchangeable)
|
|
169
208
|
* **Agents with separation** (OpenCode): Look in `dataDir` for credentials
|
|
170
209
|
*/
|
|
171
|
-
|
|
210
|
+
loadCredentialsFromDirectory?(options: ExtractOptions): Credentials | undefined;
|
|
172
211
|
/**
|
|
173
212
|
* Install credentials to storage.
|
|
174
213
|
*
|
|
175
|
-
* When `options.
|
|
176
|
-
*
|
|
214
|
+
* When `options.configDir`/`options.dataDir` is provided, credentials are
|
|
215
|
+
* written as a file to that directory. Keychain storage is not available for
|
|
216
|
+
* custom paths.
|
|
177
217
|
*
|
|
178
|
-
* When
|
|
179
|
-
* location. The `storage` option
|
|
218
|
+
* When no directories are provided, credentials are written to the default
|
|
219
|
+
* location. The `storage` option controls keychain vs file (defaults to file).
|
|
180
220
|
*/
|
|
181
221
|
installCredentials(creds: Credentials, options?: InstallOptions): OperationResult;
|
|
182
222
|
/**
|
|
@@ -219,4 +259,4 @@ interface AuthAdapter {
|
|
|
219
259
|
*/
|
|
220
260
|
getCredentialFilePath(directory: string): string;
|
|
221
261
|
}
|
|
222
|
-
export type { AdapterCapabilities, AuthAdapter, ExtractOptions, InstallOptions, OperationResult, RemoveOptions, TokenOptions, };
|
|
262
|
+
export type { AdapterCapabilities, AuthAdapter, ExtractOptions, FindStoredCredentialsOptions, InstallOptions, OperationResult, RemoveOptions, StoredCredentials, TokenOptions, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code credential installation and removal.
|
|
3
|
+
*/
|
|
4
|
+
import type { InstallOptions, OperationResult, RemoveOptions } from "../adapter.js";
|
|
5
|
+
import type { Credentials } from "../types.js";
|
|
6
|
+
declare const CREDS_FILE_NAME = ".credentials.json";
|
|
7
|
+
/** Install credentials to storage */
|
|
8
|
+
declare function installCredentials(creds: Credentials, options?: InstallOptions): OperationResult;
|
|
9
|
+
/** Remove credentials from storage */
|
|
10
|
+
declare function removeCredentials(options?: RemoveOptions): OperationResult;
|
|
11
|
+
export { CREDS_FILE_NAME, installCredentials, removeCredentials };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code credential installation and removal.
|
|
3
|
+
*/
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { isMacOS } from "../keychain.js";
|
|
6
|
+
import { resolveCustomDirectory } from "../validate-directories.js";
|
|
7
|
+
import { AGENT_ID, deleteFileCreds, deleteKeychainCreds, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, } from "./claude-storage.js";
|
|
8
|
+
const CREDS_FILE_NAME = ".credentials.json";
|
|
9
|
+
/** Install credentials to storage */
|
|
10
|
+
function installCredentials(creds, options) {
|
|
11
|
+
const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
|
|
12
|
+
if (!resolved.ok)
|
|
13
|
+
return resolved.error;
|
|
14
|
+
if (creds.type === "api-key") {
|
|
15
|
+
return {
|
|
16
|
+
ok: false,
|
|
17
|
+
message: "API key credentials cannot be installed (use ANTHROPIC_API_KEY env var)",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// Custom directory forces file storage (keychain only for default location)
|
|
21
|
+
if (resolved.customDir) {
|
|
22
|
+
const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
|
|
23
|
+
if (saveFileCreds(creds.data, targetPath)) {
|
|
24
|
+
return { ok: true, message: `Installed credentials to ${targetPath}` };
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
ok: false,
|
|
28
|
+
message: `Failed to install credentials to ${targetPath}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Default location: use storage option or default to file
|
|
32
|
+
const targetStorage = options?.storage ?? "file";
|
|
33
|
+
if (targetStorage === "keychain") {
|
|
34
|
+
if (!isMacOS()) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
message: "Keychain storage is only available on macOS",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (saveKeychainCreds(creds.data)) {
|
|
41
|
+
return { ok: true, message: "Installed credentials to macOS Keychain" };
|
|
42
|
+
}
|
|
43
|
+
return { ok: false, message: "Failed to save to macOS Keychain" };
|
|
44
|
+
}
|
|
45
|
+
const defaultPath = getDefaultCredsFilePath();
|
|
46
|
+
if (saveFileCreds(creds.data, defaultPath)) {
|
|
47
|
+
return { ok: true, message: `Installed credentials to ${defaultPath}` };
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
message: `Failed to install credentials to ${defaultPath}`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Remove credentials from storage */
|
|
55
|
+
function removeCredentials(options) {
|
|
56
|
+
const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
|
|
57
|
+
if (!resolved.ok)
|
|
58
|
+
return resolved.error;
|
|
59
|
+
// Custom directory: only remove that specific file (no keychain)
|
|
60
|
+
if (resolved.customDir) {
|
|
61
|
+
const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
|
|
62
|
+
if (deleteFileCreds(targetPath)) {
|
|
63
|
+
return { ok: true, message: `Removed ${targetPath}` };
|
|
64
|
+
}
|
|
65
|
+
return { ok: true, message: "No credentials file found at specified path" };
|
|
66
|
+
}
|
|
67
|
+
// Default location: remove from both keychain and default file
|
|
68
|
+
const removedFrom = [];
|
|
69
|
+
if (deleteKeychainCreds()) {
|
|
70
|
+
removedFrom.push("macOS Keychain");
|
|
71
|
+
}
|
|
72
|
+
if (deleteFileCreds()) {
|
|
73
|
+
removedFrom.push(getDefaultCredsFilePath());
|
|
74
|
+
}
|
|
75
|
+
if (removedFrom.length === 0) {
|
|
76
|
+
return { ok: true, message: "No credentials found" };
|
|
77
|
+
}
|
|
78
|
+
return { ok: true, message: `Removed from ${removedFrom.join(" and ")}` };
|
|
79
|
+
}
|
|
80
|
+
export { CREDS_FILE_NAME, installCredentials, removeCredentials };
|
|
@@ -19,18 +19,26 @@ declare function checkAuth(): {
|
|
|
19
19
|
details?: Record<string, unknown>;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Get credentials from environment variables only.
|
|
23
23
|
*
|
|
24
24
|
* This is called before checking vault or local storage to ensure
|
|
25
25
|
* environment variables have highest priority.
|
|
26
26
|
*/
|
|
27
|
-
declare function
|
|
27
|
+
declare function getEnvironmentCredentials(): {
|
|
28
28
|
type: "oauth-credentials" | "oauth-token" | "api-key";
|
|
29
29
|
data: Record<string, unknown>;
|
|
30
30
|
} | undefined;
|
|
31
|
-
/**
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Find credentials from local storage only (keychain + file).
|
|
33
|
+
*
|
|
34
|
+
* This skips environment variable checks and only looks at local storage.
|
|
35
|
+
* Used as fallback after vault fetch fails.
|
|
36
|
+
*
|
|
37
|
+
* Returns credentials and their source for round-tripping during refresh.
|
|
38
|
+
*/
|
|
39
|
+
declare function findStoredCredentials(): {
|
|
33
40
|
type: "oauth-credentials" | "oauth-token" | "api-key";
|
|
41
|
+
source: "keychain" | "file";
|
|
34
42
|
data: Record<string, unknown>;
|
|
35
43
|
} | undefined;
|
|
36
|
-
export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds,
|
|
44
|
+
export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, findStoredCredentials, getDefaultCredsFilePath, getEnvironmentCredentials, saveFileCreds, saveKeychainCreds, };
|
|
@@ -82,12 +82,12 @@ function checkAuth() {
|
|
|
82
82
|
return { authenticated: false };
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
85
|
+
* Get credentials from environment variables only.
|
|
86
86
|
*
|
|
87
87
|
* This is called before checking vault or local storage to ensure
|
|
88
88
|
* environment variables have highest priority.
|
|
89
89
|
*/
|
|
90
|
-
function
|
|
90
|
+
function getEnvironmentCredentials() {
|
|
91
91
|
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
92
92
|
return {
|
|
93
93
|
type: "oauth-token",
|
|
@@ -103,35 +103,30 @@ function extractFromEnvironment() {
|
|
|
103
103
|
return undefined;
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
106
|
+
* Find credentials from local storage only (keychain + file).
|
|
107
107
|
*
|
|
108
108
|
* This skips environment variable checks and only looks at local storage.
|
|
109
109
|
* Used as fallback after vault fetch fails.
|
|
110
|
+
*
|
|
111
|
+
* Returns credentials and their source for round-tripping during refresh.
|
|
110
112
|
*/
|
|
111
|
-
function
|
|
113
|
+
function findStoredCredentials() {
|
|
112
114
|
const keychainCreds = loadKeychainCreds();
|
|
113
115
|
if (keychainCreds) {
|
|
114
116
|
return {
|
|
115
117
|
type: "oauth-credentials",
|
|
116
|
-
|
|
118
|
+
source: "keychain",
|
|
119
|
+
data: keychainCreds,
|
|
117
120
|
};
|
|
118
121
|
}
|
|
119
122
|
const fileCreds = loadFileCreds();
|
|
120
123
|
if (fileCreds) {
|
|
121
124
|
return {
|
|
122
125
|
type: "oauth-credentials",
|
|
123
|
-
|
|
126
|
+
source: "file",
|
|
127
|
+
data: fileCreds,
|
|
124
128
|
};
|
|
125
129
|
}
|
|
126
130
|
return undefined;
|
|
127
131
|
}
|
|
128
|
-
|
|
129
|
-
function extractRawCredentials() {
|
|
130
|
-
// Check env vars first
|
|
131
|
-
const environmentCreds = extractFromEnvironment();
|
|
132
|
-
if (environmentCreds)
|
|
133
|
-
return environmentCreds;
|
|
134
|
-
// Fall back to local storage
|
|
135
|
-
return extractFromLocalStorage();
|
|
136
|
-
}
|
|
137
|
-
export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, extractFromEnvironment, extractRawCredentials, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, };
|
|
132
|
+
export { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, findStoredCredentials, getDefaultCredsFilePath, getEnvironmentCredentials, saveFileCreds, saveKeychainCreds, };
|
|
@@ -5,10 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { extractCredsFromDirectory } from "../extract-creds-from-directory.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { AGENT_ID, checkAuth, deleteFileCreds, deleteKeychainCreds, extractFromEnvironment, extractRawCredentials, getDefaultCredsFilePath, saveFileCreds, saveKeychainCreds, } from "./claude-storage.js";
|
|
11
|
-
const CREDS_FILE_NAME = ".credentials.json";
|
|
8
|
+
import { CREDS_FILE_NAME, installCredentials, removeCredentials, } from "./claude-install.js";
|
|
9
|
+
import { AGENT_ID, checkAuth, findStoredCredentials as findStoredCredentialsInternal, getEnvironmentCredentials as getEnvironmentCredentialsInternal, } from "./claude-storage.js";
|
|
12
10
|
/** Claude Code authentication adapter */
|
|
13
11
|
const claudeCodeAdapter = {
|
|
14
12
|
agentId: AGENT_ID,
|
|
@@ -22,19 +20,22 @@ const claudeCodeAdapter = {
|
|
|
22
20
|
const result = checkAuth();
|
|
23
21
|
return { agentId: AGENT_ID, ...result };
|
|
24
22
|
},
|
|
25
|
-
|
|
26
|
-
const result =
|
|
23
|
+
getEnvironmentCredentials() {
|
|
24
|
+
const result = getEnvironmentCredentialsInternal();
|
|
27
25
|
if (!result)
|
|
28
26
|
return undefined;
|
|
29
|
-
return { agent: AGENT_ID,
|
|
27
|
+
return { agent: AGENT_ID, type: result.type, data: result.data };
|
|
30
28
|
},
|
|
31
|
-
|
|
32
|
-
const result =
|
|
29
|
+
findStoredCredentials() {
|
|
30
|
+
const result = findStoredCredentialsInternal();
|
|
33
31
|
if (!result)
|
|
34
32
|
return undefined;
|
|
35
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
credentials: { agent: AGENT_ID, type: result.type, data: result.data },
|
|
35
|
+
source: result.source,
|
|
36
|
+
};
|
|
36
37
|
},
|
|
37
|
-
|
|
38
|
+
loadCredentialsFromDirectory(options) {
|
|
38
39
|
// Claude doesn't separate config/data - use either directory
|
|
39
40
|
const directory = options.dataDir ?? options.configDir;
|
|
40
41
|
if (!directory)
|
|
@@ -47,84 +48,8 @@ const claudeCodeAdapter = {
|
|
|
47
48
|
: undefined;
|
|
48
49
|
});
|
|
49
50
|
},
|
|
50
|
-
installCredentials
|
|
51
|
-
|
|
52
|
-
const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
|
|
53
|
-
if (!resolved.ok)
|
|
54
|
-
return resolved.error;
|
|
55
|
-
if (creds.type === "api-key") {
|
|
56
|
-
return {
|
|
57
|
-
ok: false,
|
|
58
|
-
message: "API key credentials cannot be installed (use ANTHROPIC_API_KEY env var)",
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
const { _source, ...oauthData } = creds.data;
|
|
62
|
-
// Custom directory forces file storage (keychain only for default location)
|
|
63
|
-
if (resolved.customDir) {
|
|
64
|
-
const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
|
|
65
|
-
if (saveFileCreds(oauthData, targetPath)) {
|
|
66
|
-
return {
|
|
67
|
-
ok: true,
|
|
68
|
-
message: `Installed credentials to ${targetPath}`,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
ok: false,
|
|
73
|
-
message: `Failed to install credentials to ${targetPath}`,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
// Default location: use storage option or _source marker
|
|
77
|
-
const targetStorage = options?.storage ?? (_source === "keychain" ? "keychain" : "file");
|
|
78
|
-
if (targetStorage === "keychain") {
|
|
79
|
-
if (!isMacOS()) {
|
|
80
|
-
return {
|
|
81
|
-
ok: false,
|
|
82
|
-
message: "Keychain storage is only available on macOS",
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
if (saveKeychainCreds(oauthData)) {
|
|
86
|
-
return { ok: true, message: "Installed credentials to macOS Keychain" };
|
|
87
|
-
}
|
|
88
|
-
return { ok: false, message: "Failed to save to macOS Keychain" };
|
|
89
|
-
}
|
|
90
|
-
const defaultPath = getDefaultCredsFilePath();
|
|
91
|
-
if (saveFileCreds(oauthData, defaultPath)) {
|
|
92
|
-
return { ok: true, message: `Installed credentials to ${defaultPath}` };
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
ok: false,
|
|
96
|
-
message: `Failed to install credentials to ${defaultPath}`,
|
|
97
|
-
};
|
|
98
|
-
},
|
|
99
|
-
removeCredentials(options) {
|
|
100
|
-
// Resolve custom directory with validation
|
|
101
|
-
const resolved = resolveCustomDirectory(AGENT_ID, options?.configDir, options?.dataDir);
|
|
102
|
-
if (!resolved.ok)
|
|
103
|
-
return resolved.error;
|
|
104
|
-
// Custom directory: only remove that specific file (no keychain)
|
|
105
|
-
if (resolved.customDir) {
|
|
106
|
-
const targetPath = path.join(resolved.customDir, CREDS_FILE_NAME);
|
|
107
|
-
if (deleteFileCreds(targetPath)) {
|
|
108
|
-
return { ok: true, message: `Removed ${targetPath}` };
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
ok: true,
|
|
112
|
-
message: "No credentials file found at specified path",
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
// Default location: remove from both keychain and default file
|
|
116
|
-
const removedFrom = [];
|
|
117
|
-
if (deleteKeychainCreds()) {
|
|
118
|
-
removedFrom.push("macOS Keychain");
|
|
119
|
-
}
|
|
120
|
-
if (deleteFileCreds()) {
|
|
121
|
-
removedFrom.push(getDefaultCredsFilePath());
|
|
122
|
-
}
|
|
123
|
-
if (removedFrom.length === 0) {
|
|
124
|
-
return { ok: true, message: "No credentials found" };
|
|
125
|
-
}
|
|
126
|
-
return { ok: true, message: `Removed from ${removedFrom.join(" and ")}` };
|
|
127
|
-
},
|
|
51
|
+
installCredentials,
|
|
52
|
+
removeCredentials,
|
|
128
53
|
getAccessToken(creds) {
|
|
129
54
|
const data = creds.data;
|
|
130
55
|
if ((creds.type === "oauth-credentials" || creds.type === "oauth-token") &&
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Codex auth status checking and credential extraction.
|
|
3
3
|
*/
|
|
4
|
+
import type { StoredCredentials } from "../adapter.js";
|
|
4
5
|
import type { AuthStatus, Credentials } from "../types.js";
|
|
5
6
|
/** Check auth status across all sources */
|
|
6
7
|
declare function checkAuth(): AuthStatus;
|
|
7
|
-
/**
|
|
8
|
-
declare function
|
|
9
|
-
/**
|
|
10
|
-
declare function
|
|
11
|
-
export { checkAuth,
|
|
8
|
+
/** Get credentials from environment variables */
|
|
9
|
+
declare function getEnvironmentCredentials(): Credentials | undefined;
|
|
10
|
+
/** Find stored credentials from keychain or file */
|
|
11
|
+
declare function findStoredCredentials(): StoredCredentials | undefined;
|
|
12
|
+
export { checkAuth, findStoredCredentials, getEnvironmentCredentials };
|
|
@@ -46,8 +46,8 @@ function checkAuth() {
|
|
|
46
46
|
checkKeychainAuth() ??
|
|
47
47
|
checkFileAuth() ?? { agentId: AGENT_ID, authenticated: false });
|
|
48
48
|
}
|
|
49
|
-
/**
|
|
50
|
-
function
|
|
49
|
+
/** Get credentials from environment variables */
|
|
50
|
+
function getEnvironmentCredentials() {
|
|
51
51
|
const environmentKey = getEnvironmentApiKey();
|
|
52
52
|
if (environmentKey) {
|
|
53
53
|
return {
|
|
@@ -58,44 +58,58 @@ function extractEnvironmentCredentials() {
|
|
|
58
58
|
}
|
|
59
59
|
return undefined;
|
|
60
60
|
}
|
|
61
|
-
/** Extract credentials from keychain */
|
|
61
|
+
/** Extract credentials from keychain (internal, returns source) */
|
|
62
62
|
function extractKeychainCredentials() {
|
|
63
63
|
const keychainAuth = loadKeychainCreds();
|
|
64
64
|
if (keychainAuth?.OPENAI_API_KEY) {
|
|
65
65
|
return {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
credentials: {
|
|
67
|
+
agent: AGENT_ID,
|
|
68
|
+
type: "api-key",
|
|
69
|
+
data: { apiKey: keychainAuth.OPENAI_API_KEY },
|
|
70
|
+
},
|
|
71
|
+
source: "keychain",
|
|
69
72
|
};
|
|
70
73
|
}
|
|
71
74
|
if (keychainAuth?.tokens) {
|
|
72
75
|
return {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
credentials: {
|
|
77
|
+
agent: AGENT_ID,
|
|
78
|
+
type: "oauth-credentials",
|
|
79
|
+
data: keychainAuth,
|
|
80
|
+
},
|
|
81
|
+
source: "keychain",
|
|
76
82
|
};
|
|
77
83
|
}
|
|
78
84
|
return undefined;
|
|
79
85
|
}
|
|
80
|
-
/** Extract credentials from file */
|
|
86
|
+
/** Extract credentials from file (internal, returns source) */
|
|
81
87
|
function extractFileCredentials() {
|
|
82
88
|
const fileAuth = loadFileCreds();
|
|
83
89
|
if (fileAuth?.OPENAI_API_KEY) {
|
|
84
90
|
return {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
credentials: {
|
|
92
|
+
agent: AGENT_ID,
|
|
93
|
+
type: "api-key",
|
|
94
|
+
data: { apiKey: fileAuth.OPENAI_API_KEY },
|
|
95
|
+
},
|
|
96
|
+
source: "file",
|
|
88
97
|
};
|
|
89
98
|
}
|
|
90
99
|
if (fileAuth?.tokens) {
|
|
91
|
-
return {
|
|
100
|
+
return {
|
|
101
|
+
credentials: {
|
|
102
|
+
agent: AGENT_ID,
|
|
103
|
+
type: "oauth-credentials",
|
|
104
|
+
data: fileAuth,
|
|
105
|
+
},
|
|
106
|
+
source: "file",
|
|
107
|
+
};
|
|
92
108
|
}
|
|
93
109
|
return undefined;
|
|
94
110
|
}
|
|
95
|
-
/**
|
|
96
|
-
function
|
|
97
|
-
return (
|
|
98
|
-
extractKeychainCredentials() ??
|
|
99
|
-
extractFileCredentials());
|
|
111
|
+
/** Find stored credentials from keychain or file */
|
|
112
|
+
function findStoredCredentials() {
|
|
113
|
+
return extractKeychainCredentials() ?? extractFileCredentials();
|
|
100
114
|
}
|
|
101
|
-
export { checkAuth,
|
|
115
|
+
export { checkAuth, findStoredCredentials, getEnvironmentCredentials };
|
|
@@ -65,8 +65,7 @@ function installCodexCredentials(creds, options) {
|
|
|
65
65
|
if (resolved.customDir) {
|
|
66
66
|
return installToCustomDirectory(authContent, resolved.customDir);
|
|
67
67
|
}
|
|
68
|
-
const
|
|
69
|
-
const targetStorage = options?.storage ?? (sourceMarker === "keychain" ? "keychain" : "file");
|
|
68
|
+
const targetStorage = options?.storage ?? "file";
|
|
70
69
|
return installToDefaultLocation(authContent, targetStorage);
|
|
71
70
|
}
|
|
72
71
|
/** Remove Codex credentials */
|
|
@@ -34,7 +34,6 @@ declare function saveFileCreds(auth: CodexAuthJson, filePath?: string): boolean;
|
|
|
34
34
|
declare function deleteFileCreds(filePath?: string): boolean;
|
|
35
35
|
interface CredentialsData {
|
|
36
36
|
apiKey?: string;
|
|
37
|
-
_source?: unknown;
|
|
38
37
|
tokens?: CodexAuthJson["tokens"];
|
|
39
38
|
[key: string]: unknown;
|
|
40
39
|
}
|