XeroAPI / xero-php-oauth2

Xero PHP SDK for oAuth 2 generated from Xero API OpenAPI Spec 3.0
MIT License
87 stars 64 forks source link

Deprecated code in JWTClaims #330

Closed sarahk closed 8 months ago

sarahk commented 11 months ago

SDK you're using (please complete the following information):

Describe the bug Use of the JWT functions throws deprecation errors

To Reproduce Steps to reproduce the behaviour:

  1. install xero-php-oauth2-starter & dependancies
  2. run the demo project
  3. authenticate with Xero
  4. Click the menu option for "JWT Claims"
  5. Errors are shown before the desired information

Deprecated: Creation of dynamic property XeroAPI\XeroPHP\JWTClaims::$accessToken is deprecated in /Users/mymac/Sites/CKM/vendor/xeroapi/xero-php-oauth2/lib/JWTClaims.php on line 139

Deprecated: Creation of dynamic property XeroAPI\XeroPHP\JWTClaims::$jwtAccessDecoded is deprecated in /Users/sarahking/mymac/CKM/vendor/xeroapi/xero-php-oauth2/lib/JWTClaims.php on line 126

Expected behaviour I expected to get an errorless dump of the JWT Token

Screenshots If applicable, add screenshots to help explain your problem.

Additional context This can obviously be ignored but it would be good to get the code upgraded at some point.

github-actions[bot] commented 11 months ago

PETOSS-320

github-actions[bot] commented 11 months ago

Thanks for raising an issue, a ticket has been created to track your request

portbury commented 11 months ago

I'm also experiencing issues with JWTClaims.php. From my testing, issue appears to have been introduced with release of dependency firebase/php-jwt 6.6.0.

If I run the following code...

// Try to get an access token using the authorization code grant.
$accessTokenObject = $provider->getAccessToken('authorization_code', [
    'code' => $_GET['code']
]);

$accessToken = (string) $accessTokenObject->getToken();
$refreshToken = $accessTokenObject->getRefreshToken();
$idToken = isset($accessTokenObject->getValues()['id_token']) ? $accessTokenObject->getValues()['id_token'] : null;
$expires = $accessTokenObject->getExpires();

// Extract user information who initiated connection
$jwtAccessTokenClaims = new XeroAPI\XeroPHP\JWTClaims();
$jwtAccessTokenClaims->decodeAccessToken($accessToken);
$userId = $jwtAccessTokenClaims->getXeroUserId();

On the second last line with decodeAccessToken I get the following fatal error:

Uncaught TypeError: Firebase\JWT\JWT::decode(): Argument #3 ($headers) must be of type ?stdClass, array given, called in /....../vendor/xeroapi/xero-php-oauth2/lib/JWTClaims.php on line 40 and defined in /....../vendor/firebase/php-jwt/src/JWT.php:96

Stack trace:
#0 /....../vendor/xeroapi/xero-php-oauth2/lib/JWTClaims.php(40): Firebase\JWT\JWT::decode('eyJhbG...', Array, Array)
#1 /....../vendor/xeroapi/xero-php-oauth2/lib/JWTClaims.php(51): XeroAPI\XeroPHP\JWTClaims->verify('eyJhbG...')
#2 /....../wwwroot/external/xero/authentication/callback.php(37): XeroAPI\XeroPHP\JWTClaims->decodeAccessToken('eyJhbG...')
#3 {main} thrown

Forcing usage of firebase/php-jwt release 6.5.0 in Composer stops the error and returns code to working state.

ravewill commented 10 months ago

This also introduced breaking changes in our app when we pulled in the latest version of the SDK. Are you able to fix the bug from your side or pin the version of firebase/php-jwt in the SDK?

securit commented 9 months ago

Your function needs a modification when calling JWT::decode. The 3rd parameter was deprecated after JWT 5.5.1. Up until then it was an array of supported algorithms. In JWT 6.6 a 3rd parameter was introduced for headers which may include the algorithms (ie if using OpenSSL it expects an ASN.1 DER sequence for ES256,ES256K or ES384 signatures).

You could either drop the 3rd parameter altogether to $verifiedJWT = JWT::decode($token, JWK::parseKeySet($jwks) or if you want to support ES256/256K/384, then you would have to change the $supportedAlgorithm = array('RS256'); line.

private function verify($token) {
    $json = file_get_contents('https://identity.xero.com/.well-known/openid-configuration/jwks');
    $jwks =  json_decode($json, true);
    $supportedAlgorithm = (object) ['alg'=>['RS256','ES256']];
    $verifiedJWT = JWT::decode($token, JWK::parseKeySet($jwks), $supportedAlgorithm);

    return $verifiedJWT;
}
pumpkinball commented 8 months ago

Hi @securit @sarahk @ravewill @portbury Thanks for raising this issue and really appreciate your helpful comments/suggestions to solving it 👍 I've made the changes as per @securit and it's now in the latest release 2.23.1