Files
claude-projects/wuerth-plato/memory/project_idp_witglobal.md
T

4.7 KiB

name, description, metadata
name description metadata
project-idp-witglobal PingFederate (WITGLOBAL) als IdP für plato-customer-be — DEV-Konfiguration, BFF-Architektur, Token-Eigenschaften, Test-Rig.
node_type type originSessionId
memory project 9259f85f-e34d-4327-89e2-534bbfbc48c2

PingFederate (WITGLOBAL) ist der Identity Provider für die Plato-Customer-Applikation.

Architektur (seit Umbau 2026-05-22): Backend-for-Frontend (BFF) — passt zum ursprünglichen IAM-Ticket-Inhalt.

  • BE ist OIDC-Client (openid-client v6, confidential client mit client_secret)
  • BE macht Code-Tausch, behält die Tokens
  • FE bekommt nur HTTP-only Session-Cookie via express-session
  • FE redirected bei 401 (axios-Interceptor) auf /auth/login
  • Auth-Routen: /auth/login, /oauth/callback, /auth/me, /auth/logout
  • Lokal: zusätzliche Middleware in apps/plato-customer-be/src/main.ts fängt GET / mit ?code= ab (weil IAM für localhost nur Root-Redirect-URI registriert hat)
  • Server: saubere /oauth/callback-Route, keine Root-Middleware nötig
  • Lokales Cmd: siehe project-run-commands

DEV-Endpoints und Client:

  • Issuer: https://login-dev.witglobal.net
  • Discovery: https://login-dev.witglobal.net/.well-known/openid-configuration
  • Client-ID: KONZ-PlaTo-Customer-DEV
  • Client-Secret: aus ENV OIDC_CLIENT_SECRET (server-side, nie im Browser-Bundle!)
  • Registrierte Redirect-URIs:
    • Lokal: http://localhost:3000 (Root, ohne Pfad — Exact-Match!)
    • DEV-Server: https://fahrzeugeinrichtung.apps.ocp-dev01.wgn.wuerth.com/oauth/callback
    • PROD-Server: https://fahrzeugeinrichtung.apps.ocp-01.wgn.wuerth.com/oauth/callback

Token-Eigenschaften (verifiziert 2026-05-22):

  • access_token ist ein JWT (RS512), Audience = client_id = KONZ-PlaTo-Customer-DEV
  • Claims im Access-Token: scope, client_id, iat, jti, aud, sub, uid, iss, pi.sri, exp
  • Laufzeit: 3600s
  • JWKS-URI: https://login-dev.witglobal.net/pf/JWKS (wird seit BFF von openid-client intern gehandhabt; nicht mehr direkt nötig)

User-Mapping: Nach erfolgreichem Code-Tausch wird sub (z.B. ex08802409) in libs/command/command-be/src/lib/users/user.json über UserRegistry.getUser() nachgeschlagen. Existiert kein Eintrag → 401. Marcus' Eintrag ex08802409 wurde am 2026-05-22 ergänzt (provisorisch mit marcus.hinz@adesso.de). Eine richtige User-DB ist als nächstes Thema dran (siehe project-cleanup-timeline).

Test-Rig: scripts/oidc-test.mjs — Self-contained Node-Skript (keine Deps), startet HTTP-Server auf :3000, druckt Authorize-URL, fängt Callback, tauscht Code → Token, gibt alles dekodiert aus. Vor Test: Backend stoppen (Port-Konflikt). Aufruf: CLIENT_SECRET='…' node scripts/oidc-test.mjs. ENV überschreibbar: CLIENT_ID, ISSUER, REDIRECT_URI, SCOPES, PORT. Nutzt Self-Issuing-Pattern (war zum Validieren der IdP-Anbindung gedacht, vor BFF-Umbau).

Netz-Exposure / Hardening (verifiziert 2026-05-22): Vorgelagerter Proxy/WAF antwortet ausschließlich auf die definierten OIDC-Pfade (/.well-known/... → 200, /pf/JWKS, /as/authorization.oauth2, /as/token.oauth2). Alles andere — inkl. GET / und HEAD / — wird stillschweigend geblackholed (Connection-Timeout, kein RST, kein 403). Das ist by-design und in Ordnung. Debugging-Falle: Wenn die FE-PWA "trotz nicht erreichbarem IdP läuft", ist das fast immer der Service Worker + gecachte Tokens — nicht eine offene Test-Instanz. Verifikation: DevTools → Application → Clear site data → Hard-Reload. Curl aus kalter Shell ist die ehrliche Antwort auf "ist der Server wirklich offen?".

Gotcha — redirect_uri Trailing-Slash bei lokalem BFF-Flow (gefixt 2026-05-22): PingFederate validiert redirect_uri beim Token-Tausch byte-exakt gegen den Authorize-Wert; bei DEV ist http://localhost:3000 (ohne Slash) registriert und der IdP normalisiert den Authorize-Wert mit Slash intern wieder auf den registrierten String zurück. openid-client v6 macht beim Token-Tausch aber zwangsweise stripParams(new URL(currentUrl)) → produziert http://localhost:3000/ (WHATWG-URL erzwingt pathname='/') → invalid_grant: redirect_uri value must be identical to the value included in the authorization request. Fix: customFetch-Hook in OidcService.onModuleInit patcht den outgoing URLSearchParams.redirect_uri (Body ist URLSearchParams, NICHT String/Uint8Array) und schneidet den Trailing-Slash ab. Server-Pfad (/oauth/callback) ist davon nicht betroffen.

Offene Punkte:

  • Session-Store ist MemoryStore (express-session default). Für Multi-Pod-Deployment muss Redis o.ä. rein.
  • OIDC_CLIENT_SECRET muss im Gitops-Repo als Kubernetes-Secret an den Pod gereicht werden.