Authentication & Credential Management
Relevant source files
The following files were used as context for generating this wiki page:
Authentication in the Resend CLI manages API keys and OAuth grants to authorize platform operations. The system supports multiple authentication profiles, environment-based keys, and secure credential storage using OS-native keychains.
The CLI resolves credentials through a specific priority hierarchy, ensuring flexible configuration for local development, CI/CD pipelines, and multi-account environments.
Sources: skills/resend-cli/SKILL.md, src/lib/config.ts
Authentication Architecture
The Resend CLI employs a multi-layered approach to resolve credentials. The system prioritizes immediate execution flags and environment variables over persisted configuration files.
Resolution Priority
The resolveAuthentication and resolveApiKey functions determine the active credential using the following order:
- Global Flags: The
--api-keyflag passed directly to a command. - Environment Variables: The
RESEND_API_KEYvariable. - Config File / Secure Storage: Stored credentials within a specific profile (e.g.,
defaultor a named profile).
The logic ensures that automated environments (like CI) can override local user settings by simply injecting an environment variable.
Sources: src/lib/config.ts:404-455, tests/lib/config.test.ts:77-100
Credential Storage Backends
The CLI supports two primary storage mechanisms for persisting credentials after a user logs in.
| Backend Type | Security | Implementation Details |
|---|---|---|
secure_storage | High | Stores tokens/keys in the OS-native keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service). The credentials.json file only contains non-secret metadata. |
file | Low | Stores keys and full OAuth grants in plaintext inside credentials.json. Used as a fallback when secure storage is unavailable or disabled. |
Sources: src/lib/config.ts:77-80, tests/lib/config-async.test.ts:98-135
Secure Storage Degradation
If a secure backend becomes unavailable despite being preferred, the CLI validates the environment and may fall back to plaintext storage. In cases where the keychain secret is missing for an OAuth grant, the CLI treats the user as unauthenticated rather than bricking the configuration.
Sources: src/lib/config.ts:399-402, src/commands/doctor.ts:223-231
Profile Management
Profiles allow users to switch between different Resend accounts or environments (e.g., production vs. staging) without re-authenticating.
Profile Attributes
- Active Profile: Defined by the
active_profilefield incredentials.json, theRESEND_PROFILEenvironment variable, or the--profileflag. - Permissions: API keys can be stored with specific permissions, such as
full_accessorsending_access. - Validation: Profile names must be 64 characters or fewer and contain only alphanumeric characters, dots, dashes, and underscores.
Sources: src/lib/config.ts:82-86, src/lib/config.ts:358-369
Renaming and Removal Logic
Renaming a profile requires atomicity. The CLI re-keys the credential in the backend (if secure) before updating the metadata in credentials.json. If deleting the old entry fails during a rename, the system rolls back the operation to prevent keychain/file disagreement.
Sources: src/lib/config.ts:553-605, tests/lib/config-async.test.ts:484-531
OAuth Grant Management
The CLI supports full OAuth grants, which include access tokens, refresh tokens, and expiry timestamps.
Grant Data Structure
export type OAuthGrantData = {
access_token: string;
access_token_expires_at: number; // unix seconds
refresh_token: string;
scope: string; // e.g. 'full_access'
};
Sources: src/lib/config.ts:58-63
Token Refresh Flow
When resolveAuthentication is called for an OAuth grant, it checks the expiry. If the access token is near expiration, the refreshOAuthGrant function attempts to exchange the refresh token for a new access token.
Security Operations
Key Masking
To prevent accidental exposure, the CLI masks API keys and tokens in standard output. The maskKey function shows the first 3 and last 4 characters, replacing the middle with ....
Sources: src/lib/config.ts:379-384
System Health (Doctor Command)
The doctor command performs a multi-step check of the authentication state:
- API Key Presence: Verifies a key is reachable from any source without performing network calls.
- Credential Storage: Reports whether the system is using a secure backend or plaintext file.
- API Validation: Exercises the key against the Resend API (e.g.,
domains.list()) to ensure the key is valid and not restricted.
Sources: src/commands/doctor.ts:182-243
Error Handling
Authentication operations can produce several specific error codes when requirements are not met.
| Error Code | Meaning |
|---|---|
auth_error | No API key found from flags, env, or config. |
profile_not_found | A specific profile was requested but does not exist in credentials.json. |
not_authenticated | Attempted to run a command that requires auth without a valid session. |
invalid_key_format | Provided API key does not follow the re_ prefix requirement. |
Sources: skills/resend-cli/references/error-codes.md, src/commands/whoami.ts:54-66
Authentication and credential management ensure that Resend CLI operations remain secure while providing developers with the flexibility to manage multiple environments through a robust profile and resolution system.