I have below code to bypass adding authentication during local development, I am using Azure AD & .NET Core.
#if !DEBUG
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));
#endif
However since I have my controller protected by Authorize attribute, how do I bypass the Authorize attribute inside Controller during local development:
[Authorize(Roles = "Buyer")]
public class ProductController : ApiBaseController
{
}
In .NET Framework I have below code to override the Authorize attribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
#if DEBUG
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return true;
}
#endif
}
What is the equivalent code for .NET Core ? or is there any other way we can override Authorize attribute in Startup.cs class ?
CodePudding user response:
I think you can use a IClaimsTransformation
for that. In this case, I'll just add a role to everyone, but when it's wired up it will only do it if you're in development (note: You'll need to make sure the environment variable is set correctly so IsDevelopment
works).
AddRolesClaimsTransformation.cs
/// <summary>
/// Adds roles to a user on the fly, this will hard code a Buyer role for everyone.
/// </summary>
public class AddRolesClaimsTransformation : IClaimsTransformation
{
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
// Clone current identity
var clone = principal.Clone();
var ident = (ClaimsIdentity)clone.Identity;
ident.AddClaim(new Claim(ClaimTypes.Role, "Buyer"));
return clone;
}
}
Startup.cs
// Only in dev
if (builder.Environment.IsDevelopment())
{
builder.Services.AddScoped<IClaimsTransformation, AddRolesClaimsTransformation>();
}
This should work for ASP.NET Core 3.1 according to the Microsoft docs. I tested it against .NET 6 however (in .NET 6 the templates for new sites move the Startup.cs
stuff into Program.cs
).
One other side note, if you rely on the IsDevelopment
plumbing that's on the WebHostEnvironment
you won't have to use the compiler directives. That way once the environment is setup it will just work however you deploy it there (e.g. there isn't a chance an accidental Debug build will make it into an environment it's not supposed to be in).
CodePudding user response:
Rather than explicitly specifying the roles each controller requires with [Authorize(Roles...
, you can use [Authorize(Policy...
to add a layer of indirection.
That way you can decide in your StartUp
class (or in a IConfigureOptions<AuthorizationOptions>
service), exactly what each policy means. Including any other weird requirements you might have.
[Authorize(Policy= "Buyer")]
public class ProductController : ApiBaseController
...
services.AddAuthorization(o =>
{
o.AddPolicy("Buyer", b => {
#if DEBUG
b.RequireAuthenticatedUser();
#else
b.RequireRole("Buyer");
#endif
});
});