Mike
Mike

Reputation: 582

Authorization Attribute Dependent on Runtime Configuration

I have a .Net Core 3.0 Web API that is configured with as such:

services.AddAuthentication(x =>
  {
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  })
  .AddJwtBearer(x =>
  {
    ...
  });

services.AddAuthorizationCore(options =>
  {
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
      .RequireAuthenticatedUser()
      .Build();
  });

And I enable it in the controller like:

[Authorize(Roles = "Admin,Technician")]
public IActionResult CreateFoo([FromBody] Foo foo)

Some api endpoints are also disabled using the [AllowAnonymous].

This product is supporting multiple environments, and one endpoint needs to be either anonymous or authorized dependent on the runtime variable; currently using custom "ASPNETCORE_ENVIRONMENT" options.

I have seen this comment from .net security person, but if I implement a custom policy, it disallows anonymous access.

What is the easiest way to allow anonymous access if the application is running in a certain environment?

Upvotes: 0

Views: 1414

Answers (2)

Moe Jallaq
Moe Jallaq

Reputation: 104

If I understand your question then you could create a custom attribute and always grant the user access when the application is running in a certain env?

   public class CustomEnvRequirement : AuthorizationHandler<CustomEnvRequirement>, IAuthorizationRequirement
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomEnvRequirement requirement)
        {
            string currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

            // Allow Anonymous when the current env is development.
            if (currentEnv.ToLowerInvariant().Equals("development"))
            {
                context.Succeed(requirement);
            }
            else if (currentEnv.ToLowerInvariant().Equals("production"))
            {
                // TODO: add more authorization logic.

            }
            return Task.CompletedTask;
        }
    }

And here's the Custom attribute to be added

 [Authorize(Policy = "CustomEnv")]

        public IActionResult Index()
        {
            return this.View();
        }

Also, make sure to configure it in the startup.cs

  services.AddAuthorization(options =>
            {
                options.AddPolicy("CustomEnv",
                    policy => policy.Requirements.Add(new CustomEnvRequirement()));
            });

Upvotes: 1

fenixil
fenixil

Reputation: 2124

AuthorizeAttribute is just an implementation of AuthorizationFilterAttribute . You can create your own implementation that will bypass authentication for certain environments:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class EnvironmentSpecificAutorizeAttribute : AuthorizeAttribute
{
    public string AllowAnonymousEnvironment { get; set; }

    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        // if currentEnv == AllowAnonymousEnvironment 
        //    return 
        // else
        //    base.HandleUnauthorizedRequest(actionContext);
    }
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        // same logic as above
        base.OnAuthorization(actionContext);
    }

    public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        // same logic as above
        return base.OnAuthorizationAsync(actionContext, cancellationToken);
    }
}

You may find other suggestions in this thread

Upvotes: 0

Related Questions