- Make authorization-code redemption atomic: claim the code with a guarded
delete inside the transaction that creates the authorization, so concurrent
exchanges can't both issue a token (RFC 6749 4.1.3)
- Compare the token request's client_id host to the code's stored client_id
(defense-in-depth alongside the exact redirect_uri match)
- Reject unknown response_type values with unsupported_response_type
- Validate the PKCE code_challenge (43-128 unreserved chars, S256) so a client
can't persist an over-long or malformed challenge
- Return invalid_request for missing token-endpoint parameters, and set
Cache-Control: no-store on error responses too
- Use the right separator when the redirect_uri already has a query string
- Look codes up through the active scope; drop the unused consume!; serialize
permissions as JSON
- Purge abandoned authorization codes via a recurring Solid Queue task
Part of #254
Implements the optional OAuth 2.0 Authorization Code grant with PKCE
(RFC 7636) for remoteStorage, as described in the remoteStorage spec
(section 10.1).
- Advertise the authorization and token endpoints plus the supported
code_challenge method (S256) in WebFinger, and bump the advertised
spec version to draft-dejong-remotestorage-27
- Add RsAuthorizationCode: a short-lived (5 min), single-use authorization
code stored only as a SHA256 digest
- Add RsOauthManager services for issuing and exchanging codes, including
S256 verification
- Add a cross-origin POST /rs/oauth/token endpoint that exchanges a code
(and code_verifier) for an access token, with CORS and no CSRF token
- Consent dialog now carries response_type / code_challenge through the
form and redirects with the code in the query string for the code flow
- Remove the existing-token reuse shortcut so every authorization results
in a distinct authorization (and token)
Part of #254
The admin "Default services" setting writes the LDAP serviceEnabled
attribute, but remoteStorage access was also gated behind an unused
per-user Flipper flag that nothing ever enabled, so remoteStorage was
inaccessible for everyone.
Gate remoteStorage on service_enabled? like the other services, and make
the admin toggle reflect the LDAP attribute (this also fixes it reading
current_user instead of the user being viewed). E-Mail keeps its Flipper
gate for now.
Wire Users::DeviseController as Devise parent controller with the
Turbo-aware responder, so failed form submissions (login, password
reset) render correctly as HTML with 422 status instead of
unprocessable turbo-stream content that Turbo silently drops.
Also fixes a NameError in the responder (rendering_options ->
error_rendering_options) and removes the dead TurboController.
Add a new service to import some data from Mastodon accounts:
* Find users by username, store Mastodon account ID in local db when
found
* Import display name (don't overwrite existing)
* Import avatar (don't overwrite existing)
Variants are currently broken. So we process the original file with the
most common avatar dimensions and stripping metadata, then hash and
upload only that version.