Skip to content

Commit

Permalink
Adding support for generic front logout channel
Browse files Browse the repository at this point in the history
  • Loading branch information
StarAurryon committed Sep 8, 2021
1 parent 9dde05b commit 1975cfa
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 1 deletion.
74 changes: 74 additions & 0 deletions includes/openid-connect-generic-client-wrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,21 @@ public static function register( OpenID_Connect_Generic_Client $client, OpenID_C
*/
add_action( 'wp_ajax_openid-connect-authorize', array( $client_wrapper, 'authentication_request_callback' ) );
add_action( 'wp_ajax_nopriv_openid-connect-authorize', array( $client_wrapper, 'authentication_request_callback' ) );

add_action( 'wp_ajax_openid-connect-logout', array( $client_wrapper, 'frontchannel_logout_request' ) );
add_action( 'wp_ajax_nopriv_openid-connect-logout', array( $client_wrapper, 'frontchannel_logout_request' ) );
}

if ( $settings->alternate_redirect_uri ) {
// Provide an alternate route for authentication_request_callback.
add_rewrite_rule( '^openid-connect-authorize/?', 'index.php?openid-connect-authorize=1', 'top' );
add_rewrite_tag( '%openid-connect-authorize%', '1' );
add_action( 'parse_request', array( $client_wrapper, 'alternate_redirect_uri_parse_request' ) );

// Provide an alternate route for the frontchannel_logout_request.
add_rewrite_rule( '^openid-connect-logout/?', 'index.php?openid-connect-logout=1', 'top' );
add_rewrite_tag( '%openid-connect-logout%', '1' );
add_action( 'parse_request', array( $client_wrapper, 'alternate_redirect_uri_parse_request' ) );
}

// Verify token for any logged in user.
Expand All @@ -139,6 +147,12 @@ public function alternate_redirect_uri_parse_request( $query ) {
exit;
}

if ( isset( $query->query_vars['openid-connect-logout'] ) &&
'1' === $query->query_vars['openid-connect-logout'] ) {
$this->frontchannel_logout_request();
exit;
}

return $query;
}

Expand Down Expand Up @@ -208,6 +222,7 @@ public function get_authentication_url( $atts = array() ) {
'endpoint_login' => $this->settings->endpoint_login,
'scope' => $this->settings->scope,
'client_id' => $this->settings->client_id,
'logout_uri' => $this->client->get_logout_uri(),
'redirect_uri' => $this->client->get_redirect_uri(),
'redirect_to' => $this->get_redirect_to(),
),
Expand Down Expand Up @@ -563,6 +578,65 @@ public function authentication_request_callback() {
exit;
}

/**
* Control the front channel logout endpoint as specified per openid standards.
*
* @return void
*/
public function frontchannel_logout_request() {
if ( ! is_user_logged_in() ) {
wp_send_json(
array(
'status' => 'User not logged in',
)
);
}

$user = wp_get_current_user();
$manager = WP_Session_Tokens::get_instance( $user->ID );
$token = wp_get_session_token();
$session = $manager->get( $token );

if ( ! isset( $session[ $this->cookie_token_refresh_key ] ) ) {
// Not an OpenID-based session.
wp_send_json(
array(
'status' => 'Not an OAUTH session',
)
);
}

$claim = $user->get( 'openid-connect-generic-last-id-token-claim' );

if ( ! isset( $_GET['iss'] ) || ! isset( $_GET['sid'] ) ) {
wp_send_json(
array(
'status' => 'Missing sid or iss parameter',
)
);
}

if ( $_GET['iss'] != $claim['iss'] || $_GET['sid'] != $claim['sid'] ) {
wp_send_json(
array(
'status' => 'Iss or sid not matching',
)
);
}

$refresh_token_info = $session[ $this->cookie_token_refresh_key ];
$refresh_token = $refresh_token_info['refresh_token'];
$this->client->revoke_refresh_token( $refresh_token );

wp_logout();

wp_send_json(
array(
'status' => 'Logout OK',
)
);
}

/**
* Validate the potential WP_User.
*
Expand Down
67 changes: 66 additions & 1 deletion includes/openid-connect-generic-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ class OpenID_Connect_Generic_Client {
*/
private $endpoint_userinfo;

/**
* The OIDC/oAuth token revocation endpoint URL.
*
* @see OpenID_Connect_Generic_Option_Settings::endpoint_revoke
*
* @var string
*/
private $endpoint_revoke;

/**
* The OIDC/oAuth token validation endpoint URL.
*
Expand All @@ -73,6 +82,15 @@ class OpenID_Connect_Generic_Client {
*/
private $endpoint_token;

/**
* The logout front channel flow "ajax" endpoint URI.
*
* @see OpenID_Connect_Generic_Option_Settings::logout_uri
*
* @var string
*/
private $logout_uri;

/**
* The login flow "ajax" endpoint URI.
*
Expand Down Expand Up @@ -106,23 +124,37 @@ class OpenID_Connect_Generic_Client {
* @param string $scope @see OpenID_Connect_Generic_Option_Settings::scope for description.
* @param string $endpoint_login @see OpenID_Connect_Generic_Option_Settings::endpoint_login for description.
* @param string $endpoint_userinfo @see OpenID_Connect_Generic_Option_Settings::endpoint_userinfo for description.
* @param string $endpoint_revoke @see OpenID_Connect_Generic_Option_Settings::endpoint_revoke for description.
* @param string $endpoint_token @see OpenID_Connect_Generic_Option_Settings::endpoint_token for description.
* @param string $logout_uri @see OpenID_Connect_Generic_Option_Settings::logout_uri for description.
* @param string $redirect_uri @see OpenID_Connect_Generic_Option_Settings::redirect_uri for description.
* @param int $state_time_limit @see OpenID_Connect_Generic_Option_Settings::state_time_limit for description.
* @param OpenID_Connect_Generic_Option_Logger $logger The plugin logging object instance.
*/
public function __construct( $client_id, $client_secret, $scope, $endpoint_login, $endpoint_userinfo, $endpoint_token, $redirect_uri, $state_time_limit, $logger ) {
public function __construct( $client_id, $client_secret, $scope, $endpoint_login, $endpoint_userinfo, $endpoint_revoke, $endpoint_token,
$logout_uri, $redirect_uri, $state_time_limit, $logger ) {
$this->client_id = $client_id;
$this->client_secret = $client_secret;
$this->scope = $scope;
$this->endpoint_login = $endpoint_login;
$this->endpoint_userinfo = $endpoint_userinfo;
$this->endpoint_revoke = $endpoint_revoke;
$this->endpoint_token = $endpoint_token;
$this->logout_uri = $logout_uri;
$this->redirect_uri = $redirect_uri;
$this->state_time_limit = $state_time_limit;
$this->logger = $logger;
}

/**
* Provides the configured logout URI supplied to the IDP.
*
* @return string
*/
public function get_logout_uri() {
return $this->logout_uri;
}

/**
* Provides the configured Redirect URI supplied to the IDP.
*
Expand Down Expand Up @@ -538,4 +570,37 @@ public function get_subject_identity( $id_token_claim ) {
return $id_token_claim['sub'];
}

/**
* Using the refresh token, revoke its usage
*
* @param string $refresh_token The refresh token previously obtained from token response.
*
* @return array<mixed>|WP_Error
*/
public function revoke_refresh_token( $refresh_token ) {
$request = array(
'headers' => array(
'Content-type: application/x-www-form-urlencoded',
),
'body' => array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'token' => $refresh_token,
),
);

// Allow modifications to the request.
$request = apply_filters( 'openid-connect-generic-alter-request', $request, 'refresh-token' );

// Call the server and ask to revoke token.
$this->logger->log( $this->endpoint_revoke, 'revoke_refresh_token' );
$response = wp_remote_post( $this->endpoint_revoke, $request );

if ( is_wp_error( $response ) ) {
$response->add( 'revoke_refresh_token', __( 'Revoke refresh token failed.', 'daggerhart-openid-connect-generic' ) );
}

return $response;
}

}
2 changes: 2 additions & 0 deletions includes/openid-connect-generic-option-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* @property string $scope The list of scopes this client should access.
* @property string $endpoint_login The IDP authorization endpoint URL.
* @property string $endpoint_userinfo The IDP User information endpoint URL.
* @property string $endpoint_revoke The IDP revoke endpoint URL.
* @property string $endpoint_token The IDP token validation endpoint URL.
* @property string $endpoint_end_session The IDP logout endpoint URL.
*
Expand Down Expand Up @@ -90,6 +91,7 @@ class OpenID_Connect_Generic_Option_Settings {
'client_secret' => 'OIDC_CLIENT_SECRET',
'endpoint_login' => 'OIDC_ENDPOINT_LOGIN_URL',
'endpoint_userinfo' => 'OIDC_ENDPOINT_USERINFO_URL',
'endpoint_revoke' => 'OIDC_ENDPOINT_REVOKE_URL',
'endpoint_token' => 'OIDC_ENDPOINT_TOKEN_URL',
'endpoint_end_session' => 'OIDC_ENDPOINT_LOGOUT_URL',
);
Expand Down
14 changes: 14 additions & 0 deletions includes/openid-connect-generic-settings-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,14 @@ private function get_settings_fields() {
'disabled' => defined( 'OIDC_ENDPOINT_USERINFO_URL' ),
'section' => 'client_settings',
),
'endpoint_revoke' => array(
'title' => __( 'Token Revocation Endpoint URL', 'daggerhart-openid-connect-generic' ),
'description' => __( 'Identify provider revoke endpoint.', 'daggerhart-openid-connect-generic' ),
'example' => 'https://example.com/oauth2/revoke',
'type' => 'text',
'disabled' => defined( 'OIDC_ENDPOINT_REVOKE_URL' ),
'section' => 'client_settings',
),
'endpoint_token' => array(
'title' => __( 'Token Validation Endpoint URL', 'daggerhart-openid-connect-generic' ),
'description' => __( 'Identify provider token endpoint.', 'daggerhart-openid-connect-generic' ),
Expand Down Expand Up @@ -414,9 +422,11 @@ public function sanitize_settings( $input ) {
* @return void
*/
public function settings_page() {
$logout_uri = admin_url( 'admin-ajax.php?action=openid-connect-logout' );
$redirect_uri = admin_url( 'admin-ajax.php?action=openid-connect-authorize' );

if ( $this->settings->alternate_redirect_uri ) {
$logout_uri = site_url( '/openid-connect-logout' );
$redirect_uri = site_url( '/openid-connect-authorize' );
}
?>
Expand All @@ -442,6 +452,10 @@ public function settings_page() {
<strong><?php esc_html_e( 'Redirect URI', 'daggerhart-openid-connect-generic' ); ?></strong>
<code><?php print esc_url( $redirect_uri ); ?></code>
</p>
<p class="description">
<strong><?php esc_html_e( 'Logout URI', 'daggerhart-openid-connect-generic' ); ?></strong>
<code><?php print esc_url( $logout_uri ); ?></code>
</p>
<p class="description">
<strong><?php esc_html_e( 'Login Button Shortcode', 'daggerhart-openid-connect-generic' ); ?></strong>
<code>[openid_connect_generic_login_button]</code>
Expand Down
5 changes: 5 additions & 0 deletions openid-connect-generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,11 @@ public function init() {

wp_enqueue_style( 'daggerhart-openid-connect-generic-admin', plugin_dir_url( __FILE__ ) . 'css/styles-admin.css', array(), self::VERSION, 'all' );

$logout_uri = admin_url( 'admin-ajax.php?action=openid-connect-logout' );
$redirect_uri = admin_url( 'admin-ajax.php?action=openid-connect-authorize' );

if ( $this->settings->alternate_redirect_uri ) {
$logout_uri = admin_url( '/openid-connect-logout' );
$redirect_uri = site_url( '/openid-connect-authorize' );
}

Expand All @@ -149,7 +151,9 @@ public function init() {
$this->settings->scope,
$this->settings->endpoint_login,
$this->settings->endpoint_userinfo,
$this->settings->endpoint_revoke,
$this->settings->endpoint_token,
$logout_uri,
$redirect_uri,
$state_time_limit,
$this->logger
Expand Down Expand Up @@ -333,6 +337,7 @@ public static function bootstrap() {
'scope' => '',
'endpoint_login' => defined( 'OIDC_ENDPOINT_LOGIN_URL' ) ? OIDC_ENDPOINT_LOGIN_URL : '',
'endpoint_userinfo' => defined( 'OIDC_ENDPOINT_USERINFO_URL' ) ? OIDC_ENDPOINT_USERINFO_URL : '',
'endpoint_revoke' => defined( 'OIDC_ENDPOINT_REVOKE_URL' ) ? OIDC_ENDPOINT_REVOKE_URL : '',
'endpoint_token' => defined( 'OIDC_ENDPOINT_TOKEN_URL' ) ? OIDC_ENDPOINT_TOKEN_URL : '',
'endpoint_end_session' => defined( 'OIDC_ENDPOINT_LOGOUT_URL' ) ? OIDC_ENDPOINT_LOGOUT_URL : '',

Expand Down
1 change: 1 addition & 0 deletions tests/phpstan-bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
defined( 'OIDC_CLIENT_SECRET' ) || define( 'OIDC_CLIENT_SECRET', bin2hex( random_bytes( 16 ) ) );
defined( 'OIDC_ENDPOINT_LOGIN_URL' ) || define( 'OIDC_ENDPOINT_LOGIN_URL', 'https://oidc/oauth2/authorize' );
defined( 'OIDC_ENDPOINT_USERINFO_URL' ) || define( 'OIDC_ENDPOINT_USERINFO_URL', 'https://oidc/oauth2/userinfo' );
defined( 'OIDC_ENDPOINT_REVOKE_URL' ) || define( 'OIDC_ENDPOINT_REVOKE_URL', 'https://oidc/oauth2/revoke' );
defined( 'OIDC_ENDPOINT_TOKEN_URL' ) || define( 'OIDC_ENDPOINT_TOKEN_URL', 'https://oidc/oauth2/token' );
defined( 'OIDC_ENDPOINT_LOGOUT_URL' ) || define( 'OIDC_ENDPOINT_LOGOUT_URL', 'https://oidc/oauth2/logout' );

0 comments on commit 1975cfa

Please sign in to comment.