fix(auth): restore BetterAuth OIDC flow across api/web/compose
All checks were successful
ci/woodpecker/push/infra Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful

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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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:**

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

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

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

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 │
│ ├───────────────────────►│

View File

@@ -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)
---

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)

View File

@@ -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

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)