From 281db4fe1abb0fc2189222950e95d50a3429afc0 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Tue, 5 Jan 2021 17:20:59 +0900 Subject: hotfix claim parsing --- .../openid-connect-generic-client-wrapper.php | 75 ++++++++++++++++++++-- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/daggerhart-openid-connect-generic/includes/openid-connect-generic-client-wrapper.php b/daggerhart-openid-connect-generic/includes/openid-connect-generic-client-wrapper.php index a407003..2ed6d4b 100644 --- a/daggerhart-openid-connect-generic/includes/openid-connect-generic-client-wrapper.php +++ b/daggerhart-openid-connect-generic/includes/openid-connect-generic-client-wrapper.php @@ -642,7 +642,74 @@ class OpenID_Connect_Generic_Client_Wrapper { } return $desired_nickname; - } + } + +/** + * Checks if $claimname is in the body or _claim_names of the userinfo. + * If yes, returns the claim value. Otherwise, returns false. + * + * @param string $claimname the claim name to look for + * @param array $userinfo the JSON to look in + * @param string $claimvalue the source claim value ( from the body of the JWT of the claim source) + * @return True if a reference was found + */ +function get_claim( $claimname, $userinfo, &$claimvalue ) { + if ( ! isset( $userinfo ) ) { + return False; + } + /** + * If we find a simple claim, return it. + */ + if ( array_key_exists( $claimname, $userinfo ) ) { + $claimvalue = $userinfo[$claimname]; + return True; + } + /** + * If there are not aggregated claims, it is over. + */ + if ( ! array_key_exists( '_claim_names', $userinfo ) || + ! array_key_exists( '_claim_sources', $userinfo ) ) { + return False; + } + $claim_src_ptr = $userinfo['_claim_names']; + if ( ! isset( $claim_src_ptr ) ) { + return False; + } + /** + * No reference found + */ + if ( ! array_key_exists( $claimname, $claim_src_ptr ) ) { + return False; + } + $src_name = $claim_src_ptr[$claimname]; + //Reference found, but no corresponding JWT. This is a malformed userinfo + if ( ! array_key_exists( $src_name, $userinfo['_claim_sources']) ) { + return False; + } + $src = $userinfo['_claim_sources'][$src_name]; + //Source claim is not a JWT. Abort. + if ( ! array_key_exists( 'JWT', $src ) ) { + return False; + } + /** + * Extract claim from JWT. + * FIXME: We probably want to verify the JWT signature/issuer here! + */ + $jwt = $src['JWT']; + list ($header, $body, $rest) = explode('.', $jwt, 3); + $body_str = base64_decode ( $body, false ); + $body_json = json_decode ($body_str, True); + if ( !isset ( $body_json ) ) { + return False; + } + if ( !array_key_exists( $claimname, $body_json ) ) { + return False; + } + $claimvalue = $body_json[$claimname]; + return True; +} + + /** * Build a string from the user claim according to the specified format. @@ -660,8 +727,8 @@ class OpenID_Connect_Generic_Client_Wrapper { if ( preg_match_all( '/\{[^}]*\}/u', $format, $matches, PREG_OFFSET_CAPTURE ) ) { foreach ( $matches[0] as $match ) { $key = substr( $match[0], 1, -1 ); - $string .= substr( $format, $i, $match[1] - $i ); - if ( ! isset( $user_claim[ $key ] ) ) { + $string .= substr( $format, $i, $match[1] - $i ); + if ( ! get_claim($key, $user_claim, $info ) ) { if ( $error_on_missing_key ) { return new WP_Error( 'incomplete-user-claim', @@ -675,7 +742,7 @@ class OpenID_Connect_Generic_Client_Wrapper { ); } } else { - $string .= $user_claim[ $key ]; + $string .= $info; } $i = $match[1] + strlen( $match[0] ); } -- cgit v1.2.3