PHP Fatal error: Uncaught UnexpectedValueException: "kid" invalid, unable to lookup correct key in /okta/vendor/firebase/php-jwt/src/JWT.php:117

I am having trouble getting the Okta PHP jwt-verifier to work correctly.

I saw a similar report on the git-hub issues, but no resolution was posted.

The app is setup as OpenID Connect on Okta, but I think the code examples I’ve been using are oauth2 (?)

The examples suggest using an issuer value that takes the form,
ISSUER=https://${yourOktaDomain}/oauth2/${authorizationServerId}

But for OpenID Connect, building the jwtVerifier only works if I use ISSUER=https://${yourOktaDomain}

#0 /website/DEV11_EXT/webapps/okta/vendor/okta/jwt-verifier/src/Adaptors/FirebasePhpJwt.php(54): Firebase\JWT\JWT::decode(‘eyJraWQiOiJiUUN…’, Array, Array)
#1 /website/DEV11_EXT/webapps/okta/vendor/okta/jwt-verifier/src/JwtVerifier.php(135): Okta\JwtVerifier\Adaptors\FirebasePhpJwt->decode(‘eyJraWQiOiJiUUN…’, Array)
#2 /website/DEV11_EXT/webapps/php/include/ci_security.php(482): Okta\JwtVerifier\JwtVerifier->verifyAccessToken(‘eyJraWQiOiJiUUN…’)
#3 /website/DEV11_EXT/webapps/php/common/LaunchService.php(91): ci_security->authenticate()
#4 /website/DEV11_EXT/webapps/reports/ci_report/launch.php(39): LaunchService->authenticate()
#5 /website/DEV11_EXT/webapps/php/common/DefaultSecureService.php(44): Launch->validateSession()
#6 /website/DEV11_EXT/webapps/php/common/LaunchService.php(32): DefaultSecureService->run(false)
#7 /website/DEV11_EXT in /website/DEV11_EXT/webapps/okta/vendor/firebase/php-jwt/src/JWT.php on line 117

Are you attempting to validate Access Tokens?

The JWT verifier library will not work if you are using the Org Authorization Server, issuer = https://${yourOktaDomain}. You must use a Custom Authorization Server instead, issuer = https://${yourOktaDomain}/oauth2/${authorizationServerId}, otherwise the ‘kid’ at the /keys endpoint will not match the one in the token and this library may not work correctly with the Org server in general as it is not designed to

I am attempting to validate the access token.

Perhaps I don’t understand what a Customer Authorization Server is. For issuer, I have tried both our authorization endpoint,
[authorization_endpoint] => https://connect.oktapreview.com/oauth2/v1/authorize
and also
https://connect.oktapreview.com/oauth2/v1

But both forms fail with this message.

PHP Notice: Trying to get property ‘jwks_uri’ of non-object in /website/TST5_EXT/webapps/okta/vendor/okta/jwt-verifier/src/JwtVerifier.php on line 129
[03-Nov-2021 09:53:24 CST6CDT] PHP Fatal error: Uncaught DomainException: Could not access a valid JWKS_URI from the metadata. We made a call to https://connect.oktapreview.com/oauth2/v1/authorize/.well-known/openid-configuration
endpoint, but jwks_uri was null. Please make sure you are using a custom authorization server for the jwt verifier. in /website/TST5_EXT/webapps/okta/vendor/okta/jwt-verifier/src/JwtVerifier.php:130

When I use https://connect.oktapreview.com as the ‘issuer’, the jwtVerifier object contains the jwks_uri object.

[03-Nov-2021 09:36:34 CST6CDT] Okta\JwtVerifier\JwtVerifier Object
(
[issuer:protected] => https://connect.oktapreview.com
[discovery:protected] => Okta\JwtVerifier\Discovery\Oidc Object
(
[wellKnownUri:protected] => /.well-known/openid-configuration
)

[claimsToValidate:protected] => Array
    (
        [nonce] =>
        [audience] => api://default
        [clientId] => 0oa11hem6raLTzqTy0h8
    )

[wellknown:protected] => https://connect.oktapreview.com/.well-known/openid-configuration
[metaData:protected] => stdClass Object
    (
        [issuer] => https://connect.oktapreview.com
        [authorization_endpoint] => https://connect.oktapreview.com/oauth2/v1/authorize
        [token_endpoint] => https://connect.oktapreview.com/oauth2/v1/token
        [userinfo_endpoint] => https://connect.oktapreview.com/oauth2/v1/userinfo
        [registration_endpoint] => https://connect.oktapreview.com/oauth2/v1/clients
        [jwks_uri] => https://connect.oktapreview.com/oauth2/v1/keys
        [response_types_supported] => Array
            (
                [0] => code
                [1] => id_token
                [2] => code id_token
                [3] => code token
                [4] => id_token token
                [5] => code id_token token
            )

…and more…

But using either the …/oauth2/v1 or …/oath2/v1/authorize forms for the issuer, the jwks_uri entry is missing from the jwtVerifier object.

[03-Nov-2021 09:53:24 CST6CDT] Okta\JwtVerifier\JwtVerifier Object
(
[issuer:protected] => https://connect.oktapreview.com/oauth2/v1/authorize
[discovery:protected] => Okta\JwtVerifier\Discovery\Oidc Object
(
[wellKnownUri:protected] => /.well-known/openid-configuration
)

[claimsToValidate:protected] => Array
    (
        [nonce] =>
        [audience] => api://default
        [clientId] => 0oa11hem6raLTzqTy0h8
    )

[wellknown:protected] => https://connect.oktapreview.com/oauth2/v1/authorize/.well-known/openid-configuration
[metaData:protected] =>
[adaptor:protected] => Okta\JwtVerifier\Adaptors\FirebasePhpJwt Object
    (
        [request:Okta\JwtVerifier\Adaptors\FirebasePhpJwt:private] => Okta\JwtVerifier\Request Object
            (
                [httpClient:protected] => Http\Client\Common\PluginClient Object
                    (
                        [client:Http\Client\Common\PluginClient:private] => Http\Client\Curl\Client Object
                            (
                                [curlOptions:Http\Client\Curl\Client:private] => Array
                                    (
                                        [52] =>
                                        [42] =>
                                        [19913] =>
                                    )

So the issuer you are currently trying to use is the Org Authorization Server, which is the one that issues access tokens you will not be able to validate. More details about this here: Signature Validation Failed on Access Token | Okta Help Center

In order to validate these tokens, you would need to use a Custom Authorization Server instead, which you may not be able to use in your org as it requires an additional API Access Management license. You’ll know you have the required feature if you can navigate to Security → API → Authorization Servers. This tab will not exist if you do not have this feature and it is where these custom servers can be created and modified.

You can read more about the different authorization server types here: Authorization Servers | Okta Developer

This is very helpful. We appear to have the required feature for customer authorization servers.

More reading and testing…

I am using the /introspect to validate the access token, and that seems to be working well.

I am now struggling a bit to get the /logout endpoint to work as expected.

Actually, I am getting an error (my mistake). the logout endpoint is complaining that I am not providing the client_id, but I have provided the correct value.

{“errorCode”:“invalid_client”,“errorSummary”:“A client_id must be provided in the request.”,“errorLink”:“invalid_client”,“errorId”:“oaeN30gUpZASJqFKxk-dPV9pA”,“errorCauses”:}

Are you providing the id_token_hint as a query parameter to the logout endpoint? Its value will be just the raw JWT string for the user logged in on that browser

Thanks, as it turned out I was providing the access_token, but I needed to provide the id_token.

It appears to be working now.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.