Secrets Reference
Before running the commands on this page, ensure you have:
- pnpm installed:
npm install -g pnpm - AWS CLI configured with your deployment profile (see Local Tooling Prerequisites)
- Dependencies installed: Run
pnpm installin the project root
If you encounter errors, see Troubleshooting.
This document covers all SST secrets required for B4M deployment, including how to detect which integrations are active.
Setting Secrets
Set secrets using the SST CLI:
pnpm sst secret set <SECRET_NAME> <value> --stage <stage>
Or directly:
pnpm sst secret set <SECRET_NAME> <value> --stage <stage>
What is "Platform Email"?
"Platform email" means the application sends emails FROM your domain (e.g., notifications@yourcompany.com). This includes:
- One-time login code emails (required for passwordless authentication)
- User invitation emails
- Session notifications
- AI agent communications
If YES: You need SES/SMTP setup with the MAIL_* secrets below
If NO (OAuth SSO-only login): You can skip email configuration, but users without an SSO provider will not be able to log in
Most deployments DO use platform email for user notifications.
Detecting Active Integrations
If you inherited a deployment or are unsure which integrations are active:
Stripe (Billing/Subscriptions)
How to check:
- Look for billing/subscription features in the app UI
- Check SST secrets:
pnpm sst secret list --stage production | grep STRIPE
- If secrets contain actual values (not
"placeholder"), Stripe is configured
Impact if active: Webhook URL must be updated when changing domains
Atlassian (Jira/Confluence)
How to check:
- In the app, go to Admin → Settings
- Look for
atlassianClientIdandatlassianClientSecretvalues - Or check if users see "Connect to Atlassian" in their profile settings
Impact if active: OAuth callback URL must be updated in Atlassian Developer Console
Google Drive
How to check:
- Look for "Connect Google Drive" option in user settings
- Uses same OAuth client as Google Login (
GOOGLE_CLIENT_ID)
Impact if active: Add Drive callback URL: https://app.yourdomain.com/google-drive/callback
Core Authentication Secrets (Required)
These secrets are required for the application to function:
| Secret | Description | Format | How to Generate |
|---|---|---|---|
SESSION_SECRET | Signs session cookies | Any string (48+ chars recommended) | openssl rand -base64 48 |
JWT_SECRET | OAuth state tokens, API auth | Min 32 characters | openssl rand -base64 48 |
SECRET_ENCRYPTION_KEY | Encrypts OAuth tokens at rest (AES-256) | Exactly 64 hex characters | openssl rand -hex 32 |
# Generate and set all core secrets
pnpm sst secret set SESSION_SECRET "$(openssl rand -base64 48)" --stage <stage>
pnpm sst secret set JWT_SECRET "$(openssl rand -base64 48)" --stage <stage>
pnpm sst secret set SECRET_ENCRYPTION_KEY "$(openssl rand -hex 32)" --stage <stage>
About SECRET_ENCRYPTION_KEY
SECRET_ENCRYPTION_KEY provides application-level encryption for sensitive data stored in the database. This is a defense-in-depth measure that complements MongoDB Atlas's at-rest encryption.
What it encrypts:
- OAuth access and refresh tokens for all providers (Google, GitHub, Okta, Slack, Atlassian)
- Third-party API credentials configured via Admin UI
- Any integration tokens stored for user accounts
Why it's a Tier 1 secret (SST-only): This key cannot be configured via the Admin UI because it encrypts secrets stored in the database. Storing it in the database would create a circular dependency where the key needed to decrypt data is itself encrypted in that data.
Format requirement: Must be exactly 64 hexadecimal characters (32 bytes for AES-256-GCM encryption). The openssl rand -hex 32 command generates exactly this format.
- All stored OAuth tokens become undecryptable
- Users must re-authenticate with all connected services (Google, Slack, Atlassian, etc.)
- All API credentials configured via Admin UI must be re-entered
JWT_SECRET should be at least 32 characters for security. Shorter values will work but trigger a warning in System Health. The openssl rand -base64 48 command generates a 64-character string.
During domain migration:
- DO NOT rotate
SESSION_SECRET— invalidates all active sessions - DO NOT rotate
JWT_SECRET— breaks OAuth state tokens - DO NOT rotate
SECRET_ENCRYPTION_KEY— requires re-encrypting stored tokens
Email Configuration (MAIL_*)
Required for platform email (one-time login codes, notifications):
| Secret | Description | Example |
|---|---|---|
MAIL_HOST | SMTP server hostname | email-smtp.us-east-1.amazonaws.com |
MAIL_PORT | SMTP port (typically 465 for SSL) | 465 |
MAIL_USERNAME | SMTP username | AKIA... (SES credentials) |
MAIL_PASSWORD | SMTP password | From SES SMTP credentials |
MAIL_FROM | Sender email address | noreply@yourdomain.com |
SUPPORT_EMAIL | Support contact email | support@yourdomain.com |
Example with Amazon SES:
pnpm sst secret set MAIL_HOST email-smtp.us-east-1.amazonaws.com --stage <stage>
pnpm sst secret set MAIL_PORT 465 --stage <stage>
pnpm sst secret set MAIL_USERNAME "AKIA..." --stage <stage>
pnpm sst secret set MAIL_PASSWORD "your-ses-smtp-password" --stage <stage>
pnpm sst secret set MAIL_FROM "noreply@yourdomain.com" --stage <stage>
Database Configuration
| Secret/Env | Description | Values |
|---|---|---|
MONGODB_URI | Database connection string | mongodb+srv://... |
MAIN_DB_TYPE | Database type | MongoAtlas (default) or DocumentDB |
pnpm sst secret set MONGODB_URI "mongodb+srv://user:pass@cluster.mongodb.net/dbname" --stage <stage>
# For DocumentDB users only:
pnpm sst secret set MAIN_DB_TYPE DocumentDB --stage <stage>
OAuth Providers
Google OAuth
| Secret | Description |
|---|---|
GOOGLE_CLIENT_ID | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Google OAuth client secret |
Callback URLs:
- Login:
https://app.yourdomain.com/api/auth/google/callback - Drive:
https://app.yourdomain.com/google-drive/callback
GitHub OAuth
| Secret | Description |
|---|---|
GITHUB_CLIENT_ID | GitHub OAuth client ID |
GITHUB_CLIENT_SECRET | GitHub OAuth client secret |
Callback URL: https://app.yourdomain.com/api/auth/github/callback
Okta (Enterprise SSO)
| Secret | Description | Example |
|---|---|---|
OKTA_AUDIENCE | Okta domain URL | https://your-domain.okta.com |
OKTA_CLIENT_ID | Okta OAuth client ID | From Okta admin console |
OKTA_CLIENT_SECRET | Okta OAuth client secret | From Okta admin console |
Okta SSO requires JWT_SECRET to be set. Without it, login will fail with error=okta_setup_failed.
Callback URL: https://app.yourdomain.com/api/auth/okta/callback
Microsoft OAuth
| Secret | Description |
|---|---|
MICROSOFT_CLIENT_ID | Microsoft OAuth client ID |
MICROSOFT_CLIENT_SECRET | Microsoft OAuth client secret |
Stripe (Optional)
| Secret | Description |
|---|---|
STRIPE_SECRET_KEY | Stripe API secret key |
STRIPE_PUBLISHABLE_KEY | Stripe publishable key |
STRIPE_WEBHOOK_SECRET | Webhook signing secret |
Webhook URL: https://app.yourdomain.com/api/stripe/webhook
Slack Integration (Optional)
| Secret | Description |
|---|---|
SLACK_CLIENT_ID | Slack app client ID |
SLACK_CLIENT_SECRET | Slack app client secret |
SLACK_SIGNING_SECRET | Request signature verification |
SLACK_APP_ID | Slack app ID |
Callback URLs:
- Workspace:
https://app.yourdomain.com/api/slack/oauth/callback - User link:
https://app.yourdomain.com/api/slack/oauth/user-link/callback
Verifying Configuration
System Health Dashboard
After deployment, verify configuration via Admin > General Ops > System Health:
- Log in as an admin user
- Navigate to Admin > General Ops > System Health
- Check status indicators for each integration
- Use "Send Test Email" to verify SMTP
Command Line
List configured secrets:
pnpm sst secret list | grep -E "MAIL_|MAIN_DB|STRIPE_|SESSION_|JWT_|OKTA_|GOOGLE_|GITHUB_" --stage <stage>