fix(auth): restore BetterAuth OIDC flow across api/web/compose

This commit is contained in:
2026-02-17 23:37:49 -06:00
parent 3b16b2c743
commit dedc1af080
22 changed files with 294 additions and 106 deletions
@@ -219,7 +219,7 @@ JWT_EXPIRATION=24h
OIDC_ISSUER=https://auth.example.com/application/o/mosaic/
OIDC_CLIENT_ID=prod-client-id
OIDC_CLIENT_SECRET=prod-client-secret
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/callback
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/oauth2/callback/authentik
```
### Compose Override for Production
@@ -89,7 +89,7 @@ OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
# Callback URL (must match Authentik configuration)
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
```
See [Authentik Setup](2-authentik.md) for complete OIDC configuration.
@@ -229,7 +229,7 @@ JWT_EXPIRATION=24h
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
# ======================
# Cache
@@ -54,17 +54,17 @@ Sign up at [goauthentik.io](https://goauthentik.io) for managed Authentik.
4. **Configure Provider:**
| Field | Value |
| ------------------------------ | ----------------------------------------------- |
| **Name** | Mosaic Stack |
| **Authorization flow** | default-provider-authorization-implicit-consent |
| **Client type** | Confidential |
| **Client ID** | (auto-generated, save this) |
| **Client Secret** | (auto-generated, save this) |
| **Redirect URIs** | `http://localhost:3001/auth/callback` |
| **Scopes** | `openid`, `email`, `profile` |
| **Subject mode** | Based on User's UUID |
| **Include claims in id_token** | ✅ Enabled |
| Field | Value |
| ------------------------------ | ------------------------------------------------------ |
| **Name** | Mosaic Stack |
| **Authorization flow** | default-provider-authorization-implicit-consent |
| **Client type** | Confidential |
| **Client ID** | (auto-generated, save this) |
| **Client Secret** | (auto-generated, save this) |
| **Redirect URIs** | `http://localhost:3001/auth/oauth2/callback/authentik` |
| **Scopes** | `openid`, `email`, `profile` |
| **Subject mode** | Based on User's UUID |
| **Include claims in id_token** | ✅ Enabled |
5. **Click "Create"**
@@ -96,7 +96,7 @@ Update your `.env` file:
OIDC_ISSUER=http://localhost:9000/application/o/mosaic-stack/
OIDC_CLIENT_ID=<your-client-id-from-step-2>
OIDC_CLIENT_SECRET=<your-client-secret-from-step-2>
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
```
**Important Notes:**
@@ -113,7 +113,7 @@ For production deployments:
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=prod-client-id
OIDC_CLIENT_SECRET=prod-client-secret
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/callback
OIDC_REDIRECT_URI=https://mosaic.example.com/auth/oauth2/callback/authentik
```
Update Authentik redirect URIs to match your production URL.
@@ -143,7 +143,7 @@ docker compose restart api
```bash
# Initiate OIDC flow
curl http://localhost:3001/auth/callback/authentik
curl http://localhost:3001/auth/oauth2/callback/authentik
# This will return a redirect URL to Authentik
```
@@ -223,8 +223,8 @@ Customize Authentik's login page:
```bash
# Ensure exact match (including http vs https)
# In Authentik: http://localhost:3001/auth/callback
# In .env: OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
# In Authentik: http://localhost:3001/auth/oauth2/callback/authentik
# In .env: OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
```
### Error: "Invalid client credentials"
@@ -89,7 +89,7 @@ AUTHENTIK_PORT_HTTPS=9443
OIDC_ISSUER=http://localhost:9000/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id-here
OIDC_CLIENT_SECRET=your-client-secret-here
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
```
**Bootstrap Credentials:**
+2 -2
View File
@@ -191,7 +191,7 @@ Authorization: Bearer {session_token}
OAuth callback handler for Authentik (and other OIDC providers).
```http
GET /auth/callback/authentik
GET /auth/oauth2/callback/authentik
```
**Query Parameters:**
@@ -226,7 +226,7 @@ This endpoint is called by the OIDC provider after successful authentication.
1. User clicks "Sign in with Authentik"
2. Frontend redirects to Authentik
3. User authenticates with Authentik
4. Authentik redirects to /auth/callback/authentik
4. Authentik redirects to /auth/oauth2/callback/authentik
5. Server exchanges code for tokens
6. Server creates/updates user
7. Server creates session
+3 -3
View File
@@ -111,7 +111,7 @@ If using private registry images from `git.mosaicstack.dev`:
OIDC_CLIENT_ID=<your-oidc-client-id>
OIDC_CLIENT_SECRET=<your-oidc-client-secret>
OIDC_ISSUER=https://auth.diversecanvas.com/application/o/mosaic-stack/
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/callback/authentik
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/oauth2/callback/authentik
OLLAMA_ENDPOINT=http://10.1.1.42:11434
```
@@ -163,7 +163,7 @@ ENCRYPTION_KEY=<64-char-hex> # openssl rand -hex 32
OIDC_CLIENT_ID=<from-authentik>
OIDC_CLIENT_SECRET=<from-authentik>
OIDC_ISSUER=https://auth.diversecanvas.com/application/o/mosaic-stack/
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/callback/authentik
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/oauth2/callback/authentik
# External Ollama
OLLAMA_ENDPOINT=http://10.1.1.42:11434
@@ -352,7 +352,7 @@ Update environment variables:
```bash
NEXT_PUBLIC_APP_URL=https://mosaic.example.com
NEXT_PUBLIC_API_URL=https://api.example.com
OIDC_REDIRECT_URI=https://api.example.com/auth/callback/authentik
OIDC_REDIRECT_URI=https://api.example.com/auth/oauth2/callback/authentik
```
### Resource Limits
+1 -1
View File
@@ -369,7 +369,7 @@ sleep 30
OIDC_ISSUER=https://auth.diversecanvas.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/callback/authentik
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/oauth2/callback/authentik
```
### Using External PostgreSQL
+3 -3
View File
@@ -152,7 +152,7 @@ States:
Add `OIDC_REDIRECT_URI` to `REQUIRED_OIDC_ENV_VARS`. Add URL format validation:
- Must be a valid URL
- Path must start with `/auth/callback`
- Path must start with `/auth/oauth2/callback`
- Warn if using `localhost` in production
**Tests to add:** Missing var, invalid URL, invalid path, valid URL.
@@ -716,9 +716,9 @@ Browser NestJS API Authentik
├────────────────────────────────────────────────────►│
│ │ User authenticates│
│◄────────────────────────────────────────────────────┤
│ 302 → /auth/callback/authentik?code=X │
│ 302 → /auth/oauth2/callback/authentik?code=X │
│ │ │
│ 5. GET /auth/callback/authentik?code=X │
│ 5. GET /auth/oauth2/callback/authentik?code=X │
├───────────────────────────►│ │
│ BetterAuth exchanges code │
│ ├───────────────────────►│
@@ -166,7 +166,7 @@ To use the authentication system, configure these environment variables:
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=http://localhost:3001/auth/callback
OIDC_REDIRECT_URI=http://localhost:3001/auth/oauth2/callback/authentik
# JWT Session Management
JWT_SECRET=change-this-to-a-random-secret-in-production
@@ -186,7 +186,7 @@ BetterAuth provides these endpoints automatically:
- `POST /auth/sign-up` - User registration
- `POST /auth/sign-out` - Logout
- `GET /auth/session` - Get current session
- `GET /auth/callback/authentik` - OAuth callback handler
- `GET /auth/oauth2/callback/authentik` - OAuth callback handler
- `GET /auth/profile` - Get authenticated user profile (custom)
---
+2 -2
View File
@@ -188,7 +188,7 @@ All components must follow TDD (tests first), achieve 85%+ coverage, and use PDA
### Existing Auth Implementation (from Issue #4)
- BetterAuth is configured in the API (`apps/api/src/auth/`)
- Endpoints: `/auth/callback/authentik`, `/auth/session`, `/auth/profile`
- Endpoints: `/auth/oauth2/callback/authentik`, `/auth/session`, `/auth/profile`
- Shared types available in `@mosaic/shared` package
- Session-based auth with JWT tokens
@@ -313,7 +313,7 @@ Based on existing backend (from Issue #4):
- `GET /auth/session` - Get current session
- `GET /auth/profile` - Get user profile
- `POST /auth/sign-out` - Logout
- `GET /auth/callback/authentik` - OIDC callback (redirect from Authentik)
- `GET /auth/oauth2/callback/authentik` - OIDC callback (redirect from Authentik)
### Tasks (to be implemented in future issue)
@@ -161,7 +161,7 @@ Enhance `ConnectionService` to handle OIDC-based authentication:
**Integration Tests**:
- POST /auth/initiate starts OIDC flow with correct params
- GET /auth/callback handles OIDC response and creates identity
- GET /auth/oauth2/callback/:providerId handles OIDC response and creates identity
- POST /auth/validate validates tokens from federated instances
- GET /auth/identities returns user's federated identities
- Federated requests with valid tokens are authenticated
+1 -1
View File
@@ -100,7 +100,7 @@ apps/web/src/
- `GET /auth/session` - Get current session
- `POST /auth/sign-out` - Logout
- `GET /auth/callback/authentik` - OIDC callback
- `GET /auth/oauth2/callback/authentik` - OIDC callback
### Future Endpoints (Mock Data Ready)