Summary#
- The OAuth consent page previously used
get_single_account_did()— a single-user PDS shortcut that issued auth codes to anyone who clicked Approve with no identity verification. This is wrong for a multi-user relay where many identities share the same server. - The consent page now collects a handle/DID and password, verifies them via the same
Argon2id path as
createSession, and re-renders with an error on failure rather than redirecting the client withaccess_denied. - The ATProto
login_hintquery parameter is honoured: clients can pre-populate the identifier field by including it in the authorization redirect.
Changes#
- Remove
get_single_account_didfromdb/oauth(single-user assumption eliminated) resolve_identifier,verify_password,AccountRowpromoted topub(crate)increate_sessionso the consent handler reuses the same credential path- Identifier + password inputs added to the consent page HTML/CSS
POST /oauth/authorizeverifies credentials before issuing an authorization code- Pre-existing
clippy::too_many_argumentsonpromote_accountsuppressed with allow attr - Pre-existing rustfmt drift in
app.rsimport order corrected
Test plan#
-
cargo test -p relay oauth_authorize— 30 tests pass (6 new credential-gate tests) - Manually open
/oauth/authorizewith a validclient_id— confirm identifier and password fields appear,login_hintpre-populates the identifier field - Submit with wrong password — confirm form re-renders with "Invalid credentials."
- Submit with correct credentials — confirm redirect to
redirect_uri?code=... - Submit deny — confirm redirect with
error=access_denied(no credentials required)