Question

There are a lot of similar questions out there but this has me stumped.

If I used [Authorize] I get prompted for a username and password but if I use [InternalAuthorizeV2] I don't

I have a custom AuthorizeAttribute that for the moment does not do any anything special (I'm limiting things that could be wrong).

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class InternalAuthorizeV2Attribute: AuthorizeAttribute
    {}

and a Action in my Controller

   [InternalAuthorizeV2(Roles = "MobileApps_Parkingggg")]
         public ActionResult Index()
         {
             var model = new VmParking();
             return View(model);
         }

The login is handled in a different app but they have identical web config lines

   <machineKey compatibilityMode="Framework20SP2" validationKey="editedOut" decryptionKey="editedOut" validation="SHA1" decryption="AES"/>
      <authentication mode="Forms">
          <forms name="emLogin" loginUrl="/Login/Index" timeout="540" protection="All" path="/"  enableCrossAppRedirects="true"  cookieless="UseCookies" />
      </authentication>
    <sessionState timeout="540" />

I know that if I login by going to a page with [Authorize] then back to my trouble page I can see the username but it doesn't seem to be calling my customer attribute.

New information: My attribute is in a shared DLL as it's used by many apps. It seems that if I copy the cs file to the web project it works. No idea why, still looking for hints or tips.

Was it helpful?

Solution

From what you've said, it all behaves fine if you use [Authorize] but not [InternalAuthorizeV2].

Your shared dll shouldn't make any difference if it is set up correctly; I have the same thing working. Make sure the web project is using the latest version of the dll and you have the right assembly references in the shared dll - System.Web.Mvc, v4.0.0.0 in my project.

You say its used by many apps? Do all apps have the same problem with the shared dll or just one of them? If it's just one, check the references for the one with the problem.

If the below tests all work then the final option is that whatever you are doing in your authorize attribute in the dll isn't picking up the right context for that app, or using the right membership provider or database - you haven't included the code you are using inside your attribute so it's hard to know if that could be causing a problem.

Test dependencies

You could try adding a base authorize attribute to your shared dll, and then implementing another authorize attribute in your web project that inherits the base attribute you just created. This should show that you have your shared dll set up correctly.

// in the dll:
public class BaseAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute { ... }

// in the web project:
public class InternalAuthorizeV2Attribute : BaseAuthorizeAttribute { ... }

If simply moving it from your dll project to the web project fixes it, the most likely issue is the web project is not using the right version of the dll (try cleaning and doing a complete rebuild) or your dll is referencing the wrong dlls for the System.Web.Mvc.AuthorizeAttribute. You say you have triple checked, but trying the above debugging should help you work out if this really is the case.

Debug authorization method calls

If that doesn't work then try adding the following override methods to a very simple attribute, and seeing if you hit the breakpoint on the call to base.OnAuthorization. If you don't, then it may not be the actual attributes causing your problem.

[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Method, 
  Inherited = true, AllowMultiple = true)]
public class InternalAuthorizeV2Attribute : System.Web.Mvc.AuthorizeAttribute {
  protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) {
    return false; // breakpoint here, and this should force an authorization failure
  }
  public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
  {
    base.OnAuthorization(filterContext); // breakpoint here
  }
}

This should completely prevent any user access to the Action. If that doesn't work then you know the issue doesn't lie in your attribute, but that your attribute is not being applied.

You can also add the following to your controller and check that it is hit before the authorize attribute:

protected override void OnAuthorization(AuthorizationContext filterContext) {
    base.OnAuthorization(filterContext);
}

Authorization chaining

Note that you have your attribute attached to the Action method, so it will only be hit if a an authorization attribute earlier in the chain (e.g. a global filter or controller attribute) hasn't already prevented the user being authorized (see my answer here), or prematurely returns an ActionResult that stops the chain reaching your Action attribute. However it's unlikely this is the problem if simply moving it from the dll to the project makes it work. Similarly it's unlikely you have an AllowAnonymous in the wrong place from what you've said.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top