Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/Actions/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,37 @@ public function onShutdown(): void
if ('false' !== $this->getPlugin()->getOption('sessions', 'rolling_sessions')) {
$store = $this->getSdk()->configuration()->getSessionStorage();

/**
* @var CookieStore $store
*/
$store->setState(true);
if ($store instanceof CookieStore) {
$store->setState(true);
}

// Extend the existing session token's expiry and reissue the browser cookies.
//
// The naive approach — calling wp_set_auth_cookie() with no token — rotates the
// session token. Because nonces are cryptographically bound to the session token,
// any nonce generated during the current request (with the old token) becomes
// invalid the moment the new cookie is sent, causing REST requests to fail with
// rest_cookie_invalid_nonce.
//
// wp_set_auth_cookie() accepts a $token argument. Passing the existing token
// reissues the browser cookies with a fresh expiration without rotating the token,
// so nonces remain valid and the full rolling-session behaviour is preserved.
$userId = get_current_user_id();
$token = wp_get_session_token();

if ('' !== $token) {
/** This filter is documented in wp-includes/pluggable.php */
$expiration = apply_filters('auth_cookie_expiration', 14 * DAY_IN_SECONDS, $userId, true);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 14 * DAY_IN_SECONDS default mirrors what WordPress core uses inside wp_set_auth_cookie(), but it's an implicit coupling. If core ever changes that default, these two would diverge.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I'm not sure what the best default value to use here is anyway, so I just went with the logic from core. Maybe the default should match the Auth0 session expiration lifetime, since we have access to that?

Regardless, sites can modify this using the core "auth_cookie_expiration" filter.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The likelihood of core changing that default is very very low, and if you have to choose some other value regardless then you've already diverged. Given there are settings for this in the admin anyway it doesn't feel like this should be a blocker to me at least.


// Update the server-side session record (wp_set_auth_cookie does not do this
// when a token is supplied).
\WP_Session_Tokens::get_instance($userId)->update($token, [
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WP_Session_Tokens::update() merges into existing session data. Just confirming , is there any session metadata beyond expiration that should also be refreshed for rolling sessions?

Copy link
Copy Markdown
Author

@goldenapples goldenapples Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, apparently I misunderstood how the token manager handles updates. Actually, from what I see, WP_Session_Tokens::update() overwrites all the data attached to the session, which would wipe out useful audit data like IP address, user agent, and original login date; as well as any custom data attached with the attach_session_information filter.

I think it's better here to read the existing token and only update the "expiration" field on it. Updated in dfbde56.

'expiration' => time() + $expiration,
]);

wp_set_auth_cookie(get_current_user_id(), true);
// Reissue the browser cookies with the same token and new expiration.
wp_set_auth_cookie($userId, true, '', $token);
}
}
}

Expand Down