1

I am trying to figure out if its possible to write an ASP.NET Core API that consumes an identity server token using either Reference Tokens or JWT tokens based on whatever I've configured my identity server to use. The back-end configuration for IS4 is pretty easy, I'm just not convinced that I can configure 2 different token middlewares and my service will both be ok with it and know what to do.

So the idea is:

  • If my API gets a jwtToken, it attempts to use the jwt middleware for authorization back to identity server.
  • If my API gets a reference token, it attempts to use the introspection middleware for authorization back to identity server.

Obviously, if the wrong type of token is provided for whatever is configured on the IS4 service, it will fail.

Handling the token endpoint and revocation endpoint should also be easy enough, it's just the middleware magic I'm concerned with.

I know typically you wouldn't want to do this but we have a niche use case for it. All I'm currently concerned with is whether or not its even possible. I'm not familiar with how the auth middleware works in the back-end.

Karoupa
  • 31
  • 4

3 Answers3

1

According to the Identity Server 4 Protecting APIs document, we can see that it supports to use both JWTs and reference tokens in asp.net core.

You can setup ASP.NET Core to dispatch to the right handler based on the incoming token, see this blog post for more information.

services.AddAuthentication("token")

    // JWT tokens
    .AddJwtBearer("token", options =>
    {
        options.Authority = Constants.Authority;
        options.Audience = "resource1";

        options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };

        // if token does not contain a dot, it is a reference token
        options.ForwardDefaultSelector = Selector.ForwardReferenceToken("introspection");
    })

    // reference tokens
    .AddOAuth2Introspection("introspection", options =>
    {
        options.Authority = Constants.Authority;

        options.ClientId = "resource1";
        options.ClientSecret = "secret";
    });
Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
0

The way I would do it is to use introspection and claims caching in both cases, so that the API does not need to know or care which type of access token it receives.

The introspection would only occur when an access token is first received. Subsequent requests with the same token then use cached claims.

RESOURCES

Gary Archer
  • 22,534
  • 2
  • 12
  • 24
0

Supporting both JWTs and reference tokens

In addition to @Zhi Lv post you might need to add Authorization policy, Authentication Schemes to allow validating JWT and reference tokens.

Here is the sample code template replace api name, api secret and audience appropriatly.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
            .AddJwtBearer(Options =>
            {
                Options.Authority = "https://identity.domain.com/identity/";
                Options.Audience = "resource1"; //your api baseurl e.g if you want userinfo_endpoint  specify https://identity.domain.com/identity/connect/userinfo

                Options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
            })
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "https://identity.domain.com/identity/";
                options.ApiName = "api name / scope";
                options.ApiSecret = "api secret / scope secret";
            });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("tokens", x =>
            {
                x.AddAuthenticationSchemes("jwt", "introspection");
                x.RequireAuthenticatedUser();
            });
        });
    }
Varun
  • 422
  • 3
  • 14