Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect Login to Controller Action

Starting with the ASP.NET 5 Web App Template using Individual User Accounts I have managed to get external authentication working with Microsoft accounts. When users click Login they are redirected to ExternalLogin in AccountController like this

<form asp-controller="Account" asp-action="ExternalLogin" method="post" asp-route-returnurl="@ViewData["ReturnUrl"]" class="nav navbar-right">
    <button type="submit" class="btn btn-null nav navbar-nav navbar-right" name="provider" value="Microsoft" title="Log in"><span class="fa fa-sign-in"/>&nbsp; Log In</button>
</form>

That gets them logged in using thier Microsoft account and all seems to work nicely. But how do I intercept direct attempts to access privileged actions [Authorize] so that the user is redirected to ExternalLogin? Can a default action be set in Startup.cs?

EDIT 1 Attempting to follow the advice of @Yves I have created CustomAutorizationFilter in a Filters folder. It doesn't check for any conditions

public class CustomAutorizationFilter : IAuthorizationFilter
{
    public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
    {
        //if (...) // Check you conditions here
        //{
            context.Result = new RedirectToActionResult("ExternalLogin", "Account", null);
        //}
    }
}

and have edited ConfigureServices as below

        services.AddMvc(config =>
        {
            config.Filters.Add(typeof(Filters.CustomAutorizationFilter));
        });

When I run the app locally it no longer goes to the Home page. It returns a blank http://localhost:52711/Account/ExternalLogin

Obviously there is much I do not understand.

Edit 2: Here is the signature of ExternalLogin

 // POST: /Account/ExternalLogin
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public IActionResult ExternalLogin(string provider, string returnUrl = null)

This is how ExternalLogin comes out of the box in the ASP.Net 5 Web App Template.

like image 253
Vague Avatar asked Jan 23 '16 21:01

Vague


2 Answers

You can register an IAuthorizationFilter or an IActionFilter implementations to accomplish this. In these filters you can check if the request is trying to access a privileged action, if the user is logged in or have enough permission to do it.

If you are using AutorizeAttribute, I suggest you to use AutorizationFilter. If you go with your own custom attributes, then use ActionFilter.

Here is an example:

MVC calls IAuthorizationFilter.OnAuthorization method before every action execution.

public class CustomAuthorizationFilter : IAuthorizationFilter
{
    public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
    {
        if (...) // Check you conditions here
        {
            context.Result = new RedirectToActionResult("ExternalLogin", "Account", null);
        }
    }
}

To register this filter, in Startup.cs edit your ConfigureServices method:

services.AddMvc(config =>
{
    config.Filters.Add(typeof(CustomAuthorizationFilter ));
});

Or if you wan to use your own attributes you can use ActionFilter's OnActionExecuting method to check if everything is happening as you wish...

like image 73
Yves Avatar answered Nov 15 '22 20:11

Yves


As I was unable to get CustomAuthorizationFilter working as suggested by @Yves I have resorted to a nasty hack. I have modified AccountController Login as below

     // GET: /Account/Login
    [HttpGet]
    [AllowAnonymous]
    public IActionResult Login(string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        return RedirectToAction(nameof(ExternalLogin), new { provider = "Microsoft", returnUrl = returnUrl });
        //return View();
    }

This seems to work but I'd appreciate any feedback or advice if there is a better way.

like image 39
Vague Avatar answered Nov 15 '22 20:11

Vague