auth0 / auth0-PHP

PHP SDK for Auth0 Authentication and Management APIs.
https://auth0.com/docs/libraries/auth0-php
MIT License
383 stars 213 forks source link

Authorized Party (azp) claim mismatch in the ID token #422

Closed ryangittings closed 4 years ago

ryangittings commented 4 years ago

I’m getting “Authorized Party (azp) claim mismatch in the ID token”.

Looking in the SDK’s, it seems to be because the mobile app token seems to be returning two 'aud’s, the API Audience, and the ‘{domain}/userinfo’ endpoint.

AUTH0_AUDIENCE = My application Client ID.

Mobile App Code

Auth0
                .webAuth()
                .scope("openid")
                .audience("AUTH0_AUDIENCE")
                .start {
                    switch $0 {
                    case .failure(let error):
                        // Handle the error
                        print("Error: \(error)")
                    case .success(let credentials):
                        print(credentials.accessToken))
                    }
            }

PHP API

$token_issuer  = 'https://'.env('AUTH0_DOMAIN').'/';
            $jwks_fetcher = new JWKFetcher();
            $jwks        = $jwks_fetcher->getKeys($token_issuer.'.well-known/jwks.json');
            $signature_verifier = new AsymmetricVerifier($jwks);

            $token_verifier = new IdTokenVerifier(
              $token_issuer,
              env('AUTH0_AUDIENCE'),
              $signature_verifier
            );

            try {
              $decoded_token = $token_verifier->verify($accessToken);
            } catch (\Exception $e) {
              return null;
            }
ryangittings commented 4 years ago

Any help/advice super appreciated! I have a mobile app and a PHP API built on Laravel, so need a middleware to check the token is valid.

joshcanhelp commented 4 years ago

@ryangittings - When you say "token," do you mean the access token that you get back? And that's the token you're sending to the API? That's the right way to do it, just making sure I've got everything straight.

If you're requesting an access token for the PHP API, the audience should be the API identifier, not the Client ID. The Client ID is the audience for the ID token that the mobile app receives. Try adding the API identifier there and see if that works as expected. If not, can you post the authorize URL that's being generated and the claims from a decoded access token here?

ryangittings commented 4 years ago

Yeah, I'm sending the access token returned from the Auth0.swift auth process to the Laravel backend.

All I want to do is validate that the access token passed from mobile request is valid. I'm using my "API Audience" in the API's section of Auth0 as the Audience as above, not the Client ID.

Aud is returning an array of "API Audience" as mentioned above, and 'https://...eu.auth0.com/userinfo'. azp is returning the ClientID of the Mobile application (Native Client ID in Applications in Auth).

{
  "aud": [
    "{api_audience}",
    "https://...eu.auth0.com/userinfo"
  ],
  "azp": "{native_client_id}"
}

So the PHP library can't validate the token, due to the azp being the client ID? Looking at the IdTokenVerifier->verify func in this repo, it looks like it's validating the azp against the audience set in the construct, which won't ever match in this case will it?

Does that help? I'm not sure on an easy way to get the authorize url but hopefully the decoded data helps clarify things!

joshcanhelp commented 4 years ago

So ... the problem here is that the verifier you're using is meant for OIDC-compliant ID tokens, not access tokens. That replaced the previous verifier, which could be used for both.

The access tokens we generate are JWTs (the spec does not dictate a format) and, while we generally follow the same format as ID tokens, there are some differences (this azp claim being one of them). Because our access tokens are not expected to be OIDC-compliant, they shouldn't be verified with this verifier.

Which, I realize, leaves you in a bit of a jam here. I think what we need to do is to extrapolate the checks that pertain to an access token and then add the ID token checks on top of that. I think that can be done without too much trouble or breaking changes so let me confer with my team here and make sure that makes sense.

In the meantime ... we have documentation on validating our JWT access tokens which boils down to:

  1. Check the format
  2. Check the signature
  3. Check the iss, exp, and aud claims for presence and validity
  4. Check the scopes

... and then continue along with the remainder of the effective permissions checks your API should be doing. You can do that in your API using the included JWT library along with our provided \Auth0\SDK\Helpers\JWKFetcher for the keys necessary. You can find guidance on the README for that library:

https://github.com/lcobucci/jwt/tree/3.3#validating

Again, we'll work on getting a solution into this SDK that works for this case.

ryangittings commented 4 years ago

That’s brilliant - I’ll do that as a stop gap in development and await the SDK update, as I’d rather it be authorised within the SDK just for peace of mine! Thanks so much.

joshcanhelp commented 4 years ago

@ryangittings - This is merged and released in 7.1.0. I've got a PR submitted to update the documentation at well.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.