feat: Begin support for OIDC login
This commit is contained in:
@@ -14,7 +14,7 @@ function App() {
|
||||
checkAuthState()
|
||||
|
||||
// Listen for auth changes
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((event: string, session: any) => {
|
||||
console.log('Auth state changed:', event, !!session)
|
||||
setIsAuthenticated(!!session)
|
||||
setLoading(false)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { supabase } from '../lib/supabase'
|
||||
import { MicrosoftIcon } from './MicrosoftIcon'
|
||||
|
||||
interface LoginProps {
|
||||
onLoginSuccess: () => void
|
||||
@@ -10,6 +11,7 @@ export function Login({ onLoginSuccess }: LoginProps) {
|
||||
const [password, setPassword] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const enableMicrosoftLogin = import.meta.env.VITE_ENABLE_MICROSOFT_LOGIN === 'true'
|
||||
|
||||
const handleLogin = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
@@ -35,6 +37,32 @@ export function Login({ onLoginSuccess }: LoginProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const handleMicrosoftLogin = async () => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
const { error } = await supabase.auth.signInWithOAuth({
|
||||
provider: 'azure',
|
||||
options: {
|
||||
scopes: 'email openid profile',
|
||||
redirectTo: `${window.location.origin}/`,
|
||||
},
|
||||
})
|
||||
|
||||
if (error) {
|
||||
setError(error.message)
|
||||
setLoading(false)
|
||||
}
|
||||
// If successful, user will be redirected to Microsoft login
|
||||
// and then back to the app, so we don't stop loading here
|
||||
} catch (err) {
|
||||
setError('An unexpected error occurred during Microsoft login')
|
||||
console.error('Microsoft login error:', err)
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900">
|
||||
<div className="max-w-md w-full space-y-8">
|
||||
@@ -108,6 +136,33 @@ export function Login({ onLoginSuccess }: LoginProps) {
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{enableMicrosoftLogin && (
|
||||
<>
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-gray-300 dark:border-gray-700" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-sm">
|
||||
<span className="px-2 bg-gray-50 dark:bg-gray-900 text-gray-500 dark:text-gray-400">
|
||||
Or continue with
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleMicrosoftLogin}
|
||||
disabled={loading}
|
||||
className="w-full flex items-center justify-center gap-3 py-2 px-4 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<MicrosoftIcon className="w-5 h-5" />
|
||||
<span>Sign in with Microsoft</span>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export function MicrosoftIcon({ className = "w-5 h-5" }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 23 23" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#f3f3f3" d="M0 0h23v23H0z" />
|
||||
<path fill="#f35325" d="M1 1h10v10H1z" />
|
||||
<path fill="#81bc06" d="M12 1h10v10H12z" />
|
||||
<path fill="#05a6f0" d="M1 12h10v10H1z" />
|
||||
<path fill="#ffba08" d="M12 12h10v10H12z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ interface ImportMetaEnv {
|
||||
readonly VITE_SUPABASE_URL: string;
|
||||
readonly VITE_SUPABASE_ANON_KEY: string;
|
||||
readonly VITE_VISION_API_URL?: string; // optional; defaults to "/api" via vite proxy
|
||||
readonly VITE_ENABLE_MICROSOFT_LOGIN?: string; // optional; enable Microsoft Entra authentication
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
||||
Reference in New Issue
Block a user