Extract types, constants, helpers, and UI pieces (shared LoadingSkeleton/ EmptyState/StatusBadge/CopyButton, SSOConfigFormModal, DeleteConfirmModal, ConnectionTestPanel, SSOConfigCard, SSOUsersTable, SSOInfoSection) into _components/ and _types.ts to bring page.tsx from 1482 LOC to 339 LOC (under the 500 hard cap). Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
161 lines
7.4 KiB
TypeScript
161 lines
7.4 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { ChevronDown, ChevronUp, Globe, Info, Shield } from 'lucide-react'
|
|
|
|
export function SSOInfoSection() {
|
|
const [expandedProvider, setExpandedProvider] = useState<string | null>(null)
|
|
|
|
const providers = [
|
|
{
|
|
id: 'azure',
|
|
name: 'Microsoft Entra ID (Azure AD)',
|
|
steps: [
|
|
'Melden Sie sich im Azure Portal (portal.azure.com) an',
|
|
'Navigieren Sie zu "Microsoft Entra ID" > "App-Registrierungen" > "Neue Registrierung"',
|
|
'Geben Sie einen Namen ein (z.B. "BreakPilot Comply SSO")',
|
|
'Waehlen Sie den Kontotyp (Einzelmandant oder Mehrere Mandanten)',
|
|
'Tragen Sie die Redirect URI ein (Typ: Web)',
|
|
'Notieren Sie die Application (Client) ID und die Directory (Tenant) ID',
|
|
'Erstellen Sie unter "Zertifikate & Geheimnisse" ein neues Client Secret',
|
|
'Issuer URL: https://login.microsoftonline.com/{Tenant-ID}/v2.0',
|
|
'Optional: Konfigurieren Sie Gruppen-Claims unter "Token-Konfiguration"',
|
|
],
|
|
},
|
|
{
|
|
id: 'okta',
|
|
name: 'Okta',
|
|
steps: [
|
|
'Melden Sie sich in der Okta Admin-Konsole an',
|
|
'Navigieren Sie zu "Applications" > "Create App Integration"',
|
|
'Waehlen Sie "OIDC - OpenID Connect" und "Web Application"',
|
|
'Geben Sie einen Namen und die Redirect URI ein',
|
|
'Notieren Sie die Client ID und das Client Secret',
|
|
'Issuer URL: https://{your-domain}.okta.com',
|
|
'Weisen Sie Benutzer/Gruppen der Applikation zu',
|
|
'Optional: Konfigurieren Sie Gruppen-Claims im Authorization Server',
|
|
],
|
|
},
|
|
{
|
|
id: 'keycloak',
|
|
name: 'Keycloak',
|
|
steps: [
|
|
'Melden Sie sich in der Keycloak Admin-Konsole an',
|
|
'Waehlen Sie den gewuenschten Realm oder erstellen Sie einen neuen',
|
|
'Navigieren Sie zu "Clients" > "Create client"',
|
|
'Client Type: "OpenID Connect", geben Sie eine Client ID ein',
|
|
'Aktivieren Sie "Client authentication" und "Standard flow"',
|
|
'Tragen Sie die Redirect URI unter "Valid redirect URIs" ein',
|
|
'Kopieren Sie das Client Secret aus dem Tab "Credentials"',
|
|
'Issuer URL: https://{host}/realms/{realm-name}',
|
|
'Optional: Konfigurieren Sie Gruppen-Mapper unter "Client scopes"',
|
|
],
|
|
},
|
|
]
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* How SSO Works */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h3 className="text-lg font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Info className="w-5 h-5 text-purple-600" />
|
|
Wie funktioniert SSO?
|
|
</h3>
|
|
<div className="prose prose-sm prose-slate max-w-none">
|
|
<p className="text-sm text-slate-600">
|
|
Single Sign-On (SSO) ermoeglicht es Ihren Benutzern, sich mit den bestehenden Unternehmens-Zugangsdaten
|
|
anzumelden, ohne ein separates Passwort erstellen zu muessen. BreakPilot Comply unterstuetzt den
|
|
OpenID Connect (OIDC) Standard, der mit allen gaengigen Identity Providern kompatibel ist.
|
|
</p>
|
|
<div className="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div className="bg-slate-50 rounded-lg p-4">
|
|
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
|
<span className="font-bold text-sm">1</span>
|
|
</div>
|
|
<h4 className="font-medium text-slate-900 text-sm">Konfiguration</h4>
|
|
<p className="text-xs text-slate-500 mt-1">
|
|
Verbinden Sie Ihren Identity Provider (Azure AD, Okta, Keycloak, etc.) ueber OIDC.
|
|
</p>
|
|
</div>
|
|
<div className="bg-slate-50 rounded-lg p-4">
|
|
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
|
<span className="font-bold text-sm">2</span>
|
|
</div>
|
|
<h4 className="font-medium text-slate-900 text-sm">Authentifizierung</h4>
|
|
<p className="text-xs text-slate-500 mt-1">
|
|
Benutzer werden zum Identity Provider weitergeleitet und melden sich dort an.
|
|
</p>
|
|
</div>
|
|
<div className="bg-slate-50 rounded-lg p-4">
|
|
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
|
<span className="font-bold text-sm">3</span>
|
|
</div>
|
|
<h4 className="font-medium text-slate-900 text-sm">Provisionierung</h4>
|
|
<p className="text-xs text-slate-500 mt-1">
|
|
Benutzerkonten werden automatisch angelegt und Rollen ueber Gruppen-Mappings zugewiesen.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Provider Setup Guides */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<h3 className="text-lg font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
|
<Globe className="w-5 h-5 text-purple-600" />
|
|
Einrichtungsanleitungen
|
|
</h3>
|
|
<div className="space-y-3">
|
|
{providers.map(provider => (
|
|
<div key={provider.id} className="border border-slate-200 rounded-lg">
|
|
<button
|
|
onClick={() =>
|
|
setExpandedProvider(expandedProvider === provider.id ? null : provider.id)
|
|
}
|
|
className="w-full px-4 py-3 flex items-center justify-between hover:bg-slate-50 transition-colors rounded-lg"
|
|
>
|
|
<span className="font-medium text-slate-900 text-sm">{provider.name}</span>
|
|
{expandedProvider === provider.id ? (
|
|
<ChevronUp className="w-4 h-4 text-slate-400" />
|
|
) : (
|
|
<ChevronDown className="w-4 h-4 text-slate-400" />
|
|
)}
|
|
</button>
|
|
{expandedProvider === provider.id && (
|
|
<div className="px-4 pb-4">
|
|
<ol className="space-y-2">
|
|
{provider.steps.map((step, idx) => (
|
|
<li key={idx} className="flex gap-3 text-sm text-slate-600">
|
|
<span className="w-5 h-5 bg-purple-100 text-purple-700 rounded-full flex items-center justify-center text-xs font-medium flex-shrink-0 mt-0.5">
|
|
{idx + 1}
|
|
</span>
|
|
<span>{step}</span>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Security Note */}
|
|
<div className="bg-purple-50 border border-purple-200 rounded-lg p-4">
|
|
<div className="flex items-start gap-3">
|
|
<Shield className="w-5 h-5 text-purple-600 mt-0.5 flex-shrink-0" />
|
|
<div>
|
|
<h4 className="font-medium text-purple-900 text-sm">Sicherheitshinweis</h4>
|
|
<p className="text-sm text-purple-700 mt-1">
|
|
Client Secrets werden verschluesselt gespeichert und sind nach der Eingabe nicht mehr einsehbar.
|
|
Aktivieren Sie Auto-Provisioning nur, wenn Sie sicherstellen koennen, dass nur autorisierte
|
|
Benutzer Zugang zum Identity Provider haben. Verwenden Sie Rollen-Mappings, um die
|
|
Berechtigungen Ihrer Benutzer granular zu steuern.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|