Custom AuthorizationHandler not being invoked - c#

I'm working with Identity for the first time. I'm following along with Microsoft's Policy-based authorization tutorial, but when I add a policy and requirement, the handler for that requirement is never called. In fact, it acts like the handler is never retrieved from DI (if I comment out the line adding the handler to the DI container, the app's execution doesn't change at all).
The NotLoggedInHandler is meant to ensure that certain pages are only accessed by users who aren't logged in. The handler just succeeds and returns, so the requirement should always pass:
public class NotLoggedInHandler : AuthorizationHandler<NotLoggedInRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, NotLoggedInRequirement requirement)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
}
But when I access a protected Razor Page, I get this in my log output:
[xx:xx:xx INF] Authorization failed. These requirements were not met: WebApp.Policies.NotLoggedInRequirement
I've fiddled with the order of adding services. It doesn't seem to matter whether NotLoggedInHandler is registered before or after services.AddAuthorization.
My Startup.cs file looks like this:
public class Startup
{
// Other methods/ctor omitted
public void ConfigureServices(IServiceCollection services)
{
// Identity services omitted
// Set up Authentication
services.AddAuthentication(...);
// Set up Authorization
services.AddAuthorization(
options =>
{
options.AddPolicy(
"RequireAnonymous",
policy =>
{
policy.Requirements.Add(new NotLoggedInRequirement());
}
);
}
);
services.AddTransient<AuthorizationHandler<NotLoggedInRequirement>, NotLoggedInHandler>();
// Other services omitted, not related to Identity/auth
}
}

Turns out, I was making assumptions and just needed a step back. As detailed in the tutorial from Microsoft, handlers are registered against the IAuthorizationHandler interface.
The tutorial shows how to create a handler for a single requirement and a handler for multiple requirements, but only explicitly shows how to register a handler for multiple requirements. It wasn't explicitly stated in the tutorial that the process is identical, and based on my experience with ASP.NET's DI container, I thought my solution made sense (because a one-to-one handler implements IAuthorizationHandler<TRequirement>, but a one-to-many handler implements IAuthorizationHandler).
However, it is the same regardless. I'm not sure how ASP.NET resolves these dependencies since any number of handlers will be registered to the IAuthorizationHandler interface, but it works regardless.
Changing this:
services.AddTransient<AuthorizationHandler<NotLoggedInRequirement>, NotLoggedInHandler>();
to this:
services.AddTransient<IAuthorizationHandler, NotLoggedInHandler>();
effectively solved the problem.

Related

Extend IPrincipal in .NET Core 2.1 with Windows Authentication

I'm trying to extend IPrincipal in .NET Core with Windows Authentication.
In a previous project (using .NET Framework 4.6.1) on Application_Start() I added the code below to extend IPrincipal:
protected void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
{
if (e.Identity != null && e.Identity.IsAuthenticated)
{
NgUser opPrincipal = CustomStaticMethod.GetUserAD();
HttpContext.Current.User = opPrincipal;
}
}
And this is my custom class
public class NgUser : IPrincipal
{
// code removed for abbr ...
}
Then every time in a controller casting HttpContext.Current.User as CustomPrincipal I'd have access to the custom properties without having to use claims or using static extensions or storing an object in session.
Now in .NET Core I've seen you can customize claims transformation and I've also read this and they basically extended IPrincipal.
I'd prefer to extend IPrincipal with my custom class, register it in Startup.cs and be able to access it in my controllers.
Surely this is doable, question is how?
I hope this is clear and some one can help me.
Many thanks
It's very doable. The easiest way is to add a piece of middleware, which behaves similar to OnAuthenticate, to the Configure() pipeline in .NET Core. Here you'll swap out the IPrincipal. Note, this only works if the web app is set to run with Windows Authentication only in IIS/IIS Express. Anonymous authentication adds extra overhead.
If you have this simple Win auth setup, in your Startup.cs put this near the top of your Configure(IApplicationBuilder app) method:
// Because IIS automatically captures the user login, by the time the app is touched
// in any request, the context (ctx) User is already present.
app.Use(async (ctx, next) =>
{
if (ctx.User?.Identity?.IsAuthenticated == true)
{
NgUser opPrincipal = CustomStaticMethod.GetUserAD();
ctx.User = opPrincipal;
}
// be sure to continue the rest of the pipeline!
await next.Invoke();
});
```

How should I use appsettings.json config key/values in my ConfigurationServices ASP.NET Core 2.0 on startup?

I'm trying to configure my services for an ASP.NET Core 2.0 app/website.
I wish to reference some key/values from my appsettings.json file, in this method.
I'm not sure if what I'm going is OK or not:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddJsonFormatters()
.AddCors();
var applicationSettings = Configuration.GetSection("Settings").Get<ApplicationSettings>();
services.AddSingleton(applicationSettings);
// ** THIS IS WHAT I ORIGINALLY HAD, BUT IT'S ONLY SETTING
// THE VALUE IN DI/IOC.
//services.Configure<ApplicationSettings>(options => Configuration.GetSection("Settings")
// .Bind(options));
var foo = new Foo(applicationSettings.SomeSetting);
services.AddSingleton(foo);
}
See how i'm manually adding a singleton and then later, referring a value from the app settings instance?
vs
just configuring ...
So, is either way OK or is there a specific reason for either/or?
Remember -> i'm going to need to inject my settings into controllers, etc...
Technically, you can do either. In both cases, you have the configuration registered and available through dependency injection, so everything can depend on it and will get the configuration instance.
You are also using the centrally set up Configuration there, so you have all the benefits from the configuration stack there, e.g. multiple providers or environment specific overrides.
However, the favor has definitely moved to the IOptions way of consuming custom configuration. It’s the “state of the art” and used throughout ASP.NET Core for literally everything. It also allows you to switch to options that can be updated at runtime. That’s very powerful and might become useful eventually (not necessarily for your specific situation with the singleton, but maybe for something else).
It’s also really easy to set this up, actually shorter than what you tried:
services.Configure<ApplicationSettings>(Configuration.GetSection("Settings"));
services.AddSingleton<Foo>();
Note that, even for singletons, you shouldn’t explicitly create a new instance of it, but let DI handle that. If your class has the correct constructor, dependencies will be automatically injected anyway:
public class Foo
{
private readonly ApplicationSettings _settings;
public Foo (IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
}
}
Of course, Foo can also have more dependencies here. Since it’s going to be constructed by DI, you can just add more dependencies in the constructor, without having to update some new call somewhere.
If you need to configure certain services with settings that depend on your configuration, you still should not bind your configuration there directly. All of configuration is DI-based, so you just need to inject the right thing; a IConfigureOptions<T>. That’s basically the thing that provides the IOptions<T> to services later. In your JWT case, this could look like this:
// instead of passing an option configuration delegate here…
services.AddAuthentication().AddJwtBearer();
// … we register a IConfigureOptions<JwtBearerOptions> instead
services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>();
// … ConfigureJwtBearerOptions could look like this:
class ConfigureJwtBearerOptions : IConfigureOptions<JwtBearerOptions>
{
private readonly ApplicationSettings _settings;
public ConfigureJwtBearerOptions(IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
}
public void Configure(JwtBearerOptions options)
{
// configure JwtBearerOptions here, and use your ApplicationSettings
options.MetadataAddress = _settings.JwtMetadataAddress;
}
}
This might seem unnecessarily verbose compared to just passing a delegate to AddJwtBearer() but note that this is exactly what happens under the hood when you pass that delegate: An IConfigureOptions<JwtBearerOptions> object will be created that calls your delegate in the Configure() call. So this is really just the same.
Note that for authentication schemes, you might actually set up a IConfigureNamedOptions<T> instead, which is almost the same thing except it can configure the options based on a name. For authentication schemes, that is the scheme name, so basically you check the scheme name in Configure() and then decide how to configure your options.
As for creating singleton instances, especially expensive ones, I would argue that ConfigureServices is the wrong place for such a thing. ConfigureServices is called very early in the application startup phase, when the whole DI infrastructure does not exist yet. So you could not rely on anything when creating your instance. I would also argue that it is still not your job to create the object but you should DI handle the creation of it and as such give it also control over its lifecycle.
If you absolutely need to control when the instance is created, I would suggest you to use the lifecycle events for this: Basically, after the application has set up properly but before a first request comes in, you request the instance of your services and initialize it. That way, you can still have it fully depend on DI, and it won’t be created lazily with the first request.
You can register lifecycle handlers in the Configure method:
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
{
applicationLifetime.ApplicationStarted.Register(() =>
{
// application has started, request the singleton here to trigger DI to
// create the instance
app.ApplicationServices.GetService<ExpensiveSingleton>();
});
// …
}
}
Well the problem with that approach is that it will be impossible to load multiple configuration sections through DI. The Configuration API has many features, such as pluggable configuration provides, snapshots, etc.
I would suggest you at least use a class to bind you configuration section against, so DI can inject it based on its type. If you further down the line have need to another configuration class you won't run into issues.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration

CookieAuthentication and AspNet Core 2.0 migration

I can't find a way how to migrate the application from aspnet core 1.1 to 2.0 which is using cookie authentication.
Most useful resources I already know are:
https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x#cookie-based-authentication
https://github.com/aspnet/announcements/issues/262
https://github.com/aspnet/Home/issues/2128 (my own question)
Unfortunately, I am still stuck. Here is how I do it:
In Startup.cs ConfigureServices(IServiceCollection services)I have:
services.AddSingleton<IConfigureNamedOptions<CookieAuthenticationOptions>, CookieAuthenticationOptionsSetup>();
and later:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
The CookieAuthenticationOptionsSetup class implements IConfigureNamedOptions and sets options.Cookie.Name = "test" inside the Configure method.
I event tried to manually create and set Name property to "Cookies".
If I try to change the name of cookie with lambda expression inside Startup.cs AddCookie method, it works as expected. But if I don't, the CookieAuthenticationOptionsSetup is never used and the default cookie name (.AspNetCore.Cookies) is used.
What I am missing?
AddCookie() by default calls AuthenticationBuilder.AddScheme. From there, we can learn how the options would be ideally registered if you passed them to the AddCookie call:
Services.Configure(authenticationScheme, configureOptions);
So let’s take a look at how Services.Configure works with named options. What ultimately gets registered on the service collection are IConfigureOptions<CookieAuthenticationOptions>>.
So I would guess that is the exact type that is being looked up later when the options are resolved via DI. And in fact, that is the exact type that is being request by the OptionsFactory that is being used by the OptionsMonitor which is requested by the authentication handler.
So, tl;dr: You are registering your custom configuration as the wrong type. You should register it as an IConfigureOptions<>:
services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, CookieAuthenticationOptionsSetup>();
Note of course that your CookieAuthenticationOptionsSetup needs to implement IConfigureNamedOptions properly and respond to a Configure call with your scheme name (CookieAuthenticationDefaults.AuthenticationScheme).
In addition to this answer, I also had to add Name property to the class which implements IConfigureNamedOptions<T> and set it in public void Configure(string name, CookieAuthenticationOptions options) method.
Few additional notes for those who will have the same problem:
To apply Authorize attribute globally, authentication scheme must be added (worked without it previously):
services.AddMvcCore(a =>
{
var policy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
a.Filters.Add(new AuthorizeFilter(policy));
});
To use IsAuthenticated property inside middleware, app.UseAuthentication() must be called before registering the middleware.
It is not exactly clear what is the question...
But if you want just to set cookie name (or other options) and really do not need to implement IConfigureNamedOptions try something like this:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.Cookie.Name = "TestName";
}

Nancy IoC per request auto registration

We have an ASP.NET REST service implemented with Nancy (and TinyIoc), which interfaces with a quite large legacy application. We would like to transition to full dependency injection. At the moment most of our modules instantiate the controllers directly, and takes a context class which holds the request information using the NancyContext Context property. Something like this:
public FooModule(ILegacyService legacyService) {
Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}
We would like to inject the controllers directly in the module, and get everything handled by the super-duper-happy-path :)
Our problems all stem from the fact that we need information from NancyContext. The url, headers etc. So we have attempted various approaches to get to dependency injection nirvana.
Attempting to inject controllers failed, since they're instantiated in application scope, and so any dependency to RequestContext would not have the current context information. Even registering RequestContext in ConfigureRequestContainer did not ripple through to all dependants, and they would hold references to an out of date RequestContext.
We have tried to property inject the context using IRequestStartup, and this seemed successful, until we ran into concurrency issues. Simultaneous requests in different threads would overwrite the application scope RequestContext.
We found out that we could call container.AutoRegister() in ConfigureRequestContainer, but this resulted in severe lag, since registrations takes seconds with the amount of types we have.
Using AsPerRequestSingleton() in ConfigureApplicationContainer seems like it will register once, and then instantiate per request, but there doesn't seem to be a way to get auto registration to adhere to this.
It seems like we need to register all types manually, and keep this configuration up to date manually. Is this the case? We really would prefer to have some type of auto registration with per request lifetime.
I have created a small test project (https://github.com/Rassi/NancyIocTest) in which I attempted some of these solutions.
Using DefaultNancyAspNetBootstrapper you can create your own auto registering like this:
public class Bootstrapper : DefaultNancyAspNetBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
var assemblyClasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsClass);
foreach (var assemblyClass in assemblyClasses)
{
var interfaces = assemblyClass.GetInterfaces();
if (interfaces.Count() == 1)
{
container.Register(interfaces[0], assemblyClass).AsPerRequestSingleton();
}
}
}
Everything is then instantiated per request, and you can inject context information using RequestStartup():
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
var requestUrl = container.Resolve<IRequestUrl>();
requestUrl.Context = context;
}
}
This is a simple proof of concept, which will find classes which implement one interface, and register it to that. A couple of issues should probably be handled, such as: Registering classes implementing multiple interfaces (perhaps using the convention of registering Name to IName). And also handling multiple classes registering the same interface.

Best practise for optional injecting of current user

In our ASP.NET MVC project we are using Ninject to resolve our dependencies needed by the controllers.
One of these dependencies is the current user HttpContext.Current.User.Identity. If the user is authenticated we would like to instantiate a user object and several services which relies on it. But we would like to do this not manually but let ninject inject these instances to the controller.
So we get into trouble now, since a url can be located without being authenticated of course. Then ninject tries to resolve the instances before asp.net can redirect to the login page.
I can think of the solution, that we configure ninject do just inject when user is authenticated:
kernel.Bind<User>().ToMethod(GetUser).When(context => HttpContext.Current.User.Identity.IsAuthenticated).InRequestScope();
The problem here is that even if the user is not authenticated ninject instantiates a default object, so my services crashes or needs to check the instance anyhow.
Null checks would me much more acceptable but I wouldn't like to activate AllowNullInjection setting of Ninject.
So my question is whats the best practise for doing such conditional things?
Are there Ninject features I could use in these cases or shouldn't I inject these dependencies anyway?
I assume you are talking about a situation where a non-authenticated user could try to navigate to a page that normally requires authentication, but without first going through the login process. Ninject would then be unable to inject the current user object into the controller because it's not yet known and will throw an exception.
I can see 2 options:
The first option is instead of injecting the current user, create a factory or provider that retrieves the current user details and inject this instead. The controller can then call the provider to get the current user and if the user is unavailable you can redirect to the login page.
public OrdersController(IUserProvider userProvider)
{
this.userProvider = userProvider
}
public void DoSomething()
{
var user = this.userProvider.GetCurrentUser();
if (user == null)
RedirectToLogin();
// continue doing something
}
public class UserProvider : IUserProvider
{
public User GetCurrentUser() { ... }
}
The problem with this option is that you'll need to do this potentially in many controllers (it's a "cross cutting concern") and you don't want to have to repeat the code that does the redirect over and over. Instead, a second option would be to use the Decorator design pattern to create an interceptor that checks for logged in users before forwarding on to the real controller.
The way I've done something similar in the past is using the Ninject Interception Extension to create an attribute that marks which controllers require authentication, like this (bit psuedo-codey):
public class AuthenticationInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
bool authenticated = // ... get the current user ...
if (authenticated)
invocation.Proceed();
else
RedirectToLoginPage(); // however you want to do this
}
}
public class RequiresAuthenticationAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<AuthenticationInterceptor>();
}
}
[RequiresAuthentication]
public class OrdersController : IOrdersController
{
// assume you've already been authenticated
}
The interceptor will automatically be created whenever a class that's decorated with RequiresAuthentication is created and the current user credentials will be checked. If they are invalid, the request will be forwarded to the login page, otherwise it will continue as normal. This one interceptor can then be written and tested once whilst being used in many places without duplicating code.
Just as a simple auth and non auth answer that some may find useful.
kernel.Bind<ICustomUser>()
.To<User>()
.When(ctx => HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
kernel.Bind<ICustomUser>()
.To<Guest>()
.When(ctx => !HttpContext.Current.User.Identity.IsAuthenticated)
.InRequestScope();
Otherwise anything more complex Adam Rodgers awnser is better :)

Categories