workos-vault
WorkOS Vault
Step 1: Fetch Documentation (BLOCKING)
STOP. Do not proceed until complete.
WebFetch these URLs in order — they are the source of truth:
- https://workos.com/docs/vault/quick-start
- https://workos.com/docs/vault/key-context
- https://workos.com/docs/vault/index
- https://workos.com/docs/vault/byok
If this skill conflicts with fetched docs, follow the docs.
Step 2: Pre-Flight Validation
WorkOS Credentials
Check environment variables or secrets manager for:
WORKOS_API_KEY- starts withsk_WORKOS_CLIENT_ID- starts withclient_
Verify: Both exist before continuing.
Organization Setup
Confirm target WorkOS organization exists:
- Check Dashboard or use Organizations API to list orgs
- Note organization ID (format:
org_*)
Without an organization ID, Vault operations will fail.
Customer Key Management (BYOK Only)
If implementing Bring Your Own Key:
- Customer must have AWS KMS, Azure Key Vault, or Google Cloud KMS configured
- WorkOS service principal must have IAM permissions to use customer keys
- CMK identifiers must be configured in WorkOS Dashboard
Skip this section if using WorkOS-managed keys (default).
Step 3: Install SDK
Detect language/framework, install WorkOS SDK:
# Node.js
npm install @workos-inc/node
# Python
pip install workos
# Ruby
gem install workos
# Go
go get github.com/workos/workos-go/v4
# Java
# Add to pom.xml or build.gradle per docs
Verify: SDK package exists before writing imports.
Step 4: SDK Initialization
Initialize SDK with credentials. Pattern varies by language:
Language?
|
+-- Node.js --> Import WorkOS class, instantiate with apiKey
|
+-- Python --> Import workos module, set workos.api_key
|
+-- Ruby --> Require workos, set WorkOS.key!
|
+-- Go --> Import workos package, create client with apiKey option
|
+-- Java --> Create WorkOS instance with apiKey in builder
Check fetched Quick Start docs for exact initialization pattern.
Critical: Do NOT hardcode API keys. Load from environment or secrets manager.
Step 5: Key Context Design (DECISION TREE)
Key context determines which encryption keys are used. Plan cardinality BEFORE creating objects:
Isolation requirement?
|
+-- Per-organization --> {"organization_id": "org_123"}
|
+-- Per-user --> {"organization_id": "org_123", "user_id": "user_456"}
|
+-- Per-tenant + data type --> {"organization_id": "org_123", "data_type": "ssn"}
|
+-- Custom hierarchy --> Up to 10 key-value pairs
Key context rules (from docs):
- All values MUST be strings
- Maximum 10 key-value pairs per context
- Context is IMMUTABLE after object creation (you cannot change keys, only values)
- Context determines KEK selection (WorkOS-managed or BYOK)
Example for multi-tenant SaaS isolating customer data:
{
"organization_id": "org_01HZMS...",
"environment": "production",
"data_classification": "pii"
}
This creates a unique encryption key for each combination of org + environment + classification.
Step 6: Create Encrypted Object
Use SDK's Vault object creation method. Check fetched docs for exact method name (likely vault.createObject or similar).
Pattern:
SDK method to create object with:
- key_context: dict/map of string pairs (from Step 5)
- value: string blob to encrypt (JSON serialize if needed)
- name: unique identifier within context (e.g., "user_ssn")
Critical behaviors (from docs):
- KEKs are created just-in-time based on key context
- A unique data-encrypting key (DEK) is generated per object
- DEK is encrypted with all KEKs from context
- Both encrypted value and encrypted DEKs are stored together
Returns: Object metadata including:
- Object name
- Version number (starts at 1)
- Created timestamp
- Key context (immutable)
Example pseudo-code:
object = workos.vault.createObject(
keyContext: {"organization_id": "org_123"},
name: "database_credentials",
value: '{"username":"app","password":"secret123"}'
)
Step 7: Retrieve Object Value
Use SDK's get/fetch object method. Check fetched docs for exact signature.
Pattern:
SDK method to fetch object with:
- key_context: SAME context used at creation
- name: object identifier
Returns: Object with decrypted value plus metadata (version, timestamps, etc.)
Critical: Key context MUST match exactly. Mismatched context will fail to decrypt even if object name exists.
Step 8: Update Object Value
Use SDK's update object method. Key context CANNOT change, only value.
Pattern:
SDK method to update with:
- key_context: original context (immutable)
- name: object identifier
- value: new encrypted value
- version: (optional) expected current version for consistency check
Version locking (from docs):
- If
versionparameter is provided, update ONLY succeeds if current version matches - Use this to prevent lost updates in concurrent scenarios
- If omitted, update always succeeds (last write wins)
Version is incremented on each update.
Step 9: List and Query Objects
Two SDK methods for object discovery:
List object names
Returns ONLY names, no metadata or values. Use for efficient enumeration.
SDK list method with:
- key_context: context to query within
Get object metadata
Returns metadata WITHOUT decrypting value. Use to check version, timestamps, context.
SDK metadata method with:
- key_context: context to query within
- name: object identifier
Use metadata queries to check versions before expensive decrypt operations.
Step 10: Delete Object
Use SDK's delete object method. Marks for deletion but doesn't immediately wipe data.
Pattern:
SDK delete method with:
- key_context: original context
- name: object identifier
From docs: Object becomes unavailable to API operations immediately, but physical deletion is asynchronous.
Cannot be undone. Deleted objects cannot be recreated with same name until fully purged.
Step 11: BYOK Configuration (Optional)
If using Bring Your Own Key, configure CMK mappings in WorkOS Dashboard.
Critical from docs: CMK selection is AUTOMATIC based on key context:
Key context matching example:
|
+-- {"organization_id": "org_abc123"} --> Uses CMK configured for org_abc123
|
+-- {"organization_id": "org_xyz987"} --> Uses WorkOS-managed KEK (no CMK configured)
No code changes required for BYOK. Vault automatically uses CMK when context matches configuration.
Supported CMK providers:
- AWS KMS
- Azure Key Vault
- Google Cloud KMS
Check fetched BYOK docs for Dashboard setup steps and IAM permission requirements.
Step 12: Local Encryption (Advanced)
For client-side encryption before transmission, use SDK's encrypt method with Vault-managed keys.
Pattern (check fetched docs for exact method):
SDK encrypt method with:
- key_context: context determining KEK
- plaintext: data to encrypt
Returns: Encrypted blob with embedded encrypted DEKs.
Use case: Encrypt data client-side, store encrypted blob in your own database, decrypt later via SDK.
Decryption: Use corresponding decrypt method with same key context.
Verification Checklist (ALL MUST PASS)
Run these commands to confirm integration:
# 1. Check SDK installed
npm list @workos-inc/node || pip show workos || gem list workos || go list -m github.com/workos/workos-go
# 2. Check credentials set
env | grep WORKOS_API_KEY || echo "FAIL: WORKOS_API_KEY not set"
env | grep WORKOS_CLIENT_ID || echo "FAIL: WORKOS_CLIENT_ID not set"
# 3. Test create object (replace with actual SDK test code)
# This is language-specific - write actual test that creates/retrieves/deletes object
# 4. Verify object encrypted at rest
# Check WorkOS Dashboard Vault section for test object
# 5. Application builds
npm run build || python -m py_compile app.py || rake build || go build || mvn compile
Manual checks:
- Created object appears in WorkOS Dashboard Vault section
- Retrieved value matches original plaintext
- Updated object shows incremented version
- Deleted object returns 404 on subsequent fetch
- BYOK: Customer CMK is used for configured organizations (check Dashboard audit)
Error Recovery
"Invalid key context" on create/fetch
Root cause: Context format validation failed.
Fixes:
- Check all context values are strings (not numbers, booleans, objects)
- Check context has ≤10 key-value pairs
- Check no empty strings as keys or values
"Object not found" with correct name
Root cause: Key context mismatch between create and fetch.
Fix: Verify EXACT context used at creation time. Even spacing in keys matters.
"Version conflict" on update
Root cause: Object was modified between your fetch and update (concurrent write).
Fix: Fetch latest version, reapply changes, retry update with new version number.
"Insufficient permissions" for BYOK
Root cause: WorkOS service principal lacks IAM permissions on customer CMK.
Fixes for each provider:
- AWS KMS: Grant
kms:Encrypt,kms:Decrypt,kms:GenerateDataKeyto WorkOS role - Azure Key Vault: Assign "Key Vault Crypto User" role to WorkOS service principal
- Google Cloud KMS: Grant
cloudkms.cryptoKeyVersions.useToEncryptanduseToDecryptpermissions
Check fetched BYOK docs for exact IAM policy examples.
"API key invalid"
Root cause: Key doesn't start with sk_ or was revoked.
Fixes:
- Regenerate API key in WorkOS Dashboard
- Update
WORKOS_API_KEYenvironment variable - Verify key is for correct environment (staging vs production)
SDK import fails
Root cause: Package not installed or wrong import path.
Fixes:
- Reinstall SDK package (see Step 3)
- Check import path matches SDK version (e.g.,
@workos-inc/nodenotworkos) - Clear package cache:
npm cache clean --forceor equivalent
"Rate limit exceeded"
Root cause: Too many API requests in short time.
Fixes:
- Implement exponential backoff on retries
- Batch operations where possible (list instead of individual gets)
- Cache decrypted values client-side if appropriate for use case
- Contact WorkOS support for rate limit increase
Related Skills
- workos-api-vault: Reference for Vault REST API direct usage
- workos-audit-logs: Audit Vault access events
- workos-api-organization: Manage organizations for key context isolation
More from workos/skills
workos
Use when the user asks for a WorkOS docs URL, term, or dashboard field (Sign-in endpoint, initiate_login_uri, Redirect URI, `WORKOS_*` env vars), or is implementing, debugging, or migrating WorkOS — AuthKit, SSO/SAML, Directory Sync, RBAC, FGA, MFA, Vault, Audit Logs, Admin Portal, Pipes (Connected Apps), Feature Flags, Radar (bot/fraud detection), webhooks, Custom Domains, or migrating from Auth0, Clerk, Cognito, Firebase, Supabase, Stytch, Descope, or Better Auth. Also triggers on @workos-inc/* imports.
595workos-widgets
Use when the user is implementing, embedding, or debugging a WorkOS Widget — specifically the User Management, User Profile, Admin Portal SSO Connection, or Admin Portal Domain Verification widgets. Handles the full stack — detecting the frontend (Next.js, React, React Router, TanStack Start, Vite, SvelteKit), generating access tokens via the backend SDK in use (Node, Python, Go, Ruby, PHP, Java, .NET), and wiring up the widget component correctly per the bundled OpenAPI spec. Also use when code imports from @workos-inc/widgets or the user pastes <UserManagement /> or <UserProfile /> JSX.
270workos-authkit-nextjs
Integrate WorkOS AuthKit with Next.js App Router (13+). Server-side rendering required.
64workos-authkit-base
Architectural reference for WorkOS AuthKit integrations. Fetch README first for implementation details.
42workos-authkit-react
Integrate WorkOS AuthKit with React single-page applications. Client-side only authentication. Use when the project is a React SPA without Next.js or React Router.
33workos-authkit-tanstack-start
Integrate WorkOS AuthKit with TanStack Start applications. Full-stack TypeScript with server functions. Use when project uses TanStack Start, @tanstack/start, or vinxi.
28