Skip to content

Instantly share code, notes, and snippets.

@thisismydesign
Last active September 6, 2023 12:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thisismydesign/8e6139ba17649e789f97375569c84b1a to your computer and use it in GitHub Desktop.
Save thisismydesign/8e6139ba17649e789f97375569c84b1a to your computer and use it in GitHub Desktop.
NestJS Google OAuth
this.oauth2Client.getTokenInfo(
req.user.accessToken,
);
tokenInfo {
web_1 | expiry_date: 1619210156644,
web_1 | scopes: [
web_1 | 'https://www.googleapis.com/auth/userinfo.email',
web_1 | 'https://www.googleapis.com/auth/userinfo.profile',
web_1 | 'openid'
web_1 | ],
web_1 | azp: 'xyz123.apps.googleusercontent.com',
web_1 | aud: 'xyz123.apps.googleusercontent.com',
web_1 | sub: '123',
web_1 | exp: '1619210157',
web_1 | email: 'x.y@gmail.com',
web_1 | email_verified: 'true',
web_1 | access_type: 'online'
web_1 | }
google example:
profile in strat validate
{
web_1 | id: '123',
web_1 | displayName: 'X Y',
web_1 | name: { familyName: 'X', givenName: 'Y' },
web_1 | emails: [ { value: 'x.y@gmail.com', verified: true } ],
web_1 | photos: [
web_1 | {
web_1 | value: 'https://lh3.googleusercontent.com/a-/abc123'
web_1 | }
web_1 | ],
web_1 | provider: 'google'
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GoogleOauthService } from './google-oauth.service';
import { OAuth2Client } from 'google-auth-library';
import { ConfigService } from '@nestjs/config';
import { GoogleOauthGuard } from './google-oauth.guard';
@Controller('auth/google')
export class GoogleOauthController {
private oauth2Client: OAuth2Client;
private configService: ConfigService;
constructor(
private readonly googleOauthService: GoogleOauthService,
configService: ConfigService,
) {
this.configService = configService;
this.oauth2Client = new OAuth2Client(
configService.get<string>('OAUTH_GOOGLE_ID'),
configService.get<string>('OAUTH_GOOGLE_SECRET'),
configService.get<string>('OAUTH_GOOGLE_REDIRECT_URL'),
);
}
@Get()
@UseGuards(AuthGuard('google'))
async googleAuth(@Req() _req) {
// Guard redirects
}
@Get('redirect')
// @UseGuards(GoogleOauthGuard) => enable `validate`, or do it by hand as below
async googleAuthRedirect(@Req() req) {
console.log('redirect route');
console.log('code', req.query.code);
const tokens = await this.oauth2Client.getToken(req.query.code);
console.log('tokens', tokens);
const accessToken = tokens.tokens.access_token;
const idToken = tokens.tokens.id_token;
console.log('accessToken', accessToken);
const tokenInfo = await this.oauth2Client.getTokenInfo(accessToken);
console.log('tokenInfo', tokenInfo);
// getTokenInfo will raise `invalid_token` if token is invalid/expired/etc. yay!
// const wrongTokenInfo = await this.oauth2Client.getTokenInfo('invalid');
// This would need a refresh token
// const atoken = await this.oauth2Client.getAccessToken();
// console.log('atoken', atoken);
const res = await this.oauth2Client.verifyIdToken({
idToken: idToken,
audience: this.configService.get<string>('OAUTH_GOOGLE_ID'),
});
console.log('verifyIdToken', res);
return this.googleOauthService.login(req);
}
}
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class GoogleOauthStrategy extends PassportStrategy(Strategy, 'google') {
constructor(configService: ConfigService) {
super({
clientID: configService.get<string>('OAUTH_GOOGLE_ID'),
clientSecret: configService.get<string>('OAUTH_GOOGLE_SECRET'),
callbackURL: configService.get<string>('OAUTH_GOOGLE_REDIRECT_URL'),
scope: ['email', 'profile'],
});
}
async validate(
accessToken: string,
refreshToken: string,
profile: any,
): Promise<any> {
const { name, emails, photos } = profile;
const user = {
email: emails[0].value,
firstName: name.givenName,
lastName: name.familyName,
picture: photos[0].value,
accessToken,
};
return user;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment