Setting Up Google Authentication in ASP.NET Core MVC

Google Authentication in ASP.NET Core MVC applications provides a secure and easy way for users to log in using their Google accounts. This guide walks you through the entire process of integrating Google Authentication into your ASP.NET Core MVC application.

Step 1. Create a new ASP.NET Core MVC project

  1. Open Visual Studio: Launch Visual Studio from your computer.
  2. Create a new project: Click on Create a new project from the start page.
  3. Select Project Template: In the "Create a new project" dialog, select ASP.NET Core Web Application, then click Next.
  4. Configure Project: Provide a Project name and Location for your project, then click Create.
  5. Select Application Type: In the "Create a new ASP.NET Core web application" dialog, choose Web Application (Model-View-Controller) and ensure .NET 5.0 or later is selected. Click Create.

Step 2. Configure the Google API console

  1. Access Google API Console: Navigate to the Google API Console.
  2. Create a New Project: Click on the project dropdown and select New Project. Fill in the project details and click Create.
  3. Configure the OAuth Consent Screen
    • Go to the OAuth consent screen.
    • Select External as the user type and fill in the required fields (App name, User support email, etc.). Click Save and Continue.
  4. Create OAuth Credentials
    • Go to Credentials.
    • Click Create Credentials and select OAuth 2.0 Client IDs.
    • Choose Web application as the application type.
    • Set the Authorized redirect URIs to https://localhost:{PORT}/signin-google (replace {PORT} with your port number, typically 5001 for HTTPS).
    • Click Create and copy the Client ID and Client Secret for later use.

Step 3. Add Google authentication to your ASP.NET Core application

  • Install the Required NuGet Package
    • Open the Package Manager Console from Tools > NuGet Package Manager > Package Manager Console.
    • Run the following command to install the Google authentication package.
      Install-Package Microsoft.AspNetCore.Authentication.Google
      
  • Configure Startup. cs: Open Startup.cs and update the ConfigureServices and Configure methods.
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authentication.Google;
    using System.Security.Claims;
    using GoogleAuthInAspNetCoreMVC.Data;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using GoogleAuthInAspNetCoreMVC.Models;
    
    var builder = WebApplication.CreateBuilder(args);
    var connectionString = builder.Configuration.GetConnectionString("GoogleAuthInAspNetCoreMVCContextConnection") 
        ?? throw new InvalidOperationException("Connection string 'GoogleAuthInAspNetCoreMVCContextConnection' not found.");
    builder.Services.AddDbContext<GoogleAuthInAspNetCoreMVCContext>(options => 
        options.UseSqlServer(connectionString));
    // Add services to the container.
    builder.Services.AddRazorPages();
    // Manage User Secrets
    if (builder.Environment.IsDevelopment())
    {
        builder.Configuration.AddUserSecrets<Program>();
    }
    // Add Identity in IOC Container
    builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
                   options.SignIn.RequireConfirmedAccount = false    
                 )
                .AddEntityFrameworkStores<GoogleAuthInAspNetCoreMVCContext>()
                .AddDefaultTokenProviders();
    // Configure Google authentication
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
        options.CallbackPath = "/signin-google";
        options.Events.OnCreatingTicket = ctx =>
        {
            var identity = (ClaimsIdentity)ctx.Principal.Identity;
            var profilePic = ctx.User.GetProperty("picture").GetString();
            var email = ctx.User.GetProperty("email").GetString();
            var name = ctx.User.GetProperty("name").GetString();
            // Add claims
            identity.AddClaim(new Claim("profilePic", profilePic));
            identity.AddClaim(new Claim(ClaimTypes.Email, email));
            identity.AddClaim(new Claim(ClaimTypes.Name, name));
            return Task.CompletedTask;
        };
    });
    builder.Services.ConfigureApplicationCookie(options =>
    {
        options.Cookie.HttpOnly = true;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.SameSite = SameSiteMode.Strict;
    });
    builder.Services.AddControllersWithViews();
    var app = builder.Build();
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    else
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseAuthentication(); // Ensure Authentication is before Authorization
    app.UseAuthorization();
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    app.MapRazorPages();
    app.Run();
  • Update Configuration in appsettings.json: Open appsettings.json and add your Google Client ID and Client Secret.
    {
        "Authentication": {
            "Google": {
                "ClientId": "YOUR_GOOGLE_CLIENT_ID",
                "ClientSecret": "YOUR_GOOGLE_CLIENT_SECRET"
            }
        },
    }
    

Step 4. Update your MVC application for authentication

  • Add Login Action: In your AccountController, add the following action method for logging in.
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using System.Security.Claims;
    using GoogleAuthInAspNetCoreMVC.Models;
    using GoogleAuthInAspNetCoreMVC.Data;
    
    namespace GoogleAuthInAspNetCoreMVC.Controllers
    {
        public class AccountController : Controller
        {
            private readonly SignInManager<IdentityUser> _signInManager;
            private readonly UserManager<IdentityUser> _userManager;
            private readonly GoogleAuthInAspNetCoreMVCContext _dbContext;
            public AccountController(
                SignInManager<IdentityUser> signInManager,
                UserManager<IdentityUser> userManager,
                GoogleAuthInAspNetCoreMVCContext dbContext)
            {
                _signInManager = signInManager;
                _userManager = userManager;
                _dbContext = dbContext;
            }
            public IActionResult Index()
            {
                return View();
            }
            public IActionResult AccessDenied()
            {
                return View();
            }
            public IActionResult Login(string returnUrl = "/")
            {
                return Challenge(new AuthenticationProperties { RedirectUri = returnUrl });
            }
            public IActionResult Logout()
            {
                return SignOut(new AuthenticationProperties { RedirectUri = "/" },
                    CookieAuthenticationDefaults.AuthenticationScheme);
            }
            [HttpGet]
            [AllowAnonymous]
            public IActionResult ExternalLogin(string returnUrl = "/")
            {
                var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
                var properties = _signInManager.ConfigureExternalAuthenticationProperties("Google", redirectUrl);
                return Challenge(properties, "Google");
            }
            [HttpGet]
            [AllowAnonymous]
            public async Task<IActionResult> ExternalLoginCallback(string returnUrl = "/")
            {
                var info = await _signInManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    // Handle external login failure
                    return RedirectToAction(nameof(Login));
                }
                var user = new AppUser
                {
                    Email = info.Principal.FindFirstValue(ClaimTypes.Email),
                    FirstName = info.Principal.FindFirstValue(ClaimTypes.GivenName),
                    LastName = info.Principal.FindFirstValue(ClaimTypes.Surname),
                    ProfilePic = info.Principal.FindFirstValue("profilePic")
                };
                // Save user data to the database
                _dbContext.Users.Add(user);
                await _dbContext.SaveChangesAsync();
                // Sign in user
                var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
                if (result.Succeeded)
                {
                    return LocalRedirect(returnUrl);
                }
                else
                {
                    // Handle sign-in failure
                    return RedirectToAction(nameof(Login));
                }
            }
        }
    }
    
  • Add Logout Action: In the same way, AccountController, adds the action method for logging out.
    public async Task<IActionResult> Logout()
    {
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        return RedirectToAction("Index", "Home");
    }
    
  • Update Views: Open _Layout.cshtml and add login and logout links.
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - GoogleAuthInAspNetCoreMVC</title>
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
        <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
        <link rel="stylesheet" href="~/GoogleAuthInAspNetCoreMVC.styles.css" asp-append-version="true" />
    </head>
    <body>
        <header>
            <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
                <div class="container">
                    <a class="navbar-brand" asp-area="" asp-page="/Index">GoogleAuthInAspNetCoreMVC</a>
                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                        <ul class="navbar-nav flex-grow-1">
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-action="Index" asp-controller="Account">Account</a>
                            </li>
                        </ul>
                    </div>
                    <partial name="_LoginPartial" />
                </div>
            </nav>
        </header>
        <div class="container">
            <main role="main" class="pb-3">
                @RenderBody()
            </main>
        </div>
        <footer class="border-top footer text-muted">
            <div class="container">
                &copy; 2024 - GoogleAuthInAspNetCoreMVC - <a asp-area="" asp-page="/Privacy">Privacy</a>
            </div>
        </footer>
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
        @await RenderSectionAsync("Scripts", required: false)
    </body>
    </html>

Step 5. Run your application

  1. Start the Application: Press F5 to build and run your application.
  2. Login with Google
    • Navigate to your application's homepage.
    • Click on the Login with Google link.
    • You will be redirected to Google's login page. Enter your credentials.
  3. Post-login Redirection: After successful login, you will be redirected back to your application, now authenticated.

Output

Now we will Hit the google login button the google panel will appear. You need to select the account and then authenticate it.

Google Panel

After successful login, we are on the home page.

Home Page

GitHub Project Link: https://github.com/SardarMudassarAliKhan/GoogleAuthInAspNetCoreMVC

Conclusion

By following these steps, you can successfully integrate Google Authentication into your ASP.NET Core MVC application. This setup allows users to securely log in using their Google accounts, enhancing both security and the user experience. Depending on your needs, you can further customize the authentication process, manage user profiles, and implement role-based access control.


Similar Articles