How to Login With Google in ASP.NET Core Identity

In this article, we will learn how to login with google in ASP.NET Core Identity

There are Two main steps to do when creating Google login feature.

  1. Create a new Project in Google Console.
  2. Use Google APIs to communicate with your Project located in Google Console.

Create a new Project in Google Console

First login  Google Console,

Then create a new Project in Google Console, which you can do from this URL. Give your project a name like Google Log In and click CREATE button, this is shown in the below image:

Create Google App

Now your project will be created, and you will be taken to the Project Dashboard page. In this page, on the top left corner, you will find the navigation menu. Click this menu and select APIs & Services ➤ Credentials. Check the below image for understanding:

Credentials

You will now reach Credentials Page where you will be asked to create your credentials. So, click the Create Credentials button, and then on the options that open up, click the OAuth client ID like shown in the image below:

Create Credentials

Application Name

Authorized redirect URIs contains the URL of your application to which Google will redirect users after they are authenticated.

The URL – /signin-google, is the default URL set by ASP.NET Core Identity for Google OAuth.

Authorize URL

On clicking the Create button, you will now get your Client Id and Secret displayed in a window.

oauth client id secret

Now Create ASP.NET Core Identity  Project

First you need to install the package called Microsoft.AspNetCore.Authentication.Google from NuGet.

Next, go to your Startup.cs file, and inside it’s ConfigureServices() method, set up the Google Authentication Service and provide the OAuth credentials you got from the Google Project before.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
    services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();
 
    services.AddAuthentication()
        .AddGoogle(opts =>
        {
            opts.ClientId = "Your Client Id";
            opts.ClientSecret = "Your Client Secret";
            opts.SignInScheme = IdentityConstants.ExternalScheme;
        });
 
    services.AddControllersWithViews();
}

Now go to the CustomUsernameEmailPolicy class and disable this thing as shown below:

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
 
namespace Identity.IdentityPolicy
{
    public class CustomUsernameEmailPolicy : UserValidator<AppUser>
    {
        public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
        {
            IdentityResult result = await base.ValidateAsync(manager, user);
            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
 
            if (user.UserName == "google")
            {
                errors.Add(new IdentityError
                {
                    Description = "Google cannot be used as a user name"
                });
            }
 
            return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
        }
    }
}

View Page

@model Login
 
<h1 class="bg-info text-white">Login</h1>
<div class="text-danger" asp-validation-summary="All"></div>
 
<form asp-action="Login" method="post">
    <input type="hidden" asp-for="ReturnUrl" />
    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Password"></label>
        <input asp-for="Password" class="form-control" />
    </div>
    <button class="btn btn-primary" type="submit">Log In</button>
    <a class="btn btn-info" asp-action="GoogleLogin">Log In With Google</a>
</form>

The new link targets the GoogleLogin action on the Account controller. You can see this action along with the changes I made to the Account controller (code is given below). Basically I added 2 method which are GoogleLogin & GoogleResponse.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Identity.Models;
using System.Threading.Tasks;
using System.Security.Claims;
 
namespace Identity.Controllers
{
    public class AccountController : Controller
    {
        private UserManager<AppUser> userManager;
        private SignInManager<AppUser> signInManager;
 
        public AccountController(UserManager<AppUser> userMgr, SignInManager<AppUser> signinMgr)
        {
            userManager = userMgr;
            signInManager = signinMgr;
        }
 
        // other methods
 
        public IActionResult AccessDenied()
        {
            return View();
        }
 
        [AllowAnonymous]
        public IActionResult GoogleLogin()
        {
            string redirectUrl = Url.Action("GoogleResponse", "Account");
            var properties = signInManager.ConfigureExternalAuthenticationProperties("Google", redirectUrl);
            return new ChallengeResult("Google", properties);
        }
 
        [AllowAnonymous]
        public async Task<IActionResult> GoogleResponse()
        {
            ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync();
            if (info == null)
                return RedirectToAction(nameof(Login));
 
            var result = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
            string[] userInfo = { info.Principal.FindFirst(ClaimTypes.Name).Value, info.Principal.FindFirst(ClaimTypes.Email).Value };
            if (result.Succeeded)
                return View(userInfo);
            else
            {
                AppUser user = new AppUser
                {
                    Email = info.Principal.FindFirst(ClaimTypes.Email).Value,
                    UserName = info.Principal.FindFirst(ClaimTypes.Email).Value
                };
 
                IdentityResult identResult = await userManager.CreateAsync(user);
                if (identResult.Succeeded)
                {
                    identResult = await userManager.AddLoginAsync(user, info);
                    if (identResult.Succeeded)
                    {
                        await signInManager.SignInAsync(user, false);
                        return View(userInfo);
                    }
                }
                return AccessDenied();
            }
        }
    }
}

Login Page

Sign Up Page

Submit a Comment

Your email address will not be published.

Subscribe

Select Categories