google-authentication-strategy.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import {
  2. AuthenticationStrategy,
  3. ExternalAuthenticationService,
  4. Injector,
  5. RequestContext,
  6. User,
  7. } from '@vendure/core';
  8. import { OAuth2Client } from 'google-auth-library';
  9. import { DocumentNode } from 'graphql';
  10. import gql from 'graphql-tag';
  11. export type GoogleAuthData = {
  12. token: string;
  13. };
  14. export class GoogleAuthenticationStrategy implements AuthenticationStrategy<GoogleAuthData> {
  15. readonly name = 'google';
  16. private client: OAuth2Client;
  17. private externalAuthenticationService: ExternalAuthenticationService;
  18. constructor(private clientId: string) {
  19. this.client = new OAuth2Client(clientId);
  20. }
  21. init(injector: Injector) {
  22. this.externalAuthenticationService = injector.get(ExternalAuthenticationService);
  23. }
  24. defineInputType(): DocumentNode {
  25. return gql`
  26. input GoogleAuthInput {
  27. token: String!
  28. }
  29. `;
  30. }
  31. /**
  32. * Implements https://developers.google.com/identity/sign-in/web/backend-auth
  33. */
  34. async authenticate(ctx: RequestContext, data: GoogleAuthData): Promise<User | false> {
  35. const ticket = await this.client.verifyIdToken({
  36. idToken: data.token,
  37. audience: this.clientId,
  38. });
  39. const payload = ticket.getPayload();
  40. if (!payload || !payload.email) {
  41. return false;
  42. }
  43. const user = await this.externalAuthenticationService.findCustomerUser(ctx, this.name, payload.sub);
  44. if (user) {
  45. return user;
  46. }
  47. return this.externalAuthenticationService.createCustomerAndUser(ctx, {
  48. strategy: this.name,
  49. externalIdentifier: payload.sub,
  50. verified: payload.email_verified || false,
  51. emailAddress: payload.email,
  52. firstName: payload.given_name,
  53. lastName: payload.family_name,
  54. });
  55. }
  56. }