I\'ve API created in asp.net core 2.0 where I am using mixed mode authentication. For some controllers JWT and for some using windows authentication.
I\'ve no proble
I just had the same need. I'm not yet running things on IIS, only Kestrel, but I managed to adapt Microsoft's own instructions to get per controller/controller method authentication using JWT and Windows auth.
All I did was modify Startup.cs/ConfigureServices from
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false; // should be set to true in production
x.SaveToken = true;
x.TokenValidationParameters = generateTokenValidationParameters();
});
to this
services.AddAuthentication()
.AddNegotiate()
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false; // should be set to true in production
x.SaveToken = true;
x.TokenValidationParameters = generateTokenValidationParameters();
});
So, basically, removed the Default Authentication and Challenge scheme, added Negotiate (Windows Auth) and JwtBearer using my pre-existing JWT configuration.
In the controllers, I enabled Windows Authentication by adding this authorization header
[Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)]
And similarly, I replaced my existing Authorization headers that previously did JWD (given that it was the default auth/challenge scheme) with this
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
My app will be hosted by Kestrel, so IIS won't be an issue, but I'll try that next, anyway.
@edit: I've now mastered IIS Express, too. Enabled Windows Auth through VS's IIS Express settings (Project Properties, Debug tab), then ensure that IIS does not perform automatic authentication for in and out of processing hosting by adding this to Startup.ConfigureServices (right after AddAuthentication).
//disable automatic authentication for in-process hosting
services.Configure<IISServerOptions>(options =>
{
options.AutomaticAuthentication = false;
});
//disable automatic authentication for out-of-process hosting
services.Configure<IISOptions>(options =>
{
options.AutomaticAuthentication = false;
});
I then changed my test controller to have a method with the following authorize header
[Authorize(AuthenticationSchemes = IISDefaults.AuthenticationScheme)]
And when I access that method with a browser that trusts the URL, I'm being let in and User.Identity is my windows identity.
Now off to see if that also works on an actual IIS.
You need to ensure, that you NOT setting Authorization: Bearer <JWT_token>
HTTP header when you trying to use Windows Auth. The key point here is how "Windows Auth" actually works. Let's look how it works with browser for example.
Let's call this "a normal flow":
http://example.com/api/resource
in your browser;http://example.com/api/resource
without any Authorization
HTTP Header for now (an anonymous request);Authorization
header and respond with 401 Not Authorized
status code with WWW-Authenticate: NTLM,Negotiate
HTTP Header setted up ("Go away, no anonymous access. Only 'NTLM' or 'Negotiate' guys are welcome!");401
response, find out that request was anonymous, looks to WWW-Authenticate
header and instantly repeat request, now with Authorization: NTLM <NTLM_token>
HTTP Header ("Ok, take it easy, mr. Web server! Here is my NTLM token.");Authorization
header, verify it and execute request ("Ok, you may pass. Here is your resource.").Things goes a little different, when you initialy set Authorization
header to some value:
http://example.com/api/resource
with JWT authorization;http://example.com/api/resource
with Authorization: Bearer <JWT_token>
HTTP Header now;Authorization
header with "Bearer" authentication scheme and again respond with 401 Not Authorized
status code with WWW-Authenticate: NTLM,Negotiate
HTTP Header setted up ("Go away, we don't know who are this 'Bearer' guys, but we don't like them. Only 'NTLM' or 'Negotiate' guys are welcome!");401
response, find out that request was authorized and decide that this token is bad. But, as you actually set Authorization
header, this means that you actually have some credentials. And so it ask you for this credentials with this dialog.