diff --git a/includes/openid-connect-generic-client-wrapper.php b/includes/openid-connect-generic-client-wrapper.php index 78e7f42..294d1b0 100644 --- a/includes/openid-connect-generic-client-wrapper.php +++ b/includes/openid-connect-generic-client-wrapper.php @@ -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. * @@ -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 ); @@ -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; } /** diff --git a/tests/phpunit/includes/openid-connect-generic-client-wrapper_test.php b/tests/phpunit/includes/openid-connect-generic-client-wrapper_test.php index b996c1d..c5f12df 100644 --- a/tests/phpunit/includes/openid-connect-generic-client-wrapper_test.php +++ b/tests/phpunit/includes/openid-connect-generic-client-wrapper_test.php @@ -45,6 +45,12 @@ 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' ); @@ -52,19 +58,54 @@ public function test_plugin_client_wrapper_remember_me() { // 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(); } }