Zum Hauptinhalt springen

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

BFF Auth Flow

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

ChallengeBeschreibungChallengeResponses
EMAIL_CODECode per Email gesendet{ "EMAIL_CODE": "123456" }
SMS_CODECode per SMS gesendet{ "SMS_CODE": "123456" }
NEW_PASSWORD_REQUIREDPasswort muss geändert werden{ "NEW_PASSWORD": "..." }

Error Codes

ErrorHTTP StatusBeschreibung
NotAuthorizedException401Falscher Username/Passwort
UserNotFoundException401Benutzer nicht gefunden (gleiche Response wie NotAuthorized)
UserNotConfirmedException403Account nicht aktiviert
CodeMismatchException400MFA-Code falsch
ExpiredCodeException400MFA-Code abgelaufen
TooManyRequestsException429Rate Limit
UserLockedException403Account 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-challenge und resend-code benötigt
  • Verhindert Replay-Attacks

BFF Session Handling

Nach erfolgreicher Authentifizierung:

  1. BFF speichert Tokens (Access + Refresh) serverseitig
  2. BFF setzt httpOnly Cookie für Browser-Session
  3. SPA sendet Cookie bei API-Requests
  4. 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

EndpointController
POST /endcustomer/auth/initiateEndcustomerAuthApiController
POST /endcustomer/auth/respond-to-challengeEndcustomerAuthApiController
POST /endcustomer/auth/resend-codeEndcustomerAuthApiController

Wiederverwendung

  • SignInManager für Credential-Validierung
  • IEndcustomerApi2FaService fü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

PhaseBeschreibung
1. API bauenNeue Endpoints in CCAOnline
2. BFF erweiternAuth-Proxy + Session-Management
3. SPA anpassenLogin-UI gegen BFF Auth-API
4. Optional machenKunden 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?

Referenzen