ASP.NET Core Disable Authentication in Development Environment

ASP.NET Core disable authentication in development environment

You can bypass authorization in development environment by applying AllowAnonymousAttribute to your endpoints.

Example 1 dotnet new webapi template, .NET 6 (ASP.NET Core 6) and newer

Use AllowAnonymous method in Program.cs to apply AllowAnonymousAttribute to all controllers:

if (app.Environment.IsDevelopment())
app.MapControllers().AllowAnonymous();
else
app.MapControllers();

Example 2 dotnet new webapi template, .NET Core 3.0 - .NET 5 (ASP.NET Core 3.0-5)

Use WithMetadata method in Startup.Configure() to apply AllowAnonymousAttribute to all controllers:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseEndpoints(endpoints =>
{
if (env.IsDevelopment())
endpoints.MapControllers().WithMetadata(new AllowAnonymousAttribute());
else
endpoints.MapControllers();
});
}

Example 3 dotnet new webapi -minimal template, .NET 6 (ASP.NET Core 6) and newer

Use AllowAnonymous method to apply AllowAnonymousAttribute to a minimal API endpoint:

var hiEndpoint = app
.MapGet("/hi", () => "Hello!")
.RequireAuthorization();

if (app.Environment.IsDevelopment())
hiEndpoint.AllowAnonymous();

Details

endpoints and app from the examples above, both implement IEndpointRouteBuilder which has multiple Map extension methods like MapControllers() and MapGet(...) that return IEndpointConventionBuilder.

WithMetadata (available since .NET Core 3.0) and AllowAnonymous (available since .NET 5) are extensions for IEndpointConventionBuilder and can be called upon the results of those Map methods.

AllowAnonymousAttribute's description from the docs:

Specifies that the class or method that this attribute is applied to does not require authorization.

Disable authentication in Asp.Net Core 3.0 for development

You could try something like this.

public class Startup 
{
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
Environment = env;
}

public Microsoft.AspNetCore.Hosting.IWebHostEnvironment Environment { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(opts =>
{
if (Environment.IsDevelopment())
{
opts.Filters.Add<AllowAnonymousFilter>();
}
else
{
var authenticatedUserPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
opts.Filters.Add(new AuthorizeFilter(authenticatedUserPolicy));
}
});
}

}

Ignore authorization at development environment

I found something that works for me.
Let me know if you have a better solution

My Configuration:

app.UseHttpsRedirection(); 
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseRouting();
if (env.IsStaging() || env.IsDevelopment())
{
//on staging/development dont require authentication
app.Use(async (context, next) =>
{
// Set claims for the test user.
var claims = new[] { new Claim("role", "Admin"), new Claim("sub", "some guid") };
var id = new ClaimsIdentity(claims, "DebugAuthorizationMiddleware", "name", "role");
// Add the test user as Identity.
context.User.AddIdentity(id);
// User is now authenticated.
await next.Invoke();
});
}
else
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

Credit:
Programmatically add [AllowAnonymous] attribute to all my controller methods

How do I disable/enable authentication at runtime in Asp.Net Core 2.2?

Yes you can!

The authorization system in ASP.NET Core is extensible and you can implement your scenario easily with poliy-based authorization.

Two main things to know to get going:

  • an authorization policy is made of one or more requirements
  • all of the requirements must be satisfied for a policy to succeed

Our goal is then to create a requirement which is satisfied if any of the following statements is true:

  • the maintenance mode is not enabled, or
  • the user is authenticated

Let's see the code!

The first step is to create our requirement:

public class MaintenanceModeDisabledOrAuthenticatedUserRequirement : IAuthorizationRequirement
{
}

We then have to implement the handler for this requirement, which will determine if it's satisfied or not. The good news is handlers support dependency injection:

public class MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler : AuthorizationHandler<MaintenanceModeDisabledOrAuthenticatedUserRequirement>
{
private readonly IMaintenanceModeDataService _maintenanceModeService;

public MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler(IMaintenanceModeDataService maintenanceModeService)
{
_maintenanceModeService = maintenanceModeService;
}

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MaintenanceModeDisabledOrAuthenticatedUserRequirement requirement)
{
if (!_maintenanceModeService.IsMaintenanceModeEnabled || context.User.Identities.Any(x => x.IsAuthenticated))
{
context.Succeed(requirement);
}

return Task.CompletedTask;
}
}

Next, we need to create an authorization policy that uses this requirement, and you have 2 choices here:

  • you can redefine the default policy, used when "empty" [Authorize] attributes are used, or
  • create an explicit policy that you'll have to reference in your attributes, like [Authorize(Policy = "<your-policy-name>")]

There's no right or wrong answer; I'd pick the first option is my application had only one authorization policy, and the second one if it had several of them. We'll see how to do both:

services
.AddAuthorization(options =>
{
// 1. This is how you redefine the default policy
// By default, it requires the user to be authenticated
//
// See https://github.com/dotnet/aspnetcore/blob/30eec7d2ae99ad86cfd9fca8759bac0214de7b12/src/Security/Authorization/Core/src/AuthorizationOptions.cs#L22-L28
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement())
.Build();

// 2. Define a specific, named policy that you can reference from your [Authorize] attributes
options.AddPolicy("MaintenanceModeDisabledOrAuthenticatedUser", builder => builder
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement()));
});

Next, you need to register the requirement handler as an IAuthorizationHandler, as indicated in the official docs

// The lifetime you pick is up to you
// You just need to remember that it's got a dependency on IMaintenanceModeDataService, so if you
// registered the implementation of IMaintenanceModeDataService as a scoped service, you shouldn't
// register the handler as a singleton
// See this captive dependency article from Mark Seeman: https://blog.ploeh.dk/2014/06/02/captive-dependency/
services.AddScoped<IAuthorizationHandler, MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler>();

The final step is to apply the [Authorize] attributes on your controllers/actions as needed.

// 1. If you redefined the default policy
[Authorize]
public IActionResult Index()
{
return View();
}

// 2. If you defined an explicit policy
[Authorize(Policy = "MaintenanceModeDisabledOrAuthenticatedUser")]
public IActionResult Index()
{
return View();
}

cookie or identity authentication in asp.net?

From Identity on ASP.NET Core , we can see

ASP.NET Core Identity:

Is an API that supports user interface (UI) login functionality.
Manages users, passwords, profile data, roles, claims, tokens, email
confirmation, and more.
Users can create an account with the login
information stored in Identity or they can use an external login
provider.

ASP.NET Core Identity is a complete, full-featured authentication provider for creating and maintaining logins. And it is cookie based, the user's identity stored in a cookie. So a cookie-based authentication provider without ASP.NET Core Identity can be used too, and it is Use cookie authentication without ASP.NET Core Identity .

ASP.NET Core Identity serializes a user principal into an encrypted cookie and then, on subsequent requests, validates the cookie, recreates the principal and assigns it to the User property on HttpContext. If you want to provide your own login screens and user databases you can use cookie authentication without ASP.NET Core Identity.

Asp.Net Core - modify authentication schemes while server is running

The key for adding new scheme resides withing the IOptionsFactory<TOptions> object.

While you may configure multiple IAuthenticationHandler's of same type the authenticationScheme fields specifies each's configuration (in source code it is referred as TOptions).

As all runtime options are configured and "sealed" at startup (see: options in asp.net core). It is not possible to add new option at runtime (at least without writing some code).

To add new authentication scheme we need to:

  1. Add new ConfigureNamedOptions<TOptions> to the IOptionsFactory<TOptions>. This provides the configuration to the scheme's IAuthenticationHandler when it is initialized

  2. Add new scheme to IAuthenticationSchemeProvider. This binds an instance of AuthenticationHandler to the specific authorization scheme options provided in step 1

  3. Clear IOptionsMonitorCache<TOptions> cache - Forces options refresh

This code adds OpenIdConnectHandler

//adds oidc2 scheme
var toAdd = new AuthenticationScheme("oidc2", "oidc2- display", typeof(OpenIdConnectHandler));
if (!_authenticationSchemeProvider.TryAddScheme(toAdd))
return false;
var a = new Action<OpenIdConnectOptions>(options =>
{
//configuration goes here
options.Authority = "https://demo.identityserver.io/";
options.ClientId = "c-id2";
});
_factory.AddOption("oidc2", a);
//clear cache
var allSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
var services = Request.HttpContext.RequestServices;
var c = services.GetService<IOptionsMonitorCache<OpenIdConnectOptions>>();
foreach (var s in allSchemes)
c.TryRemove(s.Name);

Click here to see source code on github

before adding oidc2 scheme: oidc1 can access the identity server while oidc2 cannot
Sample Image

Sample Image

After adding oidc2 scheme programmatically - oidc2 can access identity provider
Sample Image

ASP.NET disable authorization depending on host

Here is the code to determine if Windows authentication is supported:

string iisHttpAuth = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH");
bool isWindowsAuthenticationSupported = false;
if (iisHttpAuth != null && iisHttpAuth.ToLowerInvariant().StartsWith("windows"))
isWindowsAuthenticationSupported = true;


Related Topics



Leave a reply



Submit