Google Login With Nest.js
This article will teach you how to login users using Google in the backend using Nest.js.
Last Updated: January 23, 2022
nest.js
authentication
In a previous article, I showed you how to handle email and password authentication, refresh and access tokens all in Nest.js. This article is extending that code to also allow users to login with their Google Account. I highly recommend you start with that article, but if you already have a JWT or session based authentication in place in your app and are just looking to code along to learn how to add Google Authentication to your project than this you can fork the main branch from this repo.
Auth Flow
To begin, you must first understand the authentication flow. Because this backend is built for a frontend website or app, we will not handling getting an access secret from Google when logging in. This should be done in your frontend. If you want to see an article of me doing this please comment in this article. Once the client gets the access secret from Google the frontend will send it to the backend which we are building which will communicate with Google and retrieve the email from the access token. Once the email is retrieved then our backend can log the user in and give the frontend the new access and refresh token.
Begin Coding
Once you have forked the main branch of the repo project you can begin coding. The first thing we need to do is add a function inside of our auth.service.ts
to handle loggin in our Google User. But in order to do this we need to import googleapis
from npm by typing: npm install googleapis
in your terminal. Once that is installed we can create a new iVar inside of AuthService
called oauthClient
this will handle the authenticating of our access token and in our constructor we can instantiate it. So we have the following code:
// auth.service.ts ... import { Auth, google } from 'googleapis'; @Injectable() export class AuthService { private refreshTokens: RefreshToken[] = []; private oauthClient: Auth.OAuth2Client; // add this constructor(private readonly userService: UserService) { // we will get our GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET SOON // // initialize that oauthClient using the google.auth.OAuth2 constructor const clientId = process.env.GOOGLE_CLIENT_ID; const clientSecret = process.env.GOOGLE_CLIENT_SECRET; this.oauthClient = new google.auth.OAuth2(clientId, clientSecret); } ... }
Now we can begin to create our loginGoogleUser
method. This method will use the oauthClient
to get the email address of the user signing in, find the corresponding user using UserService
and create refresh and access tokens for that user. The method looks like the following:
// auth.service.ts async loginGoogleUser( token: string, values: { userAgent: string; ipAddress: string }, ): Promise<{ accessToken: string; refreshToken: string } | undefined> { const tokenInfo = await this.oauthClient.getTokenInfo(token); const user = await this.userService.findByEmail(tokenInfo.email); if (user) { return this.newRefreshAndAccessToken(user, values); } return undefined; }
API Code
With our business logic for logging in Google Users done, now we can provide this code to our API so in AuthController
add the route: '/google/login' and we will call the AuthService.loginGoogleUser()
to get the tokens. If no user exists we will throw an Http Error. This code looks like:
// auth.controller.ts @Post('/google/login') async googleLogin( @Body() body: GoogleTokenDto, @Req() req, @Ip() ip: string, ): Promise<{ accessToken: string; refreshToken: string }> { const result = await this.authService.loginGoogleUser(body.token, { userAgent: req.headers['user-agent'], ipAddress: ip, }); if (result) { return result; } else { throw new HttpException( { status: HttpStatus.UNAUTHORIZED, error: 'Error while logging in with google', }, HttpStatus.UNAUTHORIZED, ); } }
Getting the Credentials
Now the final part of this is to get the Google Credentials. I recommend watching me do this in the video above as most of the work needs to be done in the browser. Once you have the secret and client id you can add those to your environment and you are set to go!
Conclusion
Thank you for reading this article and if you enjoyed it share it on social media, or leave a comment below. As always the code is on Github (link is at the top of article).
Comments
Loading...