1

I am using Visual Studio 2015 Enterprise Update 1 and ASP.NET 5 rc1-final to build an endpoint that both issues and consumes JWT tokens as described in detail here. In this approach we have a single project that 'does it all' - the project uses OIDC to issue tokens, JWT bearer authentication to validate them and then guards access to various controllers using the Authorize attribute - all in the same project.

Now we would like to refactor this solution by creating an OIDC authorization & authentication endpoint that only issues and validates tokens. Then we want 'n' additional endpoints that rely on that OIDC endpoint as a central authority for authenticating tokens. This will allow us to stand up additional endpoints on our growing service backbone without having to code the authorization & authentication into every endpoint.

While I understand how to configure OIDC to issue tokens from one endpoint, it's not entirely clear how I would point my other endpoint to the OIDC endpoint for token authentication. Presently JWT authentication and OIDC are simultaneously configured in the middleware 'Configure' method so I'm guessing perhaps on all the subordinate sites I would have a small piece of code in calling app.UseJwtBearerAuthentication simply pointing the JWT middleware to the OIDC endpoint? If this is the case there's still a bit of magic taking place with the app.UseJwtBearerAuthentication that uses OIDC to allow IdentityModel to use HTTP, so I'm not clear if I would need this on the subordinate servers also.

Any advice on how to establish a single OIDC authorization & authentication endpoint and then have 'n' subordinate endpoints point to that endpoint for authentication of JWT tokens would be very much appreciated.

1 Answer 1

1

Separating the resource server role (i.e the API) from the authorization server role is definitely possible with ASOS.

When opting for JWT tokens (instead of the default encrypted tokens), you need to ensure the audience is correctly added to the authentication ticket by calling ticket.SetResources, so the JWT access token gets the appropriate aud claim, containing the identifier associated with your resource server (i.e API):

public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) {
    var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
    identity.AddClaim(ClaimTypes.NameIdentifier, "[unique identifier]");

    var ticket = new AuthenticationTicket(
        new ClaimsPrincipal(identity),
        new AuthenticationProperties(),
        context.Options.AuthenticationScheme);

    // Call SetResources with the list of resource servers
    // the access token should be issued for.
    ticket.SetResources("resource_server_1");

    // Call SetScopes with the list of scopes you want to grant.
    ticket.SetScopes("profile", "offline_access");

    context.Validate(ticket);

    return Task.FromResult(0);
}     

In your API app, you just have to set the options.Audience property with the identifier used in the authorization server, and it should work:

app.UseJwtBearerAuthentication(new JwtBearerOptions {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    Audience = "resource_server_1",
    Authority = "http://localhost:61854"
});

I would have a small piece of code in calling app.UseJwtBearerAuthentication simply pointing the JWT middleware to the OIDC endpoint? If this is the case there's still a bit of magic taking place with the app.UseJwtBearerAuthentication that uses OIDC to allow IdentityModel to use HTTP, so I'm not clear if I would need this on the subordinate servers also.

The JWT bearer middleware automatically retrieves the cryptographic key used to sign the access token from the authorization server mentioned in the options.Authority property, by making an HTTP call to the configuration metadata endpoint: you don't have to configure anything, even if the API project is separated from the authorization server app.

Sign up to request clarification or add additional context in comments.

10 Comments

Awesome, @Pinpoint - I'll give this a shot. Also should I be referring to AspNet.Security.OpenIdConnect.Server as ASOS in future posts?
Both are fine, but I guess the long name is better from a SEO perspective ;) FYI, I created a new aspnet-contrib tag (this way, I can receive a notification when a question is posted with this tag), so don't hesitate to add it when asking an ASOS question.
I wired this up to my existing "does it all" implementation so any new APIs can point to my existing endpoint as the resource server. Now the questions ;o) 1) Some time back I began adding the 'resource' key to the token request form with a value set to the URL of the resource server. Is this still required? 2) Also my custom audience validation broke because I was using URI classes to robustly compare 'aud' URI values - can I take this out now with 'aud' being filled in with a free-form name?
Also what are the scopes for? Thanks!
Starting with the next beta, the resource parameter will no longer be supported OTB, so using it is no longer recommended (calling ticket.SetResources is now the official approach). You should still be able to use a URI if you don't like using a string identifier.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.