google.strategy.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { Strategy, VerifyCallback } from 'passport-google-oauth20';
  2. import { PassportStrategy } from '@nestjs/passport';
  3. import { Injectable, UnauthorizedException } from '@nestjs/common';
  4. import { UserService } from 'src/user/user.service';
  5. import * as O from 'fp-ts/Option';
  6. import { AuthService } from '../auth.service';
  7. import * as E from 'fp-ts/Either';
  8. @Injectable()
  9. export class GoogleStrategy extends PassportStrategy(Strategy) {
  10. constructor(
  11. private usersService: UserService,
  12. private authService: AuthService,
  13. ) {
  14. super({
  15. clientID: process.env.GOOGLE_CLIENT_ID,
  16. clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  17. callbackURL: process.env.GOOGLE_CALLBACK_URL,
  18. scope: process.env.GOOGLE_SCOPE.split(','),
  19. passReqToCallback: true,
  20. store: true,
  21. });
  22. }
  23. async validate(
  24. req: Request,
  25. accessToken,
  26. refreshToken,
  27. profile,
  28. done: VerifyCallback,
  29. ) {
  30. const user = await this.usersService.findUserByEmail(
  31. profile.emails[0].value,
  32. );
  33. if (O.isNone(user)) {
  34. const createdUser = await this.usersService.createUserSSO(
  35. accessToken,
  36. refreshToken,
  37. profile,
  38. );
  39. return createdUser;
  40. }
  41. /**
  42. * * displayName and photoURL maybe null if user logged-in via magic-link before SSO
  43. */
  44. if (!user.value.displayName || !user.value.photoURL) {
  45. const updatedUser = await this.usersService.updateUserDetails(
  46. user.value,
  47. profile,
  48. );
  49. if (E.isLeft(updatedUser)) {
  50. throw new UnauthorizedException(updatedUser.left);
  51. }
  52. }
  53. /**
  54. * * Check to see if entry for Google is present in the Account table for user
  55. * * If user was created with another provider findUserByEmail may return true
  56. */
  57. const providerAccountExists =
  58. await this.authService.checkIfProviderAccountExists(user.value, profile);
  59. if (O.isNone(providerAccountExists))
  60. await this.usersService.createProviderAccount(
  61. user.value,
  62. accessToken,
  63. refreshToken,
  64. profile,
  65. );
  66. return user.value;
  67. }
  68. }