Proposal: BFF Auth-API für Kundenportal
🤖 Generated with Claude Code
Co-Authored-By: Claude (noreply@anthropic.com)
Status: Draft Datum: 2025-12 Betreff: Challenge-basierte Auth-API für BFF-Szenario
Motivation
Beim Einsatz des Hosting-Servers als BFF (Backend for Frontend) soll CCAOnline nicht mehr direkt aus dem Internet erreichbar sein. Der BFF proxied alle Requests, inklusive Authentifizierung.
Problem: Die aktuelle OAuth-Implementierung erfordert Browser-Redirects zu CCAOnline, was bei nicht-öffentlichem CCAOnline nicht funktioniert.
Lösung: Challenge-basierte Auth-API analog zu AWS Cognito.
Architektur
Diagram Source: bff-auth-flow.d2
API Design (Cognito-Style)
POST /auth/initiate
Startet Authentifizierung. Gibt entweder Tokens oder eine Challenge zurück.
Request:
{
"authFlow": "USER_PASSWORD_AUTH",
"authParameters": {
"USERNAME": "endkunde@example.com",
"PASSWORD": "..."
}
}
Response (Erfolg ohne MFA):
{
"authenticationResult": {
"accessToken": "eyJ...",
"refreshToken": "...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
}
Response (MFA erforderlich):
{
"challengeName": "EMAIL_CODE",
"session": "session-token-für-challenge-flow",
"challengeParameters": {
"EMAIL_HINT": "e***@example.com",
"CODE_DELIVERY_DESTINATION": "e***@example.com",
"CODE_DELIVERY_METHOD": "EMAIL"
}
}
Response (Fehler):
{
"error": "NotAuthorizedException",
"message": "Incorrect username or password"
}
POST /auth/respond-to-challenge
Beantwortet eine Challenge (z.B. MFA-Code).
Request:
{
"challengeName": "EMAIL_CODE",
"session": "session-token-aus-initiate",
"challengeResponses": {
"EMAIL_CODE": "123456"
}
}
Response (Erfolg):
{
"authenticationResult": {
"accessToken": "eyJ...",
"refreshToken": "...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
}
Response (Code falsch):
{
"error": "CodeMismatchException",
"message": "Invalid verification code"
}
POST /auth/resend-code
Sendet MFA-Code erneut (optional, für UX).
Request:
{
"session": "session-token-aus-initiate"
}
Response:
{
"codeDeliveryDetails": {
"destination": "e***@example.com",
"deliveryMethod": "EMAIL"
}
}
Challenge Types
| Challenge | Beschreibung | ChallengeResponses |
|---|---|---|
EMAIL_CODE | Code per Email gesendet | { "EMAIL_CODE": "123456" } |
SMS_CODE | Code per SMS gesendet | { "SMS_CODE": "123456" } |
NEW_PASSWORD_REQUIRED | Passwort muss geändert werden | { "NEW_PASSWORD": "..." } |
Error Codes
| Error | HTTP Status | Beschreibung |
|---|---|---|
NotAuthorizedException | 401 | Falscher Username/Passwort |
UserNotFoundException | 401 | Benutzer nicht gefunden (gleiche Response wie NotAuthorized) |
UserNotConfirmedException | 403 | Account nicht aktiviert |
CodeMismatchException | 400 | MFA-Code falsch |
ExpiredCodeException | 400 | MFA-Code abgelaufen |
TooManyRequestsException | 429 | Rate Limit |
UserLockedException | 403 | Account gesperrt (Lockout) |
Session Token
Der session Token ist:
- Kurzlebig (z.B. 5 Minuten)
- Enthält verschlüsselt: UserId, Challenge-Typ, Ablaufzeit
- Wird für
respond-to-challengeundresend-codebenötigt - Verhindert Replay-Attacks
BFF Session Handling
Nach erfolgreicher Authentifizierung:
- BFF speichert Tokens (Access + Refresh) serverseitig
- BFF setzt httpOnly Cookie für Browser-Session
- SPA sendet Cookie bei API-Requests
- BFF fügt Bearer Token zu proxied Requests hinzu
Browser ──Cookie──► BFF ──Bearer Token──► CCAOnline
Vorteile:
- Tokens nie im Browser (XSS-sicher)
- BFF kann Token-Refresh transparent handhaben
- Session-Invalidierung zentral möglich
Implementierung in CCAOnline
Neue Endpoints
| Endpoint | Controller |
|---|---|
POST /endcustomer/auth/initiate | EndcustomerAuthApiController |
POST /endcustomer/auth/respond-to-challenge | EndcustomerAuthApiController |
POST /endcustomer/auth/resend-code | EndcustomerAuthApiController |
Wiederverwendung
SignInManagerfür Credential-ValidierungIEndcustomerApi2FaServicefür MFA-Code Versand/Validierung- Bestehende Lockout-Logik
Session Token Implementierung
public class AuthSession
{
public string UserId { get; set; }
public string ChallengeName { get; set; }
public DateTime ExpiresAt { get; set; }
}
// Verschlüsselt mit DataProtection API
var session = _dataProtector.Protect(JsonSerializer.Serialize(authSession));
Migration / Rollout
| Phase | Beschreibung |
|---|---|
| 1. API bauen | Neue Endpoints in CCAOnline |
| 2. BFF erweitern | Auth-Proxy + Session-Management |
| 3. SPA anpassen | Login-UI gegen BFF Auth-API |
| 4. Optional machen | Kunden wählen Direct vs. BFF |
Offene Fragen
- Refresh Token Flow über BFF?
- Logout: Nur BFF-Session oder auch CCAOnline-Token invalidieren?
- Rate Limiting: Pro IP oder pro Username?
- Passwort-Reset Flow?