Search code examples
c#asp.nethttp-redirectasp.net-mvc-5asp.net-identity-2

Asp.net Identity 2.0 - redirect externally authenticated user based on role at login


I'm trying to redirect users upon login to different pages, depending on their role.

Users with a local Identity account are redirected properly in the Login method, by using User.IsInRole("RoleName").

However, when I try to conditionally redirect users who are using external validation, it fails to find the role, because the User is not set until after the redirect:

        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        // Sign in the user with this external login provider if the user already has a login
        var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);

                if(User.IsInRole("Administrator")) 
//always evaluates to false because User is null
                {
                    returnUrl = "~/admin";
                } else
                {
                    returnUrl = "~/dashboard";
                }
        switch (result)
        {
            case SignInStatus.Success:
                return RedirectToLocal(returnUrl);
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
            case SignInStatus.Failure:
            default:
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
        }
    }

It seems the User isn't completely logged in until after the RedirectToLocal() call triggers.

How can I check the external login user's roles before redirecting?


Solution

  • You are right, at least one new call is needed to apply user authentication. But if you don't want to redirect you could write something like this:

    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }
        var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
    
        if(result==SignInStatus.Success)
        {
            var user=UserManager.Find(loginInfo.Login);
            returnUrl =UserManager.IsInRole(user.Id, "Administrator")
                ? "~/admin"
                : "~/dashboard";
    
        }
        // rest of code
    }