In this article, we will learn how to login with google in Angular using ASP.NET Core.
1. Create the Angular App
Create the app using below command:
ng new YourProjectName
Install the angularx social login module
npm install angularx-social-login
2. Get client id from google
Get client id using this Link.
Now Use your google client ID and activate the social login module in the providers section of the app.module.ts:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http' import {FormsModule} from '@angular/forms' import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import {SocialAuthServiceConfig} from 'angularx-social-login' import {SocialLoginModule, GoogleLoginProvider} from 'angularx-social-login'; import { HomeComponent } from './home/home.component' @NgModule({ declarations: [ AppComponent, HomeComponent ], imports: [ BrowserModule, AppRoutingModule, SocialLoginModule, HttpClientModule, FormsModule ], providers: [ { provide: 'SocialAuthServiceConfig', useValue: { autoLogin: false, providers: [ { id: GoogleLoginProvider.PROVIDER_ID, provider: new GoogleLoginProvider( // add your google client id here ) } ] } as SocialAuthServiceConfig, } ], bootstrap: [AppComponent] }) export class AppModule { }
Now add new component using below command
ng g c ComponantName
Add routing like below
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; const routes: Routes = [ {path: 'login', component: HomeComponent}, {path: '**', redirectTo: 'login'} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Create the Login Code
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { SocialAuthService, SocialUser, GoogleLoginProvider } from 'angularx-social-login' @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { user?: SocialUser; hasApiAccess = false; constructor(private socialAuthService: SocialAuthService, private http: HttpClient) { } ngOnInit(): void { this.socialAuthService.authState.subscribe((user) => { if (user) { this.http.post<any>('https://localhost:44361/authenticate', { idToken: user.idToken, accessToken: user.response.access_token }).subscribe((authToken: any) => { console.log(authToken); let reqHeader = new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + authToken.authToken }); this.http.get<any>('https://localhost:44361/secured', { headers: reqHeader }).subscribe((data: any) => { this.hasApiAccess = true; }) }) } this.user = user; }) } loginWithgoogle(): any { this.socialAuthService.signIn(GoogleLoginProvider.PROVIDER_ID); } signout(): any { this.socialAuthService.signOut(); } }
Add HTML
<div class="container mt-5"> <div *ngIf="!user" class="card text-center" style="width: 18rem; padding: 10px;"> <h5>Google Login</h5> <div class="card-block"> <h4 class="card-title"> Not sign in </h4> <p class="card-text">sign in with</p> </div> <div class="card-block"> <button class="btn btn-primary" (click)="loginWithgoogle()">Login with Google</button> </div> </div> <div *ngIf="user" class="card text-center" style="width: 18rem; padding: 10px;"> <h5>Google Login</h5> <div class="card-block"> <p class="card-title">{{user.name}}</p> <p class="card-text">{{user.email}}</p> </div> <div class="card-block"> <button class="btn btn-danger" (click)="signout()">sign out</button> </div> </div> </div>
3. Authentication API in the .NET Core Backend
install the google Auth Package below:
Install-Package Google.Apis.Auth
Add below code in controller
using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using Google.Apis.Auth; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Configuration; using System.ComponentModel.DataAnnotations; namespace LoginWithGoogle.Controllers { [ApiController] public class LoginController : ControllerBase { public class AuthenticateRequest { [Required] public string IdToken { get; set; } public string AccessToken { get; set; } } private readonly JwtGenerator _jwtGenerator; public LoginController(IConfiguration configuration) { _jwtGenerator = new JwtGenerator(configuration.GetValue<string>("JwtPrivateSigningKey")); } [AllowAnonymous] [HttpPost("authenticate")] public IActionResult Authenticate([FromBody] AuthenticateRequest data) { GoogleJsonWebSignature.ValidationSettings settings = new GoogleJsonWebSignature.ValidationSettings(); settings.Audience = new List<string>() { "your client id" }; GoogleJsonWebSignature.Payload payload = GoogleJsonWebSignature.ValidateAsync(data.IdToken, settings).Result; return Ok(new { AuthToken = _jwtGenerator.CreateUserAuthToken(payload.Email) }); } } }
Add below key to appsettings.json
"JwtPrivateSigningKey": "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"
Edit Startup.cs
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using System; using System.Security.Cryptography; namespace LoginWithGoogle { public class Startup { public class ConfigureJwtBearerOptions : IConfigureNamedOptions<JwtBearerOptions> { public void Configure(string name, JwtBearerOptions options) { RSA rsa = RSA.Create(); rsa.ImportRSAPublicKey(Convert.FromBase64String(PUBLIC_KEY), out _); options.IncludeErrorDetails = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new RsaSecurityKey(rsa), ValidateIssuer = true, ValidIssuer = "AuthService", ValidateAudience = true, ValidAudience = "myApi", CryptoProviderFactory = new CryptoProviderFactory() { CacheSignatureProviders = false } }; } public void Configure(JwtBearerOptions options) { throw new NotImplementedException(); } } public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "LoginWithGoogle", Version = "v1" }); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "LoginWithGoogle v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseCors(x => x .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader()); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } private const string PUBLIC_KEY = @"MIICCgKCAgEAtCR2Pii+q9C76P2E9ydHYxnBPjJFGT7MvHuQPKpcS9RImfrkobt0 LPS/406eWm/tRBvnYD9nDpHJNKN3TjEenFQuDGR4RHcGK/e43SAhTAi7+s0tfAQd 6BK4gznIwvs5cWyilh1B7c9sCnxhJ/EYLIe1N2yiD8mhvfojIF4vMYxONIMTGYXy 87lnO9zRAdXAZ39YbtmFmQwK8gfXX5d/XVlKy0tc2y5bRY5iXn9kwqwvFlzL6O4v pjhqA5kwsJV7efhL9nU0ACR4dG3zwFR3SAOOSETXjnfmjH2ocga+oa65ToypUz2L 1DwnNHt+M5CtDJ9um4dbYaqfBWkjWe3FuGB0GNPS8pbX2nVt76OfHA/QKmxTWvFd POZnjpg2QhDujyXgoIY731zx5bAklKVoKFma/qfWfCyCSTUzhgu1KQm9swipMsQy NYr9CjbnIlPn4EvrBIbGcIiaRNCLCIlcAuxE/GiH1zBUfeJxfJQmurejp6mBAtAS FY08DmUebBz8mlUbB+LXMYKHZ4GK6TecPy0WJU2qRMQ//PKfOa+wkesp4M53SQdp ItDp5akTzYUo4rXwk3HPCtemKaSNhyG+EYtZ1CAmPN5sEjU0/x0Dq7SU5o8KhogB m/5HRJ3M9dMRcwD3OcsMl0kW1PPUt04itboS3SlFav90V9uc2YNGpPsCAwEAAQ=="; } }
Add a controller:
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace LoginWithGoogle.Controllers { [ApiController] [Route("[controller]")] public class SecuredController : ControllerBase { [Authorize] [HttpGet] public void Test() { return; } } }