Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ JWT_SECRET=change_me_dev_only
SESSION_SECRET=change_me_dev_only
BETTER_AUTH_SECRET=replace_with_at_least_32_random_chars
ADMIN_PASSWORD=
# BETTER_AUTH_URL: Base URL for Better Auth endpoints and OAuth callbacks
# In production, set this to the main web domain (e.g., https://corpsim.altitude-interactive.com)
# NOT the API subdomain. The nginx proxy will forward /api/auth/* to the API server.
BETTER_AUTH_URL=http://localhost:4310
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
type: patch
area: web
summary: Fix OAuth callback redirect URLs for GitHub, Microsoft, and Discord by configuring nginx proxy and BETTER_AUTH_URL
---

- Updated nginx configuration to proxy `/api/auth/*` requests from web domain to API server
- Added documentation for configuring `BETTER_AUTH_URL` to use the main web domain in production
- Fixed OAuth callback URL issues that caused "redirect_uri is not associated with this application" errors
- Ensures all OAuth providers (GitHub, Microsoft, Discord) redirect to the correct domain
24 changes: 22 additions & 2 deletions docs/project/DOKPLOY_DOCKERFILE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Create separate Dokploy apps from the same repository and Dockerfile:
- `API_PORT=4310`
- expose/public port `4310`
- `CORS_ORIGIN=https://corpsim.altitude-interactive.com`
- `BETTER_AUTH_URL=https://corpsim.altitude-interactive.com`
- ⚠️ **IMPORTANT**: Set `BETTER_AUTH_URL` to the main web domain (not the API subdomain) so OAuth callbacks redirect to the correct domain

3. `corpsim-worker`
- `APP_ROLE=worker`
Expand Down Expand Up @@ -89,11 +91,29 @@ pnpm sim:seed

## Nginx upstream mapping

- `corpsim.altitude-interactive.com` -> `10.7.0.3:4311`
- `corpsim-api.altitude-interactive.com` -> `10.7.0.3:4310`
- `corpsim.altitude-interactive.com` -> `192.0.2.10:4311` (web app)
- `corpsim-api.altitude-interactive.com` -> `192.0.2.10:4310` (API server)

**IMPORTANT**: The nginx configuration for `corpsim.altitude-interactive.com` must proxy `/api/auth/*` requests to the API server at port 4310. This allows OAuth callbacks to work correctly on the main web domain. See `docs/project/corpsim.altitude.nginx.conf` for the complete configuration.

**Note**: Replace the example IP address `192.0.2.10` (from RFC 5737 documentation range) with your actual server IP address.

## Troubleshooting

### OAuth failing with "redirect_uri is not associated with this application"

**Symptom:** When clicking "Continue with GitHub" (or other OAuth providers), you get:
- Error from OAuth provider: "The redirect_uri is not associated with this application"
- Failed OAuth authentication

**Cause:** The `BETTER_AUTH_URL` environment variable for the API service is not configured correctly, or the nginx proxy is not set up to forward `/api/auth/*` requests from the web domain to the API server.

**Solution:**
1. Ensure `BETTER_AUTH_URL=https://corpsim.altitude-interactive.com` is set for the API service (use the main web domain, NOT the API subdomain)
2. Verify the nginx configuration includes a proxy rule for `/api/auth/*` (see `docs/project/corpsim.altitude.nginx.conf`)
3. Restart the API service and nginx after making changes
4. Configure OAuth apps (GitHub, Google, Microsoft, Discord) to allow callback URLs like `https://corpsim.altitude-interactive.com/api/auth/callback/{provider}`

### Authentication failing with "Provider not found" or 404 errors

**Symptom:** When clicking "Continue with Google" (or other OAuth providers), you get:
Expand Down
116 changes: 116 additions & 0 deletions docs/project/OAUTH_CALLBACK_FIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# OAuth Callback Redirect URL Fix - Deployment Guide

## Problem
When users try to sign in/sign up with GitHub (or other OAuth providers) on production at `https://corpsim.altitude-interactive.com`, they receive an error:

> "The redirect_uri is not associated with this application."

## Root Cause
The OAuth flow in better-auth works as follows:
1. User clicks "Continue with GitHub" on the web app
2. Browser sends request to API server (via `NEXT_PUBLIC_API_URL`)
3. API server redirects to GitHub with a `redirect_uri` parameter
4. The `redirect_uri` is constructed from `BETTER_AUTH_URL` environment variable
5. GitHub redirects back to that `redirect_uri` after user authorization
6. API server processes the callback

The issue occurs because:
- The GitHub OAuth App is configured to allow callbacks to `https://corpsim.altitude-interactive.com/api/auth/callback/github`
- But `BETTER_AUTH_URL` is set to `https://corpsim-api.altitude-interactive.com`
- This causes GitHub to reject the callback URL as unauthorized

## Solution
To fix this issue, we need to:

### 1. Update Nginx Configuration
Apply the updated `docs/project/corpsim.altitude.nginx.conf` to the production nginx server:

```nginx
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name corpsim.altitude-interactive.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# Proxy Better Auth routes (/api/auth/*) to API server
location /api/auth/ {
proxy_pass http://192.0.2.10:4310;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location / {
proxy_pass http://192.0.2.10:4311;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```

This adds a specific proxy rule for `/api/auth/*` requests that forwards them to the API server. Replace the example IP addresses and SSL certificate paths with your production values.

### 2. Update API Service Environment Variable
In Dokploy (or your deployment platform), update the `corpsim-api` service environment variables:

Add:
```
BETTER_AUTH_URL=https://corpsim.altitude-interactive.com
```

This tells better-auth to construct OAuth callback URLs using the main web domain instead of the API subdomain.

### 3. Reload/Restart Services
1. Reload nginx configuration: `sudo nginx -s reload`
2. Restart the API service in Dokploy (or redeploy with the new environment variable)

### 4. Update OAuth Provider Configurations
Ensure the OAuth apps on each provider's developer portal have the correct callback URL registered:

**GitHub**: https://github.com/settings/developers
- Callback URL: `https://corpsim.altitude-interactive.com/api/auth/callback/github`

**Google**: https://console.cloud.google.com/apis/credentials
- Authorized redirect URI: `https://corpsim.altitude-interactive.com/api/auth/callback/google`

**Microsoft**: https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps
- Redirect URI: `https://corpsim.altitude-interactive.com/api/auth/callback/microsoft`

**Discord**: https://discord.com/developers/applications
- Redirect URI: `https://corpsim.altitude-interactive.com/api/auth/callback/discord`

## How It Works After the Fix
1. User clicks "Continue with GitHub" on `https://corpsim.altitude-interactive.com`
2. Browser calls `https://corpsim-api.altitude-interactive.com/api/auth/sign-in/social`
3. API server (with `BETTER_AUTH_URL=https://corpsim.altitude-interactive.com`) redirects to GitHub with `redirect_uri=https://corpsim.altitude-interactive.com/api/auth/callback/github`
4. User authorizes on GitHub
5. GitHub redirects to `https://corpsim.altitude-interactive.com/api/auth/callback/github`
6. Nginx proxies this request to the API server at port 4310
7. API server processes the callback and redirects to success page

## Testing
After applying the fix:
1. Go to `https://corpsim.altitude-interactive.com`
2. Navigate to `/sign-in` or `/sign-up`
3. Click "Continue with GitHub" (or another OAuth provider)
4. Verify you're redirected to the provider's authorization page
5. Authorize the application
6. Verify you're redirected back to the app successfully
7. Check browser network tab to confirm callbacks go to the correct domain

## Alternative Solution (Not Recommended)
Instead of updating nginx and environment variables, you could update each OAuth provider's configuration to allow callbacks to both domains:
- `https://corpsim.altitude-interactive.com/api/auth/callback/{provider}`
- `https://corpsim-api.altitude-interactive.com/api/auth/callback/{provider}`

However, this is not recommended because:
- It's confusing to have callbacks on two different domains
- It's harder to manage and update OAuth provider configurations
- Users might see inconsistent domain behavior
22 changes: 16 additions & 6 deletions docs/project/corpsim.altitude.nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@ server {
listen [::]:443 ssl http2;
server_name corpsim.altitude-interactive.com;

ssl_certificate /etc/ssl/cloudflare/altitude_pubkey.pem;
ssl_certificate_key /etc/ssl/cloudflare/altitude_privkey.key;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# Proxy Better Auth routes (/api/auth/*) to API server
location /api/auth/ {
proxy_pass http://192.0.2.10:4310;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location / {
proxy_pass http://10.7.0.3:4311;
proxy_pass http://192.0.2.10:4311;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
Expand All @@ -35,11 +45,11 @@ server {
listen [::]:443 ssl http2;
server_name corpsim-api.altitude-interactive.com;

ssl_certificate /etc/ssl/cloudflare/altitude_pubkey.pem;
ssl_certificate_key /etc/ssl/cloudflare/altitude_privkey.key;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

location / {
proxy_pass http://10.7.0.3:4310;
proxy_pass http://192.0.2.10:4310;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
Expand Down
Loading