Authorize one action in a controller but don't require a role

BYoung picture BYoung · Jul 10, 2013 · Viewed 7k times · Source

I have a Product controller the required role of "product_editor" to access most of the methods. there are a few actions that don't require authorization so [AllowAnonymous] works great. However, I have one action i would like to require they are logged in but they may not be a product editor.

Is there a simple way to declare this for the one action?

you can see a couple of my attempts commented out

[Authorize(Roles = "product_editor")]
public class ProductController : Controller
{
    #region Public Actions
    [AllowAnonymous]
    public ActionResult Search(string keyword...

    [AllowAnonymous]
    public ActionResult Details(string id...
    #endregion

    //[Authorize]
    //[Authorize(Roles="")]
    public ActionResult AuthorizedDownload(long id, string step)
    {
        SecureDownloadLink link = SecureDownloadLink.Load(id);
        if(link.belongsTo(HttpContext.Current.User.Identity.Name))
        {
            //Allow download
        }
        else
        {
            //Return 404 Error
        }
    }
}

--Edit--

Found a working solution but would love an attribute based solution since the rest of my authentication is done in attributes and the [AllowAnonymous] is a bit misleading.

[AllowAnonymous]
public ActionResult AuthorizedDownload(long id, string step)
{
    if (!User.Identity.IsAuthenticated)
        return RedirectToAction("Login", "Account", new { ReturnUrl = Request.Url.LocalPath });
....
}

Answer

Darin Dimitrov picture Darin Dimitrov · Jul 10, 2013

I don't think there's a simple way to achieve that, other than explicitly specifying the Authorize attribute explicitly on each controller action:

public class ProductController : Controller
{
    #region Public Actions
    [AllowAnonymous]
    public ActionResult Search(string keyword...

    [AllowAnonymous]
    public ActionResult Details(string id...
    #endregion

    [Authorize]
    public ActionResult AuthorizedDownload(long id, string step)
    {
        SecureDownloadLink link = SecureDownloadLink.Load(id);
        if(link.belongsTo(HttpContext.Current.User.Identity.Name))
        {
            //Allow download
        }
        else
        {
            //Return 404 Error
        }
    }

    [Authorize(Roles = "product_editor")]
    public ActionResult SomeOtherAction()
    {
        ...
    }
}

or if you have many actions, another possibility is to move the action that differs in a separate controller.