Skip to content

Commit

Permalink
feat(Cookies): Updates WP Cookie Expiration to Same as Session Length (
Browse files Browse the repository at this point in the history
…#514)

* Add remember me feature via a filter

Signed-off-by: Menno van den Ende <[email protected]>

* fix phpcs errors

* add unit test

* use refresh token expiration as cookie expiration

* only allow using token expiration if remember-me is enabled

* fix hook name

* fix expiration in remove filter of unit test

---------

Signed-off-by: Menno van den Ende <[email protected]>
Co-authored-by: Tim Nolte <[email protected]>
  • Loading branch information
menno-ll and timnolte authored Mar 22, 2024
1 parent b00f7ca commit e0c8229
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 5 deletions.
40 changes: 38 additions & 2 deletions includes/openid-connect-generic-client-wrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ class OpenID_Connect_Generic_Client_Wrapper {
*/
private $error = false;

/**
* Used to pass the openid token refresh expiration time to the auth_cookie_expiration filter.
*
* @var integer
*/
private $openid_token_refresh_expires_in = 0;

/**
* Inject necessary objects and services into the client.
*
Expand Down Expand Up @@ -672,11 +679,24 @@ public function login_user( $user, $token_response, $id_token_claim, $user_claim
// Allow plugins / themes to take action using current claims on existing user (e.g. update role).
do_action( 'openid-connect-generic-update-user-using-current-claim', $user, $user_claim );

// Determine the amount of days before the cookie expires.
$remember_me = apply_filters( 'openid-connect-generic-remember-me', false, $user, $token_response, $id_token_claim, $user_claim, $subject_identity );
$expiration_days = $remember_me ? 14 : 2;
$wp_expiration_days = $remember_me ? 14 : 2;

// If remember-me is enabled, and using token expiration is enabled,
// add a filter to overwrite the default cookie expiration with the
// openid token expiration.
if (
$remember_me
&& apply_filters( 'openid-connect-generic-use-token-refresh-expiration', false )
&& ( $token_response['refresh_expires_in'] ?? 0 )
) {
$this->openid_token_refresh_expires_in = $token_response['refresh_expires_in'];
add_filter( 'auth_cookie_expiration', array( $this, 'set_cookie_expiration_to_openid_token_refresh_expiration' ) );
}

// Create the WP session, so we know its token.
$expiration = time() + apply_filters( 'auth_cookie_expiration', $expiration_days * DAY_IN_SECONDS, $user->ID, false );
$expiration = time() + apply_filters( 'auth_cookie_expiration', $wp_expiration_days * DAY_IN_SECONDS, $user->ID, false );
$manager = WP_Session_Tokens::get_instance( $user->ID );
$token = $manager->create( $expiration );

Expand All @@ -686,6 +706,22 @@ public function login_user( $user, $token_response, $id_token_claim, $user_claim
// you did great, have a cookie!
wp_set_auth_cookie( $user->ID, $remember_me, '', $token );
do_action( 'wp_login', $user->user_login, $user );

// Remove the filter for the auth cookie expiration after all the auth cookies are set.
remove_filter( 'auth_cookie_expiration', array( $this, 'set_cookie_expiration_to_openid_token_refresh_expiration' ) );
}

/**
* Filter callback to overwrite the default cookie expiration with the
* openid token refresh expiration. This is applied both when creating the session
* token as well as when wp_set_auth_cookie is called.
*
* @param integer $expiration_in_seconds The expiration time in seconds.
* @return integer
*/
public function set_cookie_expiration_to_openid_token_refresh_expiration( $expiration_in_seconds ) {
$expiration_in_seconds = $this->openid_token_refresh_expires_in;
return $expiration_in_seconds;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,67 @@ public function test_plugin_client_wrapper_alternate_redirect_uri_parse_request(

}

/**
* Test if by using the remember-me filter, the user session expiration
* is set to 14 days, which is the default of WordPress
*
* @group ClientWrapperTests
*/
public function test_plugin_client_wrapper_remember_me() {
// Set the remember me option to true
add_filter( 'openid-connect-generic-remember-me', '__return_true' );

// Create a user and log in using the login function of the client wrapper
$user = $this->factory()->user->create_and_get( array( 'user_login' => 'test-remember-me-user' ) );
$this->client_wrapper->login_user( $user, array(
'expires_in' => 14 * HOUR_IN_SECONDS, // This does not influence the length of the cookie
'expires_in' => 5 * MINUTE_IN_SECONDS,
), array(), array(), '' );

// Retrieve the session tokens
$manager = WP_Session_Tokens::get_instance( $user->ID );
$token = $manager->get_all()[0];

// Assert if the token is set to expire in 14 days, with some seconds as a timing margin
// Assert if the token is set to expire in 14 days, with some timing margin
$this->assertGreaterThan( time() + 13 * DAY_IN_SECONDS, $token['expiration'] );
$this->assertLessThan( time() + 15 * DAY_IN_SECONDS, $token['expiration'] );

// Reset the remember me option
// Cleanup
remove_filter( 'openid-connect-generic-remember-me', '__return_true' );
$manager->destroy_all();
wp_clear_auth_cookie();
}

/**
* Test if by using the use-token-expiration, the user session expiration
* is set to the value of the expires_in parameter of the token.
*
* @group ClientWrapperTests
*/
public function test_plugin_client_wrapper_token_expiration() {
// Set the remember me option to true
add_filter( 'openid-connect-generic-remember-me', '__return_true' );
add_filter( 'openid-connect-generic-use-token-refresh-expiration', '__return_true' );

// Create a user and log in using the login function of the client wrapper
$user = $this->factory()->user->create_and_get( array( 'user_login' => 'test-remember-me-user' ) );
$this->client_wrapper->login_user( $user, array(
'expires_in' => 5 * MINUTE_IN_SECONDS,
'refresh_expires_in' => 30 * DAY_IN_SECONDS,
), array(), array(), '' );

// Retrieve the session tokens
$manager = WP_Session_Tokens::get_instance( $user->ID );
$token = $manager->get_all()[0];

// Assert if the token is set to expire in 30 days, with some timing margin
$this->assertGreaterThan( time() + 29 * DAY_IN_SECONDS, $token['expiration'] );
$this->assertLessThan( time() + 31 * DAY_IN_SECONDS, $token['expiration'] );

// Cleanup
remove_filter( 'openid-connect-generic-remember-me', '__return_true' );
remove_filter( 'openid-connect-generic-use-token-refresh-expiration', '__return_true' );
$manager->destroy_all();
wp_clear_auth_cookie();
}

}

0 comments on commit e0c8229

Please sign in to comment.