Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding new authentication schemes dynamically

I'm building an ASP.Net Core 2 PoC for some authentication/authorization discussions/decisions that we need to make.

I'm currently at a point where a user has just defined a new OpenID Provider that this application wants to support.

One way to support this would be to read all of the configured providers during startup and configure them all inside ConfigureServices. But there are tantalising clues that it's also possible to do this without having to kill and restart the app.

IAuthenticationSchemeProvider has an AddScheme method that looks ideal. Now all I need to do is to construct an AuthenticationScheme object and I'm golden. It has a constructor AuthenticationScheme(string name, string displayName, Type handlerType) But I'm not sure how to use the types correctly from Microsoft.AspNetCore.Authentication.OpenIdConnect to correctly construct this object and to allow me to specify the OpenID Connect specific options for this.

I think the type I want to use for the third parameter is OpenIdConnectHandler . But what do I do with my options? (Or in the alternative - how do I get to do the equivalent of being able to supply an Action<OpenIdConnectOptions> delegate)


I found this github issue which is also of interest (no TryAddScheme method, so exceptions are possible, interesting in the abstract if we choose to persue this PoC further) but the small sample doesn't talk about options at all.

like image 582
Damien_The_Unbeliever Avatar asked Feb 21 '18 15:02

Damien_The_Unbeliever


People also ask

What are authentication schemes?

An authentication scheme is a definition of what is required for an authentication process. This includes the following: The login module stack used to determine whether a user is granted access to an application. The user interfaces used to gather the information required to authenticate a user.

What is HttpContext SignInAsync?

SignInAsync(HttpContext, ClaimsPrincipal) Sign in a principal for the default authentication scheme. The default scheme for signing in can be configured using DefaultSignInScheme. SignInAsync(HttpContext, ClaimsPrincipal, AuthenticationProperties) Sign in a principal for the default authentication scheme.

What is authentication scheme .NET Core?

Authentication is the process of determining a user's identity. Authorization is the process of determining whether a user has access to a resource. In ASP.NET Core, authentication is handled by the authentication service, IAuthenticationService, which is used by authentication middleware.

What is JwtBearerDefaults AuthenticationScheme?

Calling AddAuthentication(JwtBearerDefaults. AuthenticationScheme) simply enables authentication and sets “Bearer” as the default scheme. This means, when you use [Authorize] without specifying an authentication scheme, it will by default challenge the user using the handler configured for “Bearer”.


Video Answer


2 Answers

There's an example of how to do this here - https://github.com/aspnet/AuthSamples/tree/master/samples/DynamicSchemes

Keep in mind that for OAuth schemes, you'll have to do more then just calling schemeProvider.AddScheme and optionsCache.TryAdd - there's also a "postconfigure" step when adding options via the normal method. Here's the class - https://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthPostConfigureOptions.cs

So you can register the type OAuthPostConfigureOptions<OAuthOptions, OAuthHandler<OAuthOptions>> into your DI container then grab it via a constructor and call OAuthPostConfigureOptions.PostConfigure on your options before adding the options to the optionsCache.

like image 186
Nick Avatar answered Oct 24 '22 09:10

Nick


To expand upon the above answer (https://stackoverflow.com/a/49825151/2200690), in addition to the schemeProvider.AddScheme and optionsCache.TryAdd in https://github.com/aspnet/AspNetCore/blob/release/2.2/src/Security/samples/DynamicSchemes/Controllers/AuthController.cs, we need to make further changes in Startup.cs and AuthController.cs :

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ...
    // register to the DI container so it can be injected in the AuthController constructor.
    services.AddSingleton<OpenIdConnectPostConfigureOptions>();
    ...
}

In AuthController.cs

Inject the OpenIdConnectPostConfigureOptions in the AuthController constructor :

public AuthController(IAuthenticationSchemeProvider schemeProvider, 
    IOptionsMonitorCache<OpenIdConnectOptions> optionsCache,
    OpenIdConnectPostConfigureOptions postConfigureOptions)
{
    _schemeProvider = schemeProvider;
    _optionsCache = optionsCache;
    _postConfigureOptions = postConfigureOptions;
}

in the AddOrUpdate method of AuthController.cs, create an instance of the OpenIdConnectOptions class and then use this in the post configure step :

var options = new OpenIdConnectOptions
{
    Authority = "xxx-endpoint",
    CallbackPath = "/signin-oidc",
    ClientId = "XXX",
    ClientSecret = "XXX",
    ......
};
_postConfigureOptions.PostConfigure("oidc", options);                
_optionsCache.TryAdd("oidc", options);
like image 39
Suketu Bhuta Avatar answered Oct 24 '22 08:10

Suketu Bhuta