Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

ExternalLoginCallback action in asp.net core

Suggested Videos
Part 104 - External identity providers in asp.net core | Text | Slides
Part 105 - Create google oauth credentials - Client Id and Client Secret | Text | Slides
Part 106 - ASP.NET Core google authentication - Setting up the UI | Text | Slides

In this video, we will discuss how to handle login information received from the external login provider such as Google for example. This is continuation to our previous video. Please watch Part 106 from ASP.NET core tutorial before proceeding.


We will be redirected to Google sign-in page, if we click on the Google button on the Login view.

ExternalLoginCallback action in asp.net core


The following is the ExternalLogin action in AccountController that redirects the user to the external login provider sign-in page, in this case Google. We discussed this in detail in our previous video.

[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl)
{
    var redirectUrl = Url.Action("ExternalLoginCallback", "Account",
        new { ReturnUrl = returnUrl });
    var properties = signInManager
        .ConfigureExternalAuthenticationProperties(provider, redirectUrl);
    return new ChallengeResult(provider, properties);
}

Upon successful authentication, Google redirects the user back to our application and the following ExternalLoginCallback action is executed.

[AllowAnonymous]
public async Task<IActionResult>
            ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    LoginViewModel loginViewModel = new LoginViewModel
    {
        ReturnUrl = returnUrl,
        ExternalLogins =
                (await signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
    };

    if (remoteError != null)
    {
        ModelState
            .AddModelError(string.Empty, $"Error from external provider: {remoteError}");

        return View("Login", loginViewModel);
    }

    // Get the login information about the user from the external login provider
    var info = await signInManager.GetExternalLoginInfoAsync();
    if (info == null)
    {
        ModelState
            .AddModelError(string.Empty, "Error loading external login information.");

        return View("Login", loginViewModel);
    }

    // If the user already has a login (i.e if there is a record in AspNetUserLogins
    // table) then sign-in the user with this external login provider
    var signInResult = await signInManager.ExternalLoginSignInAsync(info.LoginProvider,
        info.ProviderKey, isPersistent: false, bypassTwoFactor: true);

    if (signInResult.Succeeded)
    {
        return LocalRedirect(returnUrl);
    }
    // If there is no record in AspNetUserLogins table, the user may not have
    // a local account
    else
    {
        // Get the email claim value
        var email = info.Principal.FindFirstValue(ClaimTypes.Email);

        if (email != null)
        {
            // Create a new user without password if we do not have a user already
            var user = await userManager.FindByEmailAsync(email);

            if (user == null)
            {
                user = new ApplicationUser
                {
                    UserName = info.Principal.FindFirstValue(ClaimTypes.Email),
                    Email = info.Principal.FindFirstValue(ClaimTypes.Email)
                };

                await userManager.CreateAsync(user);
            }

            // Add a login (i.e insert a row for the user in AspNetUserLogins table)
            await userManager.AddLoginAsync(user, info);
            await signInManager.SignInAsync(user, isPersistent: false);

            return LocalRedirect(returnUrl);
        }

        // If we cannot find the user email we cannot continue
        ViewBag.ErrorTitle = $"Email claim not received from: {info.LoginProvider}";
        ViewBag.ErrorMessage = "Please contact support on Pragim@PragimTech.com";

        return View("Error");
    }
}

asp.net core tutorial for beginners

6 comments:

  1. The admin user with delete claims Role policy can not delete the external user (gmail user account) from the application (aspnetUsers table) as it delete the local users accounts
    please solve it...

    ReplyDelete
  2. I am confused with ApplicationUser Class, can you pleas give a details about how to create it?

    ReplyDelete
    Replies
    1. Create normal class and name ApplicationUser
      Inherit the IdenityUserC class so that we can have the all properties of Identity user.
      create new properties such as PhoneNumber2 can be used as Office number, city , gender country
      Just use ApplicationUser reference where ever you used identiyuser

      Delete
  3. Enable to log out from external authentication it seems when ever click on the google external authentication button i am loged in with previous google account not redirecting me to login credential page of google

    ReplyDelete
  4. Then you need to go and log out from your google account on that device first

    ReplyDelete
  5. hello sir
    while executing the method:
    [AllowAnonymous]
    public async Task
    ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
    --
    --
    }

    I'm getting the following error:
    An unhandled exception occurred while processing the request.
    ArgumentNullException: Value cannot be null. (Parameter 'value')
    System.Security.Claims.Claim..ctor(string type, string value, string valueType, string issuer, string originalIssuer, ClaimsIdentity subject, string propertyKey, string propertyValue)

    Stack Query Cookies Headers Routing
    ArgumentNullException: Value cannot be null. (Parameter 'value')
    System.Security.Claims.Claim..ctor(string type, string value, string valueType, string issuer, string originalIssuer, ClaimsIdentity subject, string propertyKey, string propertyValue)
    System.Security.Claims.Claim..ctor(string type, string value)
    Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory.GenerateClaimsAsync(TUser user)
    Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory.GenerateClaimsAsync(TUser user)
    Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory.CreateAsync(TUser user)
    Microsoft.AspNetCore.Identity.SignInManager.CreateUserPrincipalAsync(TUser user)
    Microsoft.AspNetCore.Identity.SignInManager.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable additionalClaims)
    EmployeeManagement.Controllers.AccountController.ExternalLoginCallback(string returnUrl, string remoteError) in AccountController.cs
    +
    await signInManager.SignInAsync(user, isPersistent: false);
    Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
    System.Threading.Tasks.ValueTask.get_Result()
    System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()

    please guide
    I'm following all your videos from begining

    ReplyDelete

It would be great if you can help share these free resources