ASP.NET has the [Allow Anonymous] attribute which allows you to bypass authorization on a specific endpoint. I'm wondering if there's a common way of enabling specific authentication schemes on an endpoint by endpoint basis.
Imagine you wanted to support different schemes like a Basic scheme and a Bearer scheme and so on. But you didn't want to support all schemes on all endpoints. It seems like a convenient way to do that would be to create attributes like [BasicAuth] and [BearerAuth] so you could just annotate the specific endpoints you want to enable. Looking at how AuhtorizationAttributes work, however, it seems like they behave like a logical AND rather than a logical OR.
For example, if I annotated an endpoint with both [BasicAuth] and [BearerAuth] and one returns False on IsAuthorized the whole thing would fail. This makes me think I'm either looking in the wrong place or have an uncommon use-case.
Am I looking in the wrong direction?
AuthorizationAttribute supports different kind of authorizations. It can be used to support Policies or Roles. If you want an OR kind of logic you can use the authorization attribute with a comma separated string for roles. That will let your endpoint accessible by those roles.
Use it like this for OR logic:
[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
}
For AND logic
[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
}
Source is Role-based authorization
I would recommend reading through the whole Authorization documentation.
Related
I am currently working on a .NET Core API using roles-based authorization.
In some of the endpoints, it is necessary to implement custom logic based on the users role. Rather than creating separate routes for different roles, I would prefer an implementation where the frontend can use the same endpoint regardless of the current users role.
Ex. to update a users information:
A admin should be able to update any users information, and any other role should be limited to only changing their own user data only.
[Authorize(Roles = "Admin")]
[HttpPut]
public UserDto UpdateUserAdmin(Input input)
//Can update any user based on Id from input.
[Authorize] //Match any role other than admin
[HttpPut]
public UserDto UpdateUserDefault(Input input)
//Can update logged in user only. Id from token.
My initial thought was that this routing would be solved using the Authorize attribute, but as far as I can tell, this attribute cannot be used to resolve ambigious matches on the same route?
While looking for a solution, I came across action constraints.
However, I ran into some problems where the claims from the token were not yet set as I ran my constraint. (Might be a problem in the order of my middleware?)
Anyway! Is Action Constraints the way to go for these kind of issues?
Or is there another solution for this in .NET Core?
I want to provide additional query string parameter authentication for some actions in some controllers. I want it to bypass [Authorize] but to use it if this custom query string authentication fails.
I've tried using IAuthorizationFilter with IOrderedFilter with Order = 0 but it seems in .net 3.1+ it's not working anymore.
Basically I want my filter to check for query string key, if this authentication fails it would pass the workflow to [Authorize] filter.
BUT if my custom Authentication filter would succeed - it should disable [Authorize] and go right to the action.
The best option I discovered is to use Policies. In Policy I can check my custom authentication and if it does not work check if (context.User.Identity.IsAuthenticated) for default auth.
For your information. Custom filters did not work. IOverrideAuthorizationFilter is NOT part of asp.net core 3.1+, so don't go there.
Custom middleware does not give you opportunity to override authentication filters.
Best option is to use Policy. On this matter official Microsoft documentation does explanation well.
I am trying to understand the ASP.NET policy-based authorization mechanism, and I understood that I need to do the following:
Set up a policy
Assign requirements to that policy
Define authorization handlers to these requirements which perform the actual validation (And return whether the requirements were fullfilled or not)
Add the authorization handlers to the dependency injection mechanism
However, reading the ASP.NET documentation, I understand I might need to set up an IAuthorizationService as well. I failed to understand why that is needed for from the ASP.NET documentation.
Do I have to set one up? What should it do? Is that an alternative to the policy and authorization handlers I am setting up or a required addition to them?
U can override IAuthorizationService to take control of full authorization logic in your application.
By default, IAuthorizationService is responsible for validation of Policy- Claim- or Role-based ruled, defined in AuthorizationOptions.
IAuthorizationService is usually being invoked in IAsyncAuthorizationFilter (which MVC adds automatically once u mark Controller or Action with [Authorize] attribute).
Here is my situation:
I have an API and I'm securing it with SSO. What I want is that based in the JWT issuer, I apply one attribute or another, so is it possible to put both authorization attributes to my controller and execute the request if at least one authorization attribute decides that the token is valid and I have a desired claim inside?
I don't want to put all this login inside one attribute, due to SRP.
Thanks
The MSDN is pretty clear about MVC Routing and Security:
The only supported way to secure an MVC application is to apply the AuthorizeAttribute attribute to each controller and use the AllowAnonymousAttribute attribute on the login and register actions.
However, I am considering the following approach:
First, I have implemented a custom Controller Factory that performs security checks based on information coming from our custom STS.
Among other information, the token issued by the STS contains claims describing all the MVC routes the user is allowed to access.
Then I check the user claims within the CreateController method:
public class SecuredControllerFactory : IControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
...
bool isAuthorized = principal.HasRequiredRight(verb, ressource);
...
}
}
This way we can configure and update security rules in a centralized manner, without redeploying our applications. Moreover, it fits the "convention over configuration" idea.
Is there something wrong with this approach? I don't see why it is considered a bad practice? Can someone exhibit a concrete security issue with this?
I guess it is bad practise because it breaks the Single Responsibility principle within the controller factory. The single responsibility of the controller factory should be to select and instantiate controllers.
I would question your reason for going with the controller factory approach:
This way we can configure and update security rules in a centralized
manner, without redeploying our applications.
This is a valid statement if you use the standard AuthorizeAttribute that specifies the allowed users/roles in code.
However, the recommended approach would be to derive from AuthorizeAttribute and implement your security rule logic in the derived class by overriding the protected AuthorizeCore() method. For example, it could look up permissions in a database so you could change them dynamically at runtime.
This also allows you to implement custom logic that gets called when the authorization check fails (HandleUnauthorizedrequest() method), which is presumably what you have to do in your custom controller factory when the authorization logic fails (e.g. redirect to a sign-on or error page?)
That way, you get the ability to change your security rules and manage them centrally without redeploying the whole application and you don't break the single responsibility of the ControllerFactory
ThinkTexture provide a good implementation in their identity model framework, as described here
http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/
This allows you to specify a Resource/Action and to encapsulate the authorization logic in a custom ClaimsAuthorizationManager in the usual WIF way. If you don't specify the resource and action explicitly in the attribute, the framework gets the values from the using the current HttpActionContext, which is nice.