Add explicit "link passkey to my account" flow
Signing in by passkey on a fresh install created a new empty account because the seeded admin has no email to match on. Add canonical SSO-style linking: an authenticated user starts an OIDC flow whose `state` is a signed, short-lived "link to user N" token (purpose=pocketid-link). The callback detects that state and attaches the returned identity to that account instead of creating/matching one — no reliance on emails lining up, and no group gating (the initiator is already authorised; this is identity linking, not access control). - auth.py: _make_link_state/_decode_link_state, GET /pocketid/link-url, callback handles state (rejects if the passkey is already on another account → auth_error=passkey_in_use). Expose has_passkey on /auth/me. - Profile: "Passkey sign-in" section for all users — shows linked state or a "Link a passkey to this account" button; success banner on return. - Login: messages for passkey_in_use / link_failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,17 @@ import { useAuthStore } from '../hooks/useAuth'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import api from '../utils/api'
|
||||
|
||||
const AUTH_ERRORS = {
|
||||
not_authorized: "Your account isn't permitted to access MileVault — ask the admin to add you to the allowed group.",
|
||||
passkey_in_use: "That passkey is already linked to another account. Sign in to that account, or have an admin remove it on the Users page, then try linking again.",
|
||||
link_failed: "Couldn't link the passkey. Please try again.",
|
||||
}
|
||||
|
||||
export default function LoginPage() {
|
||||
const [username, setUsername] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const authError = new URLSearchParams(window.location.search).get('auth_error')
|
||||
const [error, setError] = useState(
|
||||
authError === 'not_authorized'
|
||||
? "Your account isn't permitted to access MileVault — ask the admin to add you to the allowed group."
|
||||
: ''
|
||||
)
|
||||
const [error, setError] = useState(AUTH_ERRORS[authError] || '')
|
||||
const { login, isLoading } = useAuthStore()
|
||||
const navigate = useNavigate()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user