Okay, I'm obviously missing something, as this should be pretty simple. I've created the following attribute:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class EntitleAttribute : Attribute
{
public EntitleAttribute(string permissionName)
{
bool hasPermission = ...
if (!hasPermission)
{
throw new HttpException(403, "Forbidden");
}
}
}
I put it on a method:
[Entitle("Access Application")]
public ActionResult MyMethod(...) { ... }
However, it never gets called. What am I missing?
Attributes don't do anything by themselves. There needs to be some code that would look for the attribute and do something with it.
Based on code sample you want to perform some per-authentication in ASP.Net MVC application. In this case you should derive your attribute from MVC's AuthorizeAttribute. If you need more general handling in MVC site - base FilterAttribute or even IMvcFilter provide more options.
Related
Is there a way to require a specific Authorization Scheme when using the [Authorize] Attribute on a Controller in asp.net MVC 4?
I expected something like this (which is totally possible in .net core btw)
[Authorize(AuthenticationSchemes = "Bearer")]
public class MyController : Controller { }
As far as I know, there is nothing out of the box that would allow you to write this.
The standard authorize attribute doesn't support this.
But you could write your own attribute and check the claims of the identity coming in.
I used an backport of ASP.NET Core authorization policies to .NET Full framework: https://github.com/DavidParks8/Owin-Authorization to write such rules.
How to check of you come from which token?
Normally you will see a claim similar to "idp": "oidc"
How to get the claims? ((ClaimsPrinciple)User).Claims ( in Controller code)
As suggested by #Chetan Ranpariya in the comments I ended up implementing a derived attribute (from AuthorizeAttribute). According to the documentation, overriding the AuthroizeCore method is the way to do it.
When overridden, provides an entry point for custom authorization checks.
Here is a working example for future reference
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public string AuthSchemes { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (this.AuthSchemes != null)
{
string scheme = httpContext?.User?.Identity?.AuthenticationType;
if (string.IsNullOrWhiteSpace(scheme))
{
return false;
}
return this.AuthSchemes.Split(',').Contains(scheme);
}
return base.AuthorizeCore(httpContext);
}
}
The attribute can be used like this
[MyAuthorize(AuthSchemes = CookieAuthenticationDefaults.AuthenticationType)]
public class MyController : Controller { }
For some experimental/exercise purposes, I'm trying to implement a primitive login system before proceeding to Identity services.
My idea was creating a custom data annotation -just like [Authorize] of Identity- and passing inputted form data carried by Session[]. Hence, I would use my custom annotation to authorize certain controllers or methods.
public class IdCheck: ValidationAttribute
{
public string currentId { get; set; }
public override bool IsValid(object value)
{
currentId = value as string;
if (currentId != null)
{
return true;
}
else
{
return false;
}
}
}
and I tried to use it like that:
[IdCheck(currentId = Session["UserId"])]
public class SomeController : Controller
{
//methods
}
However, I got an error with the message: "An object reference is required for the non static field, method or property 'Controller.Session'"
I can neither access the Session[] before a controller nor before method declaration. I have no idea how to instantiate or refere.
Is there a way to utilize Session[] in my case? Because I don't want to manually check each method with if statements like
if(Session["UserId"] != null) {}
Any alternative solution is more than welcomed.
Note: I am aware of that using Session is not a recommended way of implementing such a task. But my intention is to have an understanding of how login operations work before utilizing advanced Identity services.
Is there a way to utilize Session[] in my case?
Not as you're doing now, but you could use HttpContext.Current.Session inside your custom attribute code instead of passing it as property.
Thanks a lot Oscar. What you proposed actually worked. However, I managed to find a better way yo carry out my "primitive login" operation using a custom data annotation.
After some more research it turned out that implementing FilterAttribute class along with IAuthorizationFilter filter does the trick. I believe this could help someone else as well:
public class IdCheck : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Session["UserId"] == null)
{
filterContext.Result = new RedirectResult("/");
}
}
}
and the usage is the same of course:
[IdCheck]
public class SomeController : Controller
{
//methods
}
I have a database with users, the users can have different roles.
I want to implement basic authentication for my MVC Web API and I want to be able to tag methods with an Authorize tag and also pass userType as a parameter.
[Authorize(admin)]
public bool Test()
{
}
[Authorize(user)]
public bool Test1()
{
}
I can't figure out how to make this attribute, for example how do I make an attribute that simply makes a method always return false?
[AttributeUsage(AttributeTargets.All)]
public class TestAttribute: System.Attribute
{
//Return false?
}
I'm looking for some advice.
EDIT:
I made the following class:
ilterContext.HttpContext.Response.StatusCode = 401;
filterContext.Result = new EmptyResult();
filterContext.HttpContext.Response.End();
}
}
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
then i add [BasicAuthorize] to a method, but it still let me access it without basic autentication.
any idea?
I suggest you read some basics about authorization and authentication and how the Authorize attribute can be applied.
Roles are out of the box. Just use the built-in capabilities of the Authorize attribute: Example:
[Authorize(Roles="admin")]
public bool Test()
{
}
If you need a custom implementation you need to inherit from System.Web.Mvc.AuthorizeAttribute instead of from System.Attribute. Everything else is pretty straight forward from here. Basic example explained here: Basic Authorization Attribute in ASP.NET MVC
I'm having some problem with my custom AuthorizeAttribute
public class ExplicitAuthorizeAttribute : AuthorizeAttribute
{
private readonly MembershipUserRole[] _acceptedRoles;
public ExplicitAuthorizeAttribute()
{
}
public ExplicitAuthorizeAttribute(params MembershipUserRole[] acceptedRoles)
{
_acceptedRoles = acceptedRoles;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Validation ...
}
}
I use it like this:
[ExplicitAuthorize[(MembershipUserRole.Admin, MembershipUserRole.SuperAdmin)]
It works perfectly for HttpGet and HttpPost to validate my controllers and methods.
But when I use it in a ApiController and make ajax calls, AuthorizeCore isn't running and I got a security breach. :/
My enum looks like this
[Flags]
public enum MembershipUserRole
{
Admin= 1,
SuperAdmin = 2
}
Does anyone know why my AuthorizeCore isn't validating in this context?
By the way If I use
[Authorized(Roles ="Admin, SuperAdmin")]
It's validates perfectly, but I'd like to have Stronly Typed Roles,that's why I'm using enums.
You have derived from the wrong class: System.Web.Mvc.AuthorizeAttribute whereas for a Web API controller you should derive from System.Web.Http.AuthorizeAttribute.
Don't forget that ASP.NET MVC and ASP.NET Web API are 2 completely different frameworks and even if they share some common principles and names, the corresponding classes are located in 2 completely different namespaces.
So what you have done is decorate an ASP.NET Web API action with an AuthorizeAttribute that it doesn't know anything about.
If you want to make authorization in ASP.NET Web API make sure you have derived from the correct attribute:
public class ExplicitAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
private readonly MembershipUserRole[] _acceptedRoles;
public ExplicitAuthorizeAttribute()
{
}
public ExplicitAuthorizeAttribute(params MembershipUserRole[] acceptedRoles)
{
_acceptedRoles = acceptedRoles;
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//Validation ...
}
}
In my filterConfig, I have registered a global attribute filter, which requires authorization on each of my methods.
However, I have one particular method where I want to apply a different authorization filter attribute. How does one accomplish this, if at all possible?
Note: I do not want to use the [AllowAnonymous] attribute (which works seamlessly and completely ignores my filter), since I want the request to be authorized, just through a different set of authorization logic on the method.
You can alter your filter to allow multiple by setting AllowMultiple = true in the AttributeUsage attribute on your attribute class, and add a check so that if the filter is present multiple times, the globally-applied one doesn't execute. The ActionExecutingContext that gets passed into OnActionExecuting() lets you get the filters applied via filterContext.ActionDescriptor.GetCustomAttributes(), so you can use that here.
Then, alter the constructor so that you can pass in a parameter (probably an enum) that it can use to decide which authorisation method to use - the normal one, or this other one. Give that parameter a default value that makes it select the normal auth method. Then, on that one method that needs a different auth method, you can apply the filter with the other value of the parameter. So it might look like this:
public class CustomAuthAttribute : AuthorizeAttribute
{
public CustomAuthAttribute(AuthMethod method = AuthMethod.StandardAuth)
{
//stuff
}
}
[CustomAuth(AuthMethod.WeirdAuth)]
public ActionResult MethodThatNeedsDifferentAuth()
{
//stuff
}
you can write your own version of the authorize attribute and pass specific parameter to depending on what action would you like your attribute to do for example
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public string currentAction { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (currentAction != "notallowed")
{
HandleUnauthorizedRequest(filterContext);
}
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
context.Result = new RedirectResult("/home/login");
}
and then apply it to your class or action
[CustomAuthorize(currentAction = "notallowed")]
public class HomeController : Controller