Skip to content

[3.0] Theme split (wave 4, part 13) — make the login form's ajax submit actually run - #9430

Open
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/theme-login-script
Open

[3.0] Theme split (wave 4, part 13) — make the login form's ajax submit actually run#9430
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/theme-login-script

Conversation

@albertlast

Copy link
Copy Markdown
Collaborator

Description

Part of the #7933 split (wave 4, part 13). Login area.

The login form's ajax submit has never run. The top menu opens it through
reqOverlayDiv(), which hands the response to smc_Popup.setBody(), which
assigns innerHTML — and innerHTML does not execute <script> elements. So
the generated handler sits in the DOM as inert markup and the overlay falls back
to a plain submit: the member leaves the page they were on and lands at
?action=login2 instead of being logged in where they stood. The focus() call
in the same block never ran either.

Checked on release-3.0 by opening the overlay and dispatching a cancelable
submit at the form: nothing prevents it, and jQuery has no handlers bound to
it.

Where it did run, it could still be a syntax error. The branch for a CORS
origin that is not the forum itself opens an else and never closes it:

    else {
        window.location.reload();

    },
    error: function(xhr) {

The brace meant for success: function(data) { closes the else instead, so
$.ajax() never parses. Served to an allowed origin, the whole block dies:

$ curl -H 'Origin: http://example.test' -H 'X-SMF-AJAX: 1' \
      'http://localhost/index.php?action=login;ajax' | extract-script | node --check
SyntaxError: Unexpected token ','

And that branch is reached more often than intended. The guard deciding
whether to emit the handler tests

!in_array(Utils::$context['valid_cors_found'], ['same', 'subsite'])

'subsite' is not a value that exists. Security::corsPolicyHeader() only ever
sets 'same', 'subdomain', 'alias', 'additional' or 'wildcard', and
User.php:2407 spells the same check ['same', 'subdomain']. A subdomain origin
is trusted everywhere else in SMF and should be submitting the form plainly;
instead it fell into the broken branch.

What changes

The handler moves to Themes/default/scripts/login.js, delegated from the
document
, so a form that arrives through innerHTML is covered like any other
— that is what makes the overlay work. The form opts in by carrying
data-ajax-login, whose value is what corsPolicyHeader() decided, so the
PHP branching inside the JavaScript goes away entirely.

Guests load the file with the page. That is not incidental: it is the only way
the code can be present when the overlay opens, since the ajax response has no
template layers and cannot bring its own script. alerts.js is loaded the same
way for members, for the same reason.

It also sends X-Requested-With, which jQuery added on its own and which
Login2::checkAjax() looks for. Without it the response to the submit comes back
as a full page rather than a fragment.

The setTimeout(...).focus() block is left exactly as it was. It is inert in the
overlay for the same innerHTML reason, but it works on the full page and it is
not what this is about.

Testing

In the overlay, on this branch: a wrong password leaves the page alone and shows
the error inside the overlay, with the form and a fresh token behind it; the
right password then logs in without navigating. On the full page the form has no
attribute and submits normally.

With CORS enabled, an allowed additional origin gets data-ajax-login="additional"
and a subdomain origin gets no attribute at all. Every emitted script block passes
node --check.

Issues References (Fixes|Related|Closes)

Related to #7933

The login form the top menu opens has a submit handler generated into it, but
nothing has ever executed it. reqOverlayDiv() hands the response to
smc_Popup.setBody(), which assigns innerHTML, and innerHTML does not run script
elements. So the overlay has been falling back to a plain submit: the member
leaves the page they were on and lands at ?action=login2 instead of being logged
in where they stood. The focus() call in the same block never ran either.

Where the block did run, it could still be broken. The branch for a CORS origin
that is not the forum itself opens an else and never closes it:

	else {
		window.location.reload();

	},
	error: function(xhr) {

so the brace meant for success: function(data) closes the else instead, and the
$.ajax() call never parses. Served to an allowed origin, the whole script block
is a SyntaxError.

That branch is also reached more often than intended, because the guard deciding
whether to emit the handler at all tests

	!in_array(Utils::$context['valid_cors_found'], ['same', 'subsite'])

and 'subsite' is not a value that exists. corsPolicyHeader() only ever sets
'same', 'subdomain', 'alias', 'additional' or 'wildcard', and User.php spells the
same check ['same', 'subdomain']. A subdomain origin is trusted everywhere else
and should be submitting the form plainly; instead it took the broken branch.

The handler moves to Themes/default/scripts/login.js, delegated from the document
so that a form arriving through innerHTML is covered like any other, and the form
opts in with data-ajax-login carrying what corsPolicyHeader() decided. Guests
load the file with the page, because that is the only way it can be there when
the overlay opens. Nothing is generated into the page any more, so the PHP
branching inside the JavaScript goes with it.

It also sends X-Requested-With, which jQuery used to add on its own and which
Login2::checkAjax() looks for.

Verified in the overlay: a wrong password now leaves the page alone and shows the
error in the overlay with the form and a fresh token behind it, and the right
password logs in without navigating. On the full page the form has no attribute
and submits normally. With CORS on, an allowed additional origin gets
data-ajax-login="additional" and a subdomain gets no attribute at all.

Signed-off-by: Mathias Albert <mathiaspapealbert@hotmail.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@jdarwood007 jdarwood007 added this to the 3.0 Alpha 5 milestone Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants