feat: implement OAuth 2.0 / OpenID Connect support
Some checks failed
Build & Push Docker Image / build (push) Failing after 1m12s

- Added OAuth configuration management in the admin panel.
- Implemented OAuth authorization flow with PKCE for enhanced security.
- Created routes for handling OAuth provider discovery, authorization, and callback.
- Integrated OAuth login and registration options in the frontend.
- Updated UI components to support OAuth login and registration.
- Added internationalization strings for OAuth-related messages.
- Implemented encryption for client secrets and secure state management.
- Added error handling and user feedback for OAuth processes.
This commit is contained in:
2026-03-04 08:54:25 +01:00
parent e22a895672
commit cdfc585c8a
14 changed files with 1039 additions and 10 deletions

View File

@@ -3,7 +3,7 @@ import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { useLanguage } from '../contexts/LanguageContext';
import { useBranding } from '../contexts/BrandingContext';
import { Mail, Lock, User, ArrowRight, Loader2, CheckCircle, ShieldAlert } from 'lucide-react';
import { Mail, Lock, User, ArrowRight, Loader2, CheckCircle, ShieldAlert, LogIn } from 'lucide-react';
import BrandLogo from '../components/BrandLogo';
import toast from 'react-hot-toast';
@@ -19,7 +19,7 @@ export default function Register() {
const [needsVerification, setNeedsVerification] = useState(false);
const { register } = useAuth();
const { t } = useLanguage();
const { registrationMode } = useBranding();
const { registrationMode, oauthEnabled, oauthDisplayName } = useBranding();
const navigate = useNavigate();
// Invite-only mode without a token → show blocked message
@@ -197,6 +197,26 @@ export default function Register() {
</button>
</form>
{oauthEnabled && (
<>
<div className="relative my-6">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-th-border" />
</div>
<div className="relative flex justify-center text-xs">
<span className="px-3 bg-th-card/80 text-th-text-s">{t('auth.orContinueWith')}</span>
</div>
</div>
<a
href="/api/oauth/authorize"
className="btn-secondary w-full py-3 flex items-center justify-center gap-2"
>
<LogIn size={18} />
{t('auth.registerWithOAuth').replace('{provider}', oauthDisplayName || 'SSO')}
</a>
</>
)}
<p className="mt-6 text-center text-sm text-th-text-s">
{t('auth.hasAccount')}{' '}
<Link to="/login" className="text-th-accent hover:underline font-medium">