[2.x] feat(core): redirect-only OAuth flow — rewrite ResponseFactory#4461
Merged
[2.x] feat(core): redirect-only OAuth flow — rewrite ResponseFactory#4461
Conversation
Replace the HtmlResponse popup approach with a proper RedirectResponse flow throughout Forum\Auth\ResponseFactory: - Logged-in users: redirect to returnTo with remember-me cookie set. - Email-match users: auto-link provider then same redirect. - New users: redirect to returnTo with _flarum_auth=<token> appended so the frontend can open the SignUpModal without any JS window tricks. Remove authenticationComplete() from ForumApplication — it existed only to call window.opener callbacks from the popup flow. The returnTo parameter must be validated by the caller (AbstractOAuth- Controller::validateReturnTo) before being passed to make(); this class trusts it is a safe same-origin path. Add unit and integration test coverage for Registration, ResponseFactory and LoginProvider. BREAKING CHANGE: ResponseFactory::make() now requires a $returnTo string as the fourth argument, and returns a RedirectResponse instead of an HtmlResponse. Extensions or custom OAuth controllers that call make() directly must be updated. authenticationComplete() is removed from ForumApplication.
Merged
9 tasks
Member
Author
|
Companion PR: FriendsOfFlarum/oauth#109 — both must be merged together. |
- Registration::$payload initialised to null to prevent "must not be accessed before initialization" error on getPayload() when nothing has been provided. - ResponseFactoryTest: remove makeLoggedInResponse unit tests that hit RememberAccessToken::generate() → Eloquent DB connection. The logged- in redirect path is already covered by the integration test suite; unit tests now only cover URL construction logic for the registration response (which needs no DB).
8167041 to
fae5776
Compare
…e-population
Redirect-based OAuth flows (e.g. fof/oauth) bounce the user back to the forum
with a _flarum_auth query param carrying a RegistrationToken. Previously there
was no way to resolve that token back to username/email/provided fields without
a round-trip through the popup authenticationComplete callback.
- Add GET /api/registration-tokens/{token} — returns username, email, and the
provided[] field list. Provider name, identifier, and payload internals are
NOT exposed. The token acts as its own credential; no auth required.
- Store suggested fields (suggestUsername, suggestEmail) in the token payload
under a 'suggested' key so they survive the redirect.
- Add RegistrationTokenResource to ApiServiceProvider.
- Integration tests: 15 cases covering happy paths, all field combinations,
security (sensitive fields absent), expiry, and rejected write methods.
- ResponseFactory integration test: assert suggested fields land in payload.
…up pre-population
Redirect-based OAuth flows return the user to the forum with a
_flarum_auth token in the URL. The frontend needs to resolve that token
to username/email/provided[] before opening the SignUpModal.
Using POST (body: {token}) rather than GET /{token} keeps the token out
of server access logs, browser history, and Referer headers.
- ResolveRegistrationTokenController: accepts {token} in POST body,
returns {username, email, provided[]}. Provider name, identifier, and
payload internals are not exposed. Returns 404 for invalid/expired tokens.
- Route: POST /api/registration-token (name: registration-token)
- CSRF exempt (same pattern as /api/token login endpoint)
- Also stores suggested fields in token payload so they survive the redirect
(ResponseFactory change from previous commit)
- 15 integration tests: happy paths, field combinations, security
(sensitive fields absent), expiry, and rejected HTTP methods
Username, Nickname (when flarum-nicknames is active), Email and Password fields now display a <label> above the input so they are clearly distinguishable when pre-filled from an OAuth redirect — previously placeholder text disappears once a value is present, making Username and Nickname look identical. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o-link
When an OAuth login auto-links a user via email match, the redirect now
includes _flarum_linked={provider} so the frontend can show the
AccountLinkedModal informing the user their accounts have been connected.
…Response protected, move _flarum_linked URL-building into make() Extensions can now override either method to customise the login redirect or registration handoff without needing to touch _flarum_linked logic. Clean signature: makeLoggedInResponse(User, string) with no optional params. Adds regression test asserting returning users do not get _flarum_linked appended.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR is one half of a two-part OAuth overhaul. The companion PR is FriendsOfFlarum/oauth#109 — both must be merged together.
Changes
ResponseFactory::make()now accepts a$returnTostring and returns aRedirectResponsein all cases. Logged-in users are redirected with a remember-me cookie; new users are redirected with_flarum_auth=<token>appended so the frontend can openSignUpModal.ResponseFactorystores suggested fields (username, email) in theRegistrationTokenpayload under asuggestedkey so they survive the redirect and can be returned to the frontend.ResponseFactory::makeLoggedInResponse()andmakeRegistrationResponse()are nowprotected— extensions can subclass and override either method to customise the login redirect or registration handoff._flarum_linkedURL-building is handled inmake()before the call, keeping both method signatures clean and stable._flarum_linked={provider}param — appended to the redirect URL when a user's account is linked to an OAuth provider for the first time (email-match auto-link path). The companion fof/oauth PR does the same for the manual security-page link flow. The frontend detects the param and shows anAccountLinkedModal.POST /api/registration-token— new endpoint (ResolveRegistrationTokenController) that accepts a token in the POST body and returns onlyusername,email, andprovided[]. Provider name, identifier, and payload internals are never exposed. Token in POST body keeps it out of server access logs, browser history, and Referer headers.registration-tokenadded to CSRF exempt paths — unauthenticated POST is allowed since token possession is the credential.ForumApplication::authenticationComplete()removed — it existed solely for the popup JS callback path.SignUpModalfield labels — Username, Email, and Password fields now show a visible<label>above the input. Nicknames extension's Nickname field updated the same way. Fixes the OAuth pre-fill UX where placeholder text disappears once a value is present, making Username and Nickname look identical.Registration,ResponseFactory,LoginProvider, andResolveRegistrationTokenController.ResponseFactory::make()signature adds a requiredstring $returnTofourth argumentreturnToURL; defaults to'/'ResponseFactory::make()returnsRedirectResponseinstead ofHtmlResponseForumApplication::authenticationComplete()removed_flarum_authfrom the URL on bootAny extension with a custom OAuth controller that calls
ResponseFactory::make()directly must be updated.Test plan
returnTowith_flarum_authparam, SignUpModal opens pre-populated with username/emailreturnTowith remember cookie and no_flarum_linkedparam_flarum_linked={provider}, AccountLinkedModal appearsPOST /api/registration-tokenreturns username/email/provided for valid tokenPOST /api/registration-tokenreturns 404 for invalid/expired/missing tokenphp vendor/bin/phpunit framework/core/tests/unit/Forumphp vendor/bin/phpunit framework/core/tests/integration/forum/Authphp vendor/bin/phpunit framework/core/tests/integration/api/registration_tokens