Skip to content
Open
Changes from all commits
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
41 changes: 36 additions & 5 deletions src/Actions/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,43 @@ 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
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
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.


// Update the expiration date in the server-side session record
// (wp_set_auth_cookie does not do this when a token is supplied).
$manager = \WP_Session_Tokens::get_instance( $userId );
$session = $manager->get( $token );

if ( ! is_array( $session ) ) {
return;
}

$session['expiration'] = time() + $expiration;
$manager->update( $token, $session );

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