1 Authentifizierung
mrrmlab Wiki edited this page 2026-05-02 18:03:36 +02:00

Authentifizierung

Übersicht

mrrmlab verwendet Keycloak als Identity Provider mit dem OIDC Authorization Code Flow + PKCE (RFC 7636). Alle Clients (Web, Mobile) nutzen dasselbe @mrrmlab/auth-Package.

Keycloak-Clients

Client ID Typ Redirect URI
mrrmlab-web SPA (public) https://app.mrrm.de/auth/callback
mrrmlab-web-dev SPA (public) https://dev.app.mrrm.de/auth/callback
mrrmlab-android Native (public) mrrmlab://auth/callback

Realm: mmlab auf https://auth.mrrm.de

Login-Flow

1. App generiert PKCE-Paar:
   code_verifier (zufällig, 64 Zeichen)
   code_challenge = BASE64URL(SHA-256(code_verifier))

2. Browser öffnen mit URL:
   https://auth.mrrm.de/realms/mmlab/protocol/openid-connect/auth
     ?client_id=mrrmlab-android
     &response_type=code
     &redirect_uri=mrrmlab://auth/callback
     &code_challenge=<challenge>
     &code_challenge_method=S256
     &scope=openid profile email offline_access
     &state=<random>
     &nonce=<random>

3. Nutzer authentifiziert sich in Keycloak

4. Keycloak redirectet zurück:
   mrrmlab://auth/callback?code=<auth_code>&state=<state>

5. App tauscht Code gegen Tokens:
   POST https://auth.mrrm.de/realms/mmlab/protocol/openid-connect/token
   Body: code=<code>&code_verifier=<verifier>&grant_type=authorization_code&...

6. Tokens speichern (expo-secure-store / localStorage)

7. ID-Token lokal verifizieren (Signatur via JWKS, Issuer, Audience, Nonce)

Token-Speicherung

Platform Storage
Web localStorage (via WebStorageTokenStore)
Mobile expo-secure-store (verschlüsselt im Android Keystore)

Token-Refresh

AuthClient prüft bei jedem API-Aufruf ob der Access Token bald abläuft (Standard: 30 Sekunden vor Ablauf). Falls ja, wird automatisch mit dem Refresh Token erneuert.

Backend-Validierung

// NestJS — globaler Guard
@Injectable()
export class JwtAuthGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const token = extractBearerToken(request);
    const { payload } = await jwtVerify(token, JWKS, {
      issuer: env.KC_ISSUER,
      audience: env.KC_AUDIENCE,
    });
    request.user = toAuthUser(payload);
    return true;
  }
}

JWKS werden gecacht und automatisch rotiert.

Dev-Modus (kein Keycloak)

Wenn KC_ISSUER leer ist:

  • Backend: JwtAuthGuard gibt immer true zurück, ownerSub = 'dev-user'
  • Web/Mobile: AuthClient wird nicht erstellt; API-Calls ohne Token

→ Ermöglicht lokale Entwicklung ohne Keycloak-Instanz.

Scopes

Scope Zweck
openid OIDC-Basisprotokoll
profile Name, preferred_username
email E-Mail-Adresse
offline_access Refresh Token (langlebig)