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:
Add new
ConfigureNamedOptions<TOptions>
to theIOptionsFactory<TOptions>
. This provides the configuration to the scheme'sIAuthenticationHandler
when it is initializedAdd new scheme to
IAuthenticationSchemeProvider
. This binds an instance ofAuthenticationHandler
to the specific authorization scheme options provided in step 1Clear
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
After adding oidc2
scheme programmatically - oidc2
can access identity provider
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
Entity Framework - Capitalizing First Property Name Letter
Instantiate a Class from Its Textual Name
Convert JavaScript Regex to C#
How to Share Sessions Between PHP and ASP.NET Application
How to Stop an Application from Opening
How to Call R Functions from C# and Retrieve The Result in C#
Openssl.Net Porting a Ruby Example to C# (From Railscasts 143 Paypal-Security)
Getters, Setters, and Properties Best Practices. Java VS. C#
Recursive Linq Query: Select Item and All Children with Subchildren
Writing File to Web Server - ASP.NET
How to Pass Current User Information to All Layers in Ddd
How to Get Data by SQLdatareader.Getvalue by Column Name
How to Convert Code from C# to PHP
Pinvokestackimbalance C# Call to Unmanaged C++ Function
How Could the New Async Feature in C# 5.0 Be Implemented with Call/Cc