This is Jian Wu from NIO, we developed an internal app with React Front-end using Okta Signin Widget and Node RESTful API Server using Okta JWTVerifier.
We tested our app with Okta Developer Org without problem. But, when we move our app to integrate with Okta NIO Authorization Server, we caught JwksError on our Node server with
JWTVerifier:
Token Verification Failed!
{ [JwtParseError: Error while resolving signing key for kid “MHJwWvrETU0kFJENrSQQr5LPj-uHS4IJn_DfgNQwpX0”]
name: ‘JwtParseError’,
userMessage:
‘Error while resolving signing key for kid “MHJwWvrETU0kFJENrSQQr5LPj-uHS4IJn_DfgNQwpX0”’,
message:
‘Error while resolving signing key for kid “MHJwWvrETU0kFJENrSQQr5LPj-uHS4IJn_DfgNQwpX0”’,
jwtString:
This is Jian Wu from NIO, we developed an internal app with React Front-end using Okta Signin Widget and Node RESTful API Server using Okta JWTVerifier.
What I found is that is caused by jwksClient failed to fetch keys from jwksUri which pointing to Okta NIO Authorization Server.
Please provide a solution or fix to this problem. Otherwise, it means that we can not use OktaJWTVerifier for a production environment with real Okta Authorization Server.
I have merged your two topics together in order to keep the discussion in one place.
Regarding the issue, the Okta authorization server (endpoints available at https://nio.okta.com/.well-known/openid-configuration) does not return the signing keys for access token due to possible security issues that might occur and also due to RFC restrictions.
If you would like to validate an access token issued by the Okta authorization server, the best way to go would be with the /introspect endpoint. Here is a cURL example to achieve this
As for now, I’m using JWTVerifier from okta-oidc-js, if there is a way I can turn off the verifyAccessToken call inside JWTVerifier and return the JWT Token back, then I can try to send request to introspect endpoint from application layer code.
If this kid is part of the access token, then, as mentioned before, the Okta authorization server does not return it. This is by design, unfortunately there is no option to enable it.
You can validate the access tokens through /introspect endpoint or you can purchase the API Access Management SKU and you will be able to verify locally the access tokens issued through custom authorization servers created through this SKU.
You can find here further details about the features offered by API Access Management SKU.
Based on your reply and conversation through support channel with Vasile, from what I understood, Okta JWT Verifier for Node.js REQUIRES an Okta Authorization Server with “API Access Management” Component/Option, which is PAID add-on option not included in standard Okta Authorization Server, to work.
Alternatively, we need develop our own JWTVerifier using introspect endpoint as part of standard Okta Authorization Server. Obviously, comparing getting and caching public signing key, this has performance penalty on both Okta end and our app end as app need making https call to this endpoint for each request.
Please let me know if what I stated here is incorrect.
As the signing keys for access tokens are not returned when using the Okta authorization server, the access tokens issued by this authorization should should not be used for authorization. Although the “request to /introspect” scenario is possible, when doing numerous requests per minute, the next requests will be blocked due to rate limitation.
The best solution here would be to have a local token issued for the user authenticated and use this token to access the resource server. This token can work as follows:
database table schema can be defined as ID, token, user, exp
when the user logs in to the application, the token is generated (or copied based on the access token) and added in the database table, along with who generated the token and when it will expire
when the resource server is accessed with this token in the authorization header, the resource server takes it and verifies it against the one in the database
if the token expired, you can generate a new token (or request a new one from Okta)
Based on your replies, it seems that Okta Authorization Server can not be used by an internal app inside enterprise to authenticate internal user.
Even though we bought Okta Authorization Server to authenticate internal user accessing Outlook, JIRA, …, but, for our internal app, we either have to build our own internal authentication server to authenticate internal user for these internal apps or we have to buy extra Custom Authorization Server Option, which I assume is expensive.
I’m not in any way against Okta to earn its money, but just want to clarify what is the proper scope and limitation to use Okta Developer libraries, as this information is not available either on developer.okta.com or github site.
I was having the same issue. Following the documentation, I had my issuer for the jwt-verifier set to https://{okta_domain}/oauth2/default, but I needed to change it to https://{okta_domain}/oauth2 instead (notice I trimmed off the /default). I did not see any documentation anywhere for this. Perhaps I missed it. Maybe this will help someone else.
Now the code that works for me looks like this:
const oktaJwtVerifier = new OktaJwtVerifier({
issuer: "https://{okta_domain}/oauth2",
clientId: "{client_id}"
});
It looks like that we are in the same boat:-), there are two ways to solve this problem for now:
Your Okta Auth Server need have an extra paid component: Custom Authorization Server to support JWTVerifier, you can find the difference between general Okta Auth Server and Okta Custom Authorization Server in this Okta Support Doc
As @dragos suggested, implemented a simple JWTVerifier using existing introspect endpoint available from general Okta Auth Server. This is not a best solution but is doable especially if you are building an internal app not heavily loaded