1

I have a table of clubs, when a new one is created a new role is created Club(the id of the club)Admin.

I want to be able to reference this role in the authorisation attribute of the method.

Heres what Ive tried on the controller method:

        [Authorize(Roles = "Club" + clubId + "Admin")]
    public ActionResult ClubDetails(int clubId)
    {
        var viewModel = db.Clubs
          .Where(t => t.ClubId == clubId)
          .Select(t => new ClubDetailsViewModel
          {
              ClubId = t.ClubId,
              Name = t.Name,
              ShortName = t.ShortName,
              Founded = t.Founded,
              ContactName = t.FirstName + " " + t.LastName,
              Address1 = t.Address1,
              Address2 = t.Address2,
              City = t.City,
              County = t.County,
              Postcode = t.Postcode,
              Telephone = t.Telephone,
              Email = t.Email,
              Website = t.Website,
              Bio = t.Bio,
              ClubTypeId = t.ClubTypeId,
              MembershipStatusId = t.MembershipStatusId,
              ChequesPayable = t.ChequesPayable,
              BACSAcc = t.BACSAcc,
              BACSSort = t.BACSSort,
              PaypalAdd = t.PaypalAddress,
          })
          .FirstOrDefault();
        return View(viewModel);
    }

But that gives an error on clubId in the authorise attribute. The name clubId does not exist in the current context

Is there a way I can reference the parameter that is passed to the method in the authorise attribute?

Phill Sanders
  • 487
  • 2
  • 10
  • 30
  • well, Authorize attribute execute in MVC pipline before Binding happends. You i gess, you should create your own Authorization filter. [This answer](http://stackoverflow.com/a/12828402/1849444) will help you i gess. – teo van kot Jul 12 '15 at 18:15

2 Answers2

3

No. You have to override the AuthorizeAttribute class to make your own custom attribute.

[AttributeUsageAttribute( AttributeTargets.Class | 
                          AttributeTargets.Method, 
                          Inherited = true, AllowMultiple = true )]
public class CustomAuthorizeAttribute : AuthorizeAttribute {

   public override bool AuthorizeCore( HttpContextBase context ) {

       // this is where you can inspect the principal in context.User
       // and check if he/she is in role

       // you can get the clubId from context.Request.Params

       var clubId = int.Parse( context.Request.Params["clubId"] );

       return context.User.IsInRole( string.Format( "Club{0}Admin", clubId ) );  
   }

}

and then

[CustomAuthorizeAttribute]
public ActionResult ClubDetails(int clubId)

You could even move the Club{0}Admin to the attribute's constructor as a parameter.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • Excellent thanks very much, is there a way to add a other roles to the attribute so several roles can be authorised? – Phill Sanders Jul 12 '15 at 19:15
  • Also where do I need to place the custom attribute definition? – Phill Sanders Jul 12 '15 at 19:23
  • Place the code where you want so that the class is accessible from the controller. This should be basic. Also, modify the core code as you want, pass additional parameters if necessary. My example is just to get you started. – Wiktor Zychla Jul 12 '15 at 19:46
  • I thought it would be, but Ive placed it in the controller where its available for my methods but it gives the following error: 'GRCWebApp.Controllers.ClubController.CustomAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase)': cannot change access modifiers when overriding 'protected' inherited member 'System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase)' – Phill Sanders Jul 12 '15 at 20:05
  • 1
    That is really a simple issue, change public to protected. – Wiktor Zychla Jul 12 '15 at 22:12
0

You cannot pass dynamic data to attributes. To solve your problem you can either inherit the Authorize attribute and check clubId inside AuthorizeCore method (you'll have to get clubId manually) or check access rights in the code of your action, i.e.

if(User.IsInRole("Club" + clubId + "Admin"))

You should probably consider splitting "Admin" role and clubId, so that all your clubadmins have the same role "Admin" and they all are bound to clubId (i.e. with a column in the database)

Andrey
  • 196
  • 1
  • 8
  • This still looks wrong. He apparently doesn't want to check if `clubId` is some fixed value, rather, he wants to verify if `clubId` that is bound to the method's parameter is the very same `clubId` that is in the role's name. – Wiktor Zychla Jul 12 '15 at 18:25