Access Token validation


#1

I have a back-end ASP.NET core 2.0 web api services to which I want to restrict access. I tried to follow the example scenario described here https://developer.okta.com/quickstart/#/angular/dotnet/aspnetcore, when I have implicit flow and my SPA application receives id token and access token. I have my Authentication middleware configured configured exactly as described in the example

services.AddAuthentication(sharedOptions =>
{
    sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
    options.Authority = "https://{yourOktaDomain}.com/oauth2/default";
    options.Audience = "api://default";
});

And this works alright when I pass the id_token as a Bearer in Authorization header. But it doesn’t work when I pass access_token as a Bearer. I receive 401 with error: “The signature key was not found”. And it makes sense, because for Access Token Signed key can’t be verified, according to OKTA documentation. So is it an error in the OKTA example when they send access_token as a Bearer and then validate it on back with configs specified above? Or it is that I’m doing something wrong here?


#2

I had the same issue. You need to create a custom authorization server. The default one cannot be used to validate access tokens.

Here is more information.


#3

Thanks Brian! Your answer helped me a lot! I think the confusing part for me was that the Custom Authorization Server, predefined by Okta, has Name as “default”, which I confused with Okta Authorization Server, which is used by default.


#4

Thanks for jumping in @bromanko!

To add some more explanation: you do need an authorization server set up to validate access tokens. When you create a new organization thru http://developer.okta.com, an AS called default is set up for you automatically, which should work fine with the above instructions for aspnetcore 2.0. If you want, you can create your own AS.

As @bromanko pointed out, there’s another authorization server (the Okta Org AS) that’s limited and isn’t meant to be used for these use cases. That’s not the same as the default AS. Sorry for the confusion.

@pavlo.tsybulivskyi if you are unable to validate access tokens with the default AS in a new developer organization, let me know. That should work.


#5

Hi @nate.barbettini … sorry to jump in this question. I am having a similar issue and I appreciate your help. I created the organization around July 10 and look like the default AS was not created at that time. I tried to do it manually but looks like I was not doing it right. Should I create a new dev organization? Or can I fix the current one?

My main interest is based on how to validate access token signatures by code (like I am able to do it with the id token from OIDC) however the access token provided by the OIDC flows doesn’t use the same kid than the id token.
id token kid: ADrZkJxiLoLIBzYQQNwV5Fsii1u0TIv-ZB5pNGVzy3Y vs access token kid: 9kGdBfacZTeZRWOomS2u1jybi6_lRrn1gkg7kU3K-U8

thanks for your help and sorry if it is a rookie question

thanks for your help!!!


#6

Hi @lopezlucas,

The default authorization server was a recent edition and can be added to existing orgs by contacting developers@okta.com. Otherwise, all new orgs get it out of the gate.

You can also setup a custom authorization server, where you can validate the accessToken’s kid using /keys endpoint.


#7

To add to @jmelberg’s point: if you don’t have the default authorization server, creating a custom authorization server is just as good. The default AS is just a convenience we added recently so you don’t have to create a custom AS yourself.


#8

thanks @jmelberg and @nate.barbettini for your quick answer. We will try to add the custom server and see if we could make it work. Thanks again…


#9

Hi @lopezlucas. Just in case that you will still need this. The reason why the id_token’s kid is different from access_token’s kid is that id_token and access_token may be from different authorization server. Inserting authorizationServerId into api uri can solve this problem (just like this oauth2/${authorizationServerId}/v1/token/). Then the kid of access_token will be the same as id_token.

The tokens can be validated with njwt. It requires pem-jwk module to generate a pem with jwk of your authorization server.

Hope this will help.