1

I would like to secure whole website so that every page except login page would require a user to be authenticated. In order to achieve this, I register Authorize filter at application startup:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new AuthorizeAttribute());
}

Now there is a problem with my LoginController, which despite applying [AllowAnonymous] attribute to it and still requires user to be authenticated. This is my login controller:

[AllowAnonymous]
public class LoginController : SurfaceController
{
    public LoginController()
    {
    }

    [HttpPost]
    [ValidateAntiForgeryToken]        
    [AllowAnonymous]
    public async Task<ActionResult> HandleLogin(LoginModel model, string returnTo)
    {
        return CurrentUmbracoPage();
    }
}

There are no other child actions on the page and the problem is definitively with the LoginController. What happens here and how it can be fixed?

UPDATE: my views are

Login page template:

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
    // Layout = "Master.cshtml";
    Layout = null;
}
    <div>@Umbraco.Field("bodyText")</div>
    @Html.Partial("Login")

Login Partial is:

@using ClientDependency.Core.Mvc
@using PlayProj.Presentation.Controllers
@using Umbraco.Web
@using Umbraco.Web.Models

@{
    var loginModel = new LoginModel();

    Html.EnableClientValidation();
    Html.EnableUnobtrusiveJavaScript();

    Html
        .RequiresJs("~/scripts/jquery.validate.hooks.js", 200)
        .RequiresJs("~/scripts/foundation.form.validation.js", 201);
}

@using (Html.BeginUmbracoForm<LoginController>("HandleLogin", null, new { @class = "loginForm", autocomplete = "off" }))
{
    <fieldset>
        <legend>Login</legend>

        <button>Login</button>
    </fieldset>
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
lekso
  • 1,731
  • 3
  • 24
  • 46
  • So far you are going down the right path but you are not showing enough information about `LoginController`. Maybe you missed something that we could help you with. Show the rest of that class. – Nkosi May 09 '16 at 11:34
  • Hi Nikosi, The controller doesn't have anything else really - only the HandleLogin action. However, the problem happens already at page load. The page goes into infinite redirection loop. I updated my OP so that it now contains the views – lekso May 09 '16 at 11:59
  • Is there a reason you aren't just using the standard Umbraco "Public Access" functionality? if you're authorising members this would be easier than trying to set this up in all your surface controllers globally. Also, are you trying to protect entire pages or just partials on a page? EDIT: The RenderMvcController would be a better choice perhaps. – Robert Foster May 09 '16 at 13:44
  • We authenticate users using a third party OAuth provider, so there are no members or roles setup in Umbraco. – lekso May 09 '16 at 14:15
  • Also, I just noticed that when I have a global Authorize filter, then I also cannot login to to umbraco because the Umbraco login page also required a user to be authenticated. So, it is a global problem rather that bug with LoginController. I wonder, whether this is the way Umbraco is supposed to work and there is a workaround or did I make a mistake? – lekso May 09 '16 at 14:23
  • take a look at UmbracoIdentity for OAuth with Umbraco... https://github.com/Shazwazza/UmbracoIdentity – Robert Foster May 09 '16 at 20:07

2 Answers2

0

Rather than registering a Global Filter, could you maybe swap out the default controller for one which has the Authorize attribute on. Then by default all pages which don't have a hijacked route will be routed through your new Authorized default controller. You can change the default controller in Umbraco during the ApplicationStarting event like so:

DefaultRenderMvcControllerResolver.Current.SetDefaultControllerType(typeof(YourDefaultController));
Tom
  • 179
  • 5
0

Instead of using global AuthorizeAttribute you can implement your own base controller and handle authorization there.

public class AuthorizedSurfaceController : SurfaceController
{
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        var authorized = false; //get this from your provider
        if(!authorized)
        {
            filterContext.Result = new RedirectResult("/login");
        }
    }
}
Davor Zlotrg
  • 6,020
  • 2
  • 33
  • 51
  • How should I make the new AuthorizedSurfaceController class activated? I have created this class but the method is not called when I open my home page. – meir Oct 17 '20 at 11:56