import { AuthenticationStrategy, ExternalAuthenticationService, Injector, RequestContext, User, } from '@vendure/core'; import { OAuth2Client } from 'google-auth-library'; import { DocumentNode } from 'graphql'; import gql from 'graphql-tag'; export type GoogleAuthData = { token: string; }; export class GoogleAuthenticationStrategy implements AuthenticationStrategy { readonly name = 'google'; private client: OAuth2Client; private externalAuthenticationService: ExternalAuthenticationService; constructor(private clientId: string) { this.client = new OAuth2Client(clientId); } init(injector: Injector) { this.externalAuthenticationService = injector.get(ExternalAuthenticationService); } defineInputType(): DocumentNode { return gql` input GoogleAuthInput { token: String! } `; } /** * Implements https://developers.google.com/identity/sign-in/web/backend-auth */ async authenticate(ctx: RequestContext, data: GoogleAuthData): Promise { const ticket = await this.client.verifyIdToken({ idToken: data.token, audience: this.clientId, }); const payload = ticket.getPayload(); if (!payload || !payload.email) { return false; } const user = await this.externalAuthenticationService.findCustomerUser(ctx, this.name, payload.sub); if (user) { return user; } return this.externalAuthenticationService.createCustomerAndUser(ctx, { strategy: this.name, externalIdentifier: payload.sub, verified: payload.email_verified || false, emailAddress: payload.email, firstName: payload.given_name, lastName: payload.family_name, }); } }