Opened 4 months ago
Last modified 4 months ago
#61874 new defect (bug)
Unable to access WordPress login session during login
Reported by: | dd32 | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | Users | Keywords: | |
Focuses: | Cc: |
Description (last modified by )
WordPress Sessions are based on a Key which is stored in the Auth cookies, and during each login a new session is initiated.
This session token value is only stored in the authentication cookie. In order to retrieve it, the auth cookies must be set in $_COOKIE
, which is only done by a client-request.
This leads to an awkward situation, where WordPress will create a login session, create cookies based on it, and then have no ability to let any further executed code know the session details.
To complicate matters, the logic for retrieving the current user is awkward as Core applies two different methodologies between login and logout:
wp_signon()
doesn't set the$current_user
upon login (#39385) despitewp_logout()
clears the$current_user
global upon logout (#35488)
As a result of that, during the login_redirect
filter the user will be logged out, and during the logout_redirect
filter the user will also be logged out (despite the user being logged in according to the cookies superglobal).
For example, the following code does two things:
- Sets additional data in the user session on login (Similar to the Two-Factor plugin)
- Hooks to
login_redirect
filter with the intention of acting upon data in the current user session.
<?php add_filter( 'attach_session_information', function( $session ) { $session['foo'] = 'bar'; return $session; } ); add_filter( 'login_redirect', function( $redirect, $orig_redirect, $user ) { var_dump( [ 'variant' => 'Current', '$user->ID' => $user->ID, 'get_current_user_id()' => get_current_user_id(), 'wp_get_session_token()' => wp_get_session_token(), 'session_data' => WP_Session_Tokens::get_instance( $user->ID )->get( wp_get_session_token() ) ] ); die(); }, 10, 3 );
which results in this output:
wp-content/mu-plugins/example.php: array (size=5) 'variant' => string 'Current' (length=7) '$user->ID' => int 1 'get_current_user_id()' => int 0 'wp_get_session_token()' => string '' (length=0) 'session_data' => null
tl;dr: It's not possible (without hoops, see comments) to retrieve the current user session data after login.
Change History (4)
#2
follow-up:
↓ 3
@
4 months ago
One partial option is that we could have wp_set_auth_cookie()
fill in the $_COOKIE super-global when setting cookies, this would have the effect of allowing wp_get_session_token()
to operate, but would not set the current user global:
-
wp-includes/pluggable.php
1090 1090 return; 1091 1091 } 1092 1092 1093 $_COOKIE[ $auth_cookie_name ] = $auth_cookie; 1094 $_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie; 1095 1093 1096 setcookie( $auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true ); 1094 1097 setcookie( $auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true ); 1095 1098 setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true );
which would result in this:
wp-content/mu-plugins/example.php: array (size=5) 'variant' => string 'Diff' (length=4) '$user->ID' => int 1 'get_current_user_id()' => int 0 'wp_get_session_token()' => string '8XpzO0LxNDfqeHHaHduytWPFVWKYjnfBounb39FfPhK' (length=43) 'session_data' => array (size=7) 'foo' => string 'bar' (length=3) ....
Still not perfect, as now wp_get_session_token()
can determine the current user session, but it's apparently for no user, as no user is logged in, as a result of the outcome of #39385.
#3
in reply to:
↑ 2
@
4 months ago
Replying to dd32:
However, that fits nicely with this next edge-case:
Going back to the logout_redirect
filter, it's also possible to retrieve the session token at that point in time, although the data will have been lost (although the token is still known):
<?php add_filter( 'logout_redirect', function( $redirect, $requested_redirect_to, $user ) { var_dump( [ 'variant' => 'logout_redirect', 'is_user_logged_in()' => is_user_logged_in(), '$user->ID' => $user->ID, 'get_current_user_id()' => get_current_user_id(), 'wp_get_session_token()' => wp_get_session_token(), 'session_data' => WP_Session_Tokens::get_instance( $user->ID )->get( wp_get_session_token() ), ] ); die(); }, 10, 3 );
which generates:
wp-content/mu-plugins/example.php: array (size=6) 'variant' => string 'logout_redirect' (length=15) 'is_user_logged_in()' => boolean false '$user->ID' => int 1 'get_current_user_id()' => int 0 'wp_get_session_token()' => string '8XpzO0LxNDfqeHHaHduytWPFVWKYjnfBounb39FfPhK' (length=43) 'session_data' => null
Again.. the session token is known during logout, but the current user global is unset and what data was in the session has been lost.
There is a workaround, by watching for a cookie set action:
which then does allow access to the session data: