Middleware pipeline with UseAuthentication - c#

I've below code in Startup.Configure function
app.UseMiddleware<LogMiddleware>(_loggingLevelSwitch)
//other code
.ConfigureExceptionHandler(Logger, Configuration)
.UseIdentityServer()
.UseStaticFiles()
.UseMiddleware<ContextSetupMiddleware>()
.ConfigureMvcAndLocalization()
//other code
UseIdentityServer internally calls UseAuthentication
I've setup two schemes cookie and Bearer.
My expectation is after authentication ContextSetupMiddleware should be called but it is happening otherwise.
For cookie, I can understand since authentication will be done later and once signin is done it works as expected.
For Bearer, I think it should be part of pipeline since we add a scheme to authenticationbuilder.
Update:
Made defaultscheme as "Bearer" it started working as I wanted.
However the website has AccountLogin screen (cookie based Auth) and some RestAPI's (JWT based Auth).
Is there a way cookie based authentication is only applicable on AccountLogin screen. I can't add [Authorize] since it is login scree.

It is actually by design. The default scheme will override if at any middleware it is required then use context.AuthenticateAsync().
In my case, in ContextSetupMiddleware just call context.AuthenticateAsyc() and authentication done.

Related

Running custom C# middeware after authentication

In my Program.cs I have
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseMiddleware<MyCustomMiddleware>();
app.UseAuthorization();
app.UseEndpoints(cfg =>
{
cfg.MapControllers();
cfg.MapFallbackToController("Get", "Branding");
});
with the expectation that my custom middleware would run after authentication and therefore I would have a claims identity to play with.
But when my MyCustomMiddleware.Invoke is called the _next is AuthorizationMiddleware as expeted, but the context.User is not authenticated and has no claims.
However, the context.User is authenticated and has claims after _next.Invoke(context) returns.
So it looks like the middleware is running out of order.
What could be wrong?!
I believe that the behaviour you are seeing is correct if the AuthenticationMiddleware has yet to complete authenticating the user. Depending on your selected authentication scheme, the AuthenticationMiddleware may have returned back a HTTP 401 Challenge response to the client, or a HTTP 301 redirect to send the user to the authentication provider's login page if using OAuth. Check the context.Response inside of your middleware to be sure that this is in fact what is happening.
If the AuthenticationMiddleware hasn't short circuited the middleware, the unauthenticated request will still be passed on to the subsequently registered middleware before the response is sent back to the client.
Typically, its recommended that the AuthorizationMiddleware is ordered immediately after the AuthenticationMiddleware (see: ASP.NET Core Fundamentals Built-in Middleware), so that the user is properly authenticated and claims have been added. Because you have chosen to put a middleware in between, you are seeing the in-between process that ASP.NET core is following to authenticate and provide claims for the user.

JwtBearer Authentication with Custom Authorization in .net core 2.1

We have a Gateway (implemented using Ocelot), which performs both Authentication & Authorization of the calls before it reaches the APIs
For Authentication, the gateway uses JwtBearer like below
services.AddAuthentication(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Events = JwtBeaerEvents();
options.TokenValidationParameters = TokenValidationParameters(tokenConfig);
});
And, this validates the token correctly.
Apart from this, the Gateway is implemented with Custom Authorization, to which it reads the permission related settings using a custom configuration file. And, this Custom Authorization is added as a middleware
We try to add this Authorization middleware after Authentication middleware, like
app.UseAuthentication().UseAuthorizationMiddleware();
This works for a valid token. However, for an invalid token, irrespective of Authentication got failed, the call is being routed to AuthorizationMiddleware as well. And, based on these findings, looks like we need to go with DI, rather than middleware. But, what we want is a custom implementation for Authorization which accepts the permissions/policy/scope via config file (in the gateway) along with JwtBearer scheme, rather than decorating them in the API attribute. Could anyone throw some light on how to achieve the same?
Your help is much appreciated
The issue is due to the behaviour of .net core. When the Identity's IsAuthenticated flag is false, Http StatusCode is not set to 401 by the framework in case of Token validation failure during Authentication and also it proceeds to the next call. If only we used the Policy based Authorization, it would have been automatically taken care by RequireAuthenticatedUser() while building the Authorization Policy. However, since we are using a custom middleware, introduced one another middleware which replicates what DenyAnonymousAuthorizationRequirement does, like below
var user = httpContext.User;
var userIsAnonymous =
user?.Identity == null ||
!user.Identities.Any(i => i.IsAuthenticated);
if (userIsAnonymous)
{
httpContext.Response.StatusCode = 401;
return Task.CompletedTask;
}
return _next(httpContext);
We placed this middleware in between Authentication & Authorization middlewares and the issue has been resolved

Startup.cs security measures

I would like to know whether I am
(a) engaging in good coding practices,
(b) repeating myself harmlessly, or
(c) adding inefficient redundancies
For example:
1) In Configure() I can add RewriteOptions().AddRedirectToHttps();
2) In ConfigureServices() I can add
services.Configure<MvcOptions>(options =>
{ options.Filters.Add(new RequireHttpsAttribute()); });
Another example:
1) In Configure() I can add app.UseAuthentication();
2) In ConfigureServices() I can add .RequireAuthenticatedUser() to my AddMvc() call.
It seems in both examples that I can get away with just one call. Am I free and clear to keep only one call? And if so, which one is the better to keep?
I've searched around a fair bit and I can see all of these approaches in use, but I haven't found a resource that compares the relative merits of these calls, let alone indicates whether it's good or bad practice to use them together.
To take your first example:
1) In Configure() I can add RewriteOptions().AddRedirectToHttps();
2) In ConfigureServices() I can add services.Configure<MvcOptions>(options =>
{ options.Filters.Add(new RequireHttpsAttribute()); });
Both of these achieve essentially the same thing - they will redirect HTTP requests to HTTPS. The difference is which requests they are applied to.
If you use the rewriter middleware, all requests that make it to the middleware will be redirected to HTTPS.
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(); // Requests handled by this middleware won't be redirected to HTTPS
var options = new RewriteOptions()
.AddRedirectToHttps();
app.UseRewriter(options); // All requests that make it this far will be redirected from HTTP to HTTPS
app.UseMvc(); // Requests guaranteed to be HTTPS
}
In the second case, where you use a global filter to apply the RequireHttpsAttribute, only requests that make it to the MvcMiddleware will be redirected to HTTPS.
In terms of best practices, I recommend using the rewriter middleware - you can add it to the start of your middleware pipeline, and then all of your requests are required to HTTPS, instead of just the requests that make it to the MVC middleware.
In your second example, the two methods actually do different things:
app.UseAuthentication() - authenticates the request, and sets the User associated with the request by e.g. deserializing the user principal stored in the cookie
RequireAuthenticatedUser() - Requires that a User has logged in before action methods on your controllers are called. If the user hasn't logged in, they are redirected to the login page. In this case, you must call app.UseAuthentication() before app.UseMvc(), otherwise the User for the request will not be set even if you've logged in, and you will be redirected to the login page.

Stateless authentication with NancyFx, OWIN and JWT

I have a OWIN self-hosted application which has a front-end where users can sign up. Nancyfx does the logic for routing and Models, and in the documentation I saw that Nancyfx comes with 3 types of authentication.
Forms (Nancy.Authentication.Forms)
Basic (Nancy.Authentication.Basic)
Stateless (Nancy.Authentication.Stateless)
I've settled on the Stateless Authentication, and following this example I tried to set up a basic form of authentication.
I wanted to expand further on this, using JWT to have some basic info handy and as a form of basic authentication (e.g. client has token so he's verified.), but this is where I run into a few problems.
The way I authenticate Home -> login -> redirect upon success causes my Response.Header.Authorization to be cleared, not allowing me to catch the token in my custom Bootstrapper.
Code:
protected override void RequestStartup(TinyIoCContainer requestContainer, IPipelines pipelines, NancyContext context)
{
AllowAccessToConsumingSite(pipelines);
StatelessAuthentication.Enable(pipelines, requestContainer.Resolve<IStatelessAuthConfigurationFactory>().Config());
}
//Returns ClaimsPrincipal or Null;
public StatelessAuthenticationConfiguration Config()
{
if(_stat == null)
{
_stat = new StatelessAuthenticationConfiguration(VerifyToken);
}
return _stat;
}
Since my authorization header disappears every request, I would need to persist the JWT. I figure it's possible using OWIN environment or Nancy context, but would this be advisable + what would the effect be for a multi-user environment regarding security.
OWIN has it's own authentication Manager that I could use, I've experimented with it, but it tends to provide a cookie upon successful sign in, which it doesn't seem to revoke on Logout. I just ran into a few issues overall with it, so I settled on NancyFx authentication. (not really a problem as a more general remark I suppose)
Thanks in advance for any help!
Regarding (1), if you roll your own redirection after a successful login, consider setting the Authorization header during the redirect, e.g.
return Response.AsRedirect("/").WithHeader("Authorization", token);
It's actually the responsibility of the client to hold the valid JWT token after authentication. Returning it as a cookie (and deleting it upon logout) could make things easier in terms of client-side implementation and avoid the token persistence issue.
Regarding (2), not really, it's not necessary. JWT tokens are self-contained, and that's why they're useful in stateless auth scenarios.

Microsoft.Owin.Security.Oauth Bearer Token Authorization Interception

I am in the process of implementing OAuth 2 on a web API with Microsoft.Owin.Security.Oauth.
I would like to keep the bearer token small and keep private data out of it. To do this, I'd like to store a session ID in it and then fill out the ClaimsIdentity programmatically once the session ID has been received and processed. This would also give me greater flexibility related to how logging out, role changes, and other things can be handled.
This should be a matter of intercepting the right event and adding a delegate. However, I can't find an event that gets fired on my authorization provider, a subclass of "OAuthAuthorizationServerProvider". I thought that "AuthorizeEndpoint" would do it, but it does NOT get fired for API methods decorated with the [Authorize] attribute, even though these methods clearly get checked for a valid bearer token. When I overrode "MatchEndpoint", all I found is that a call to a method that was decorated with [Authorize] showed up with "IsAuthorizeEndpoint" and "IsTokenEndpoint" both set to false. The latter makes sense to me, the former does not.
I am very confused. Can somebody who knows this library tell me what's going on and what I need to do to accomplish this seemingly simple idea?
I think you may be conflating resources marked with the AuthorizeAttribute with the OWIN Authorize endpoint. The AuthorizeEndpoint and TokenEndpoint are setup in the OWIN configuration as receivers for their respective authentication types. The Authorize Endpoint is used for web-base, user-agent authentication and is where you would expect a browser to be redirected should they be unauthorized to access a resource. The token endpoint is used instead for username-password token authentication and refreshing, and is the one you want. Assuming you are assigning both of these within your OWIN startup configuration, the event you may be looking to overload for OnValidateTokenRequest to ensure that your customizations to the token do not cause it to be invalid once the client tries to utilize it again. You would want to do your actual modifications to the token at the OnTokenEndpoint event.

Categories