With Core 1.1 followed @blowdart's advice and implemented a custom middleware:
https://stackoverflow.com/a/31465227/29821
It worked like this:
- Middleware ran. Picked up a token from the request headers.
- Verified the token and if valid built an identity (ClaimsIdentity) that contained multiple claims which then it added via HttpContext.User.AddIdentity();
- In ConfigureServices using services.AddAuthorization I've added a policy to require the claim that is provided by the middleware.
- 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.
Best Answer
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 theIAuthenticationHandler
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 extendsAuthenticationHandler<>
), there's an override forTask<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 a401 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 theDefaultAuthenticateScheme
andDefaultChallengeScheme
when usingservices.AddAuthentication(...)
.Here's an example of what this should all look like:
In Startup.cs / ConfigureServices() add:
In Startup.cs / Configure() add:
Create a new file CustomAuthExtensions.cs
Create a new file CustomAuthOptions.cs
Create a new file CustomAuthHandler.cs