ASP.NET Core 2.0 authentication middlewareAsk Questions

 Posted on 26 days ago

With Core 1.1 when I implemented a custom middleware:

It worked like this:

  1. Middleware ran. Picked up a token from the request headers.
  2. Verified the token and if valid built an identity (ClaimsIdentity) that contained multiple claims which then it added via HttpContext.User.AddIdentity();
  3. In ConfigureServices using services.AddAuthorization I've added a policy to require the claim that is provided by the middleware.
  4. In the controllers/actions I would then use [Authorize(Roles = "some role that the middleware added")]

This somewhat works with 2.0, except that if the token is not valid (step 2 above) and the claim is never added I get "No authenticationScheme was specified, and there was no DefaultChallengeScheme found."

So now I'm reading that auth changed in 2.0:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

What's the right path for me to do the same thing in ASP.NET Core 2.0? I don't see an example to do truly custom authentication.

Share On: facebook gplus twitter
profile
Asked by Karishnamurthy Aiyar on 26 days ago Score: 32 points
Add Comment:

Comments

2 Answers

0 Corrected Answers
Aproved Answers
0
Profile
Answered by hardik chaudhary on 9/28/2019 3:27:53 PM Score: 542 points

So, after a long day of trying to solve this problem, I've finally figured out how Microsoft wants us to make custom authentication handlers for their new single-middleware setup in core 2.0.

After looking through some of the documentation on MSDN, I found a class called AuthenticationHandler<TOption> that implements the IAuthenticationHandler interface.

From there, I found an entire codebase with the existing authentication schemes located at https://github.com/aspnet/Security

Inside of one of these, it shows how Microsoft implements the JwtBearer authentication scheme. (https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer)

I copied most of that code over into a new folder, and cleared out all the things having to do with JwtBearer.

In the JwtBearerHandler class (which extends AuthenticationHandler<>), there's an override for Task<AuthenticateResult> HandleAuthenticateAsync()

I added in our old middleware for setting up claims through a custom token server, and was still encountering some issues with permissions, just spitting out a 200 OK instead of a 401 Unauthorized when a token was invalid and no claims were set up.

I realized that I had overridden Task HandleChallengeAsync(AuthenticationProperties properties) which for whatever reason is used to set permissions via [Authorize(Roles="")] in a controller.

After removing this override, the code had worked, and had successfully thrown a 401 when the permissions didn't match up.

The main takeaway from this is that now you can't use a custom middleware, you have to implement it via AuthenticationHandler<> and you have to set the DefaultAuthenticateScheme and DefaultChallengeScheme when using services.AddAuthentication(...).

Here's an example of what this should all look like:

In Startup.cs / ConfigureServices() add:

services.AddAuthentication(options => { // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...) options.DefaultAuthenticateScheme = "Custom Scheme"; options.DefaultChallengeScheme = "Custom Scheme"; }) .AddCustomAuth(o => { });

In Startup.cs / Configure() add:

app.UseAuthentication();

Create a new file CustomAuthExtensions.cs

public static class CustomAuthExtensions { public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions) { return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions); } }

Create a new file CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions { public CustomAuthOptions() { } }

Create a new file CustomAuthHandler.cs

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions> { public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { // store custom services here... } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package return AuthenticateResult.NoResult(); } }

Comments

Add Comment:
Aproved Answers
0
Profile
Answered by Walter Tross on 9/26/2019 8:22:41 AM Score: 24 points

There are considerable changes in Identity from Core 1.x to Core 2.0 as the article you reference points out. The major change is getting away from the middleware approach and using dependency injection to configure custom services. This provides a lot more flexibility in customizing Identity for more complex implementations. So you want to get away from the middleware approach you mention above and move towards services. Follow the migration steps in the referenced article to achieve this goal.

Start by replacing app.UseIdentity with app.UseAuthenticationUseIdentity is depreciated and will not be supported in future versions. For a complete example of how to insert a custom claims transformation and perform authorization on the claim view this blog post.

Comments

Add Comment:

Post Your Answers

Existing Members

Sign in to your account
Email Address
Password
New Member?
Sign up and complete profile
Full Name
Email Address
I have read and agree to the Terms of Service and Privacy Policy
Please subscribe me to the StoodQ newsletters
Guideline to answer a question:

Useful tips to submit your answer
Please read below guidelines before you submit your answer for question.

  • Read and understand question for which you are submitting your answer.
  • Try to avoid grammatical and spell mistake while answering.
  • Do not post any irrelevant information in your answer.
  • Explain your answer with example or any reference link to help who posted question.
  • If you find irrelevant question, please report it to support. Click here to contact support.
  • You agree to the privacy policy and terms of use to submit any contents.

Note: StoodQ is online developers community which helps developer for their difficulty, lets help them with your value contribution.