API Key Management
Relevant source files
The following files were used as context for generating this wiki page:
The API Key Management system allows users to configure their own Large Language Model (LLM) provider API keys to power the resume enhancement features. The system is designed with a dual-mode architecture to support both authenticated users ("Full Mode") and guest users ("Light Mode"). In Full Mode, keys are securely encrypted and stored in the database, associated with the user's account. In Light Mode, keys are stored locally in the user's browser storage, offering a quick, no-login-required experience.
This system is crucial for enabling AI-powered enhancements, as it provides the necessary credentials to interact with external AI services like OpenAI, Anthropic, and Google Gemini. The management interface allows users to add, view, and delete their keys, ensuring they have full control over their credentials.
Sources: README.md:103-107, api-keys-light/page.tsx:102-106
Architecture Overview
The API Key Management feature operates in two distinct modes depending on the user's authentication status.
- Full Mode: For authenticated users. API keys are encrypted and stored in the PostgreSQL database. This provides persistence and security.
- Light Mode: For unauthenticated users. API keys are stored directly in the browser's
localStorage. This is less secure and non-persistent across devices but allows for immediate use without an account.
The diagram below illustrates the high-level architecture for both modes.
Full Mode (Authenticated Users)
Full Mode is available to users who have signed in. It offers a secure and persistent way to manage API keys.
Sources: api-keys/page.tsx:7-11
UI Components
The user interface for managing API keys in Full Mode is handled by the ApiKeyManager component, which is rendered on the /api-keys page.
api-keys/page.tsx: This is the main page route. It performs a server-side check for an active user session. If the user is not authenticated, they are redirected to the sign-in page.api-keys/_components/api-key-manager.tsx: This client-side component is responsible for all user interactions:- Fetching and displaying a list of the user's saved API keys.
- Providing a dialog form to add a new API key. The form includes fields for Provider, Key Name, the API Key itself, and the Default Model to use.
- Handling the deletion of existing API keys.
- Displaying the list of supported providers and links to get API keys.
The component interacts with the backend via API calls to /api/api-keys.
Sources: api-keys/page.tsx:7-11, api-keys/_components/api-key-manager.tsx
Backend API
The backend logic is handled by a set of API routes. All endpoints require an authenticated user session.
| Method | Endpoint | Description |
|---|---|---|
GET | /api/api-keys | Fetches all API keys for the authenticated user, excluding the encrypted key value. |
POST | /api/api-keys | Adds a new API key for the user. It encrypts the key before saving it to the database. |
DELETE | /api/api-keys/[id] | Deletes a specific API key by its ID. |
Sources: api/api-keys/route.ts, api/api-keys/[id]/route.ts
POST /api/api-keys
This endpoint creates a new API key. It validates that a user does not already have a key for the selected provider to prevent duplicates.
Request Body:
| Parameter | Type | Description |
|---|---|---|
provider | string | The AI provider (e.g., 'openai'). |
keyName | string | A user-defined name for the key. |
apiKey | string | The actual API key. |
defaultModel | string | The default model to use for this provider. |
Sources: api/api-keys/route.ts:60-64
The following sequence diagram shows the flow for adding a new API key.
Sources: api/api-keys/route.ts:54-120
Data Storage and Security
API keys for authenticated users are stored in the UserApiKey table in the database.
Database Schema
The UserApiKey model has a unique constraint on the combination of userId and provider.
This diagram shows the relationship between the User and UserApiKey tables.
Sources: schema.prisma:93-106
UserApiKey Table Schema:
| Field | Type | Description |
|---|---|---|
id | String | Unique identifier (CUID). |
userId | String | Foreign key linking to the User table. |
provider | String | The AI provider (openai, anthropic, gemini). |
keyName | String | A user-friendly name for the key. |
encryptedKey | String | The encrypted API key. |
defaultModel | String | The default model to use for this provider (e.g., gpt-4o-mini). |
isActive | Boolean | Indicates if the key is the active one for the user. |
Sources: schema.prisma:93-106
Encryption
To enhance security, API keys are never stored in plain text. The lib/crypto.ts utility provides functions to encrypt and decrypt keys using the AES-256-GCM algorithm.
encryptApiKey(apiKey): This function is called by thePOST /api/api-keysendpoint before saving a key to the database. It uses anENCRYPTION_KEYdefined as a 32-character environment variable.decryptApiKey(encryptedKey): This function is used when an API key is needed to make a request to an AI provider, for example, in the/api/enhance-resume/[id]route.
Sources: lib/crypto.ts, api/api-keys/route.ts:88-89, api/enhance-resume/[id]/route.ts:202
Light Mode (Unauthenticated Users)
Light Mode provides a way for users to try the application without creating an account. API keys are managed entirely on the client side.
Sources: page.tsx:61-63, api-keys-light/page.tsx
UI and Logic
The UI is located at /api-keys-light and is implemented in api-keys-light/page.tsx. It is similar to the Full Mode manager but with a key difference: all operations interact with the browser's localStorage instead of a backend API.
An alert on the page explicitly warns the user that keys are stored in their browser and will be lost if browser data is cleared.
Sources: api-keys-light/page.tsx:102-106
Local Storage Management
The lib/api-key-storage.ts file provides the localApiKeyStorage object, which is a wrapper around the localStorage API for managing API keys.
save(provider, keyName, apiKey): Saves a new API key tolocalStorage.getAll(): Retrieves all saved API keys fromlocalStorage.delete(id): Removes a specific API key fromlocalStorage.
The keys are stored as a JSON string under the key guc_local_api_keys.
The following flowchart illustrates the process of adding a key in Light Mode.
API Key Usage
The primary purpose of storing API keys is to use them for resume enhancement. The /api/enhance-resume/[id] endpoint demonstrates this usage.
The process is as follows:
- The endpoint retrieves the authenticated user's session.
- It finds the
UserApiKeyrecord marked asisActive: truefor that user. - If a key is found, it calls
decryptApiKey()to get the plain-text key. - The decrypted key is then used in the
Authorizationheader of the request to the corresponding AI provider (OpenAI, Anthropic, or Gemini).
This ensures that the user's own key is used for the AI-powered operation, and the key is only decrypted at the moment it is needed.
The sequence diagram below shows this flow.
Summary
The API Key Management system in GUC-Resume-Enhancer is a flexible feature that caters to both registered and guest users. For registered users, it provides a secure, persistent storage solution by encrypting keys and saving them to the database. For guest users, it offers a convenient, client-only solution using localStorage. This dual-mode approach lowers the barrier to entry while providing a robust solution for long-term users, all while ensuring that sensitive API keys are handled with appropriate security measures.