OIDC-Integration: Keycloak-Login (Authorization Code Flow + PKCE), app-seitige Rollen bleiben unangetastet

This commit is contained in:
Kühn
2026-09-15 11:41:29 +02:00
parent 1d03ab498f
commit 1ee37c402a
9 changed files with 420 additions and 6 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext';
import { API_BASE } from '../utils/api';
export default function AuthModal() {
const { login, register } = useAuth();
@@ -11,6 +12,22 @@ export default function AuthModal() {
const [success, setSuccess] = useState('');
const [loading, setLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [oidcConfigured, setOidcConfigured] = useState(false);
// OIDC-Verfügbarkeit + Fehler aus dem Callback (als Query-Parameter) laden
useEffect(() => {
fetch(`${API_BASE}/auth/oidc/status`)
.then((res) => (res.ok ? res.json() : { configured: false }))
.then((data) => setOidcConfigured(!!data.configured))
.catch(() => setOidcConfigured(false));
const params = new URLSearchParams(window.location.search);
const oidcError = params.get('oidcError');
if (oidcError) {
setError(oidcError);
// Parameter aus der URL entfernen (sauberer Zustand bei Reload)
window.history.replaceState({}, '', window.location.pathname);
}
}, []);
const handleSubmit = async (e) => {
e.preventDefault();
@@ -138,6 +155,20 @@ export default function AuthModal() {
<button className="btn btn-outline btn-sm w-full" onClick={toggleMode}>
{mode === 'login' ? 'Neuen Account erstellen' : 'Zurück zur Anmeldung'}
</button>
{/* OIDC (Keycloak) — nur angezeigt, wenn serverseitig konfiguriert */}
{oidcConfigured && (
<>
<div className="divider text-sm">Single Sign-On</div>
<a
href={`${API_BASE}/auth/oidc/login`}
className="btn btn-secondary w-full"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 7a2 2 0 012 2m4 2a8 8 0 01-8 8m0 0a8 8 0 01-8-8 8 8 0 018-8 8 8 0 018 8m-6 4h.01M12 15v.01" /></svg>
Mit Unternehmens-Konto anmelden
</a>
</>
)}
</div>
</div>
</div>