From 68bbba467c21540d128788837338e3244a44a743 Mon Sep 17 00:00:00 2001 From: Sohail Sayed <44615627+SohailSayed@users.noreply.github.com> Date: Sun, 10 Mar 2024 20:39:14 -0400 Subject: [PATCH] Sohail/remove google auth (#32) * remove google login related code * remove SIGNUPMETHOD type * resolve linting warnings * fixup! resolve linting warnings * remove react-google-login dependancy --- backend/graphql/resolvers/authResolvers.ts | 10 --- backend/graphql/types/authType.ts | 1 - .../services/implementations/authService.ts | 39 ------------ .../services/implementations/userService.ts | 21 ++----- backend/services/interfaces/authService.ts | 9 --- backend/services/interfaces/userService.ts | 15 +---- backend/types.ts | 2 - backend/utilities/firebaseRestClient.ts | 62 ------------------- frontend/package.json | 1 - frontend/src/APIClients/AuthAPIClient.ts | 37 +---------- frontend/src/components/auth/Login.tsx | 41 +----------- frontend/src/graphql/Mutations.ts | 13 ---- frontend/yarn.lock | 8 --- 13 files changed, 9 insertions(+), 250 deletions(-) diff --git a/backend/graphql/resolvers/authResolvers.ts b/backend/graphql/resolvers/authResolvers.ts index 57e4c67..419675e 100644 --- a/backend/graphql/resolvers/authResolvers.ts +++ b/backend/graphql/resolvers/authResolvers.ts @@ -31,16 +31,6 @@ const authResolvers = { res.cookie("refreshToken", refreshToken, cookieOptions); return rest; }, - loginWithGoogle: async ( - _parent: undefined, - { idToken }: { idToken: string }, - { res }: { res: Response }, - ): Promise> => { - const authDTO = await authService.generateTokenOAuth(idToken); - const { refreshToken, ...rest } = authDTO; - res.cookie("refreshToken", refreshToken, cookieOptions); - return rest; - }, register: async ( _parent: undefined, { user }: { user: RegisterUserDTO }, diff --git a/backend/graphql/types/authType.ts b/backend/graphql/types/authType.ts index 52972ef..6221d44 100644 --- a/backend/graphql/types/authType.ts +++ b/backend/graphql/types/authType.ts @@ -19,7 +19,6 @@ const authType = gql` extend type Mutation { login(email: String!, password: String!): AuthDTO! - loginWithGoogle(idToken: String!): AuthDTO! register(user: RegisterUserDTO!): AuthDTO! refresh: String! logout(userId: ID!): ID diff --git a/backend/services/implementations/authService.ts b/backend/services/implementations/authService.ts index ecd3b94..7c79d1a 100644 --- a/backend/services/implementations/authService.ts +++ b/backend/services/implementations/authService.ts @@ -38,45 +38,6 @@ class AuthService implements IAuthService { } } - /* eslint-disable class-methods-use-this */ - async generateTokenOAuth(idToken: string): Promise { - try { - const googleUser = await FirebaseRestClient.signInWithGoogleOAuth( - idToken, - ); - // googleUser.idToken refers to the Firebase Auth access token for the user - const token = { - accessToken: googleUser.idToken, - refreshToken: googleUser.refreshToken, - }; - // If user already has a login with this email, just return the token - try { - // Note: an error message will be logged from UserService if this lookup fails. - // You may want to silence the logger for this special OAuth user lookup case - const user = await this.userService.getUserByEmail(googleUser.email); - return { ...token, ...user }; - /* eslint-disable-next-line no-empty */ - } catch (error) {} - - const user = await this.userService.createUser( - { - firstName: googleUser.firstName, - lastName: googleUser.lastName, - email: googleUser.email, - role: "Volunteer", - password: "", - }, - googleUser.localId, - "GOOGLE", - ); - - return { ...token, ...user }; - } catch (error) { - Logger.error(`Failed to generate token for user with OAuth ID token`); - throw error; - } - } - async revokeTokens(userId: string): Promise { try { const authId = await this.userService.getAuthIdById(userId); diff --git a/backend/services/implementations/userService.ts b/backend/services/implementations/userService.ts index 9be67dd..5dc291e 100644 --- a/backend/services/implementations/userService.ts +++ b/backend/services/implementations/userService.ts @@ -140,26 +140,15 @@ class UserService implements IUserService { return userDtos; } - async createUser( - user: CreateUserDTO, - authId?: string, - signUpMethod = "PASSWORD", - ): Promise { + async createUser(user: CreateUserDTO, authId?: string): Promise { let newUser: User; let firebaseUser: firebaseAdmin.auth.UserRecord; try { - if (signUpMethod === "GOOGLE") { - /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ - firebaseUser = await firebaseAdmin.auth().getUser(authId!); - } else { - // signUpMethod === PASSWORD - firebaseUser = await firebaseAdmin.auth().createUser({ - email: user.email, - password: user.password, - }); - } - + firebaseUser = await firebaseAdmin.auth().createUser({ + email: user.email, + password: user.password, + }); try { newUser = await MgUser.create({ firstName: user.firstName, diff --git a/backend/services/interfaces/authService.ts b/backend/services/interfaces/authService.ts index 85d4f36..194eb4a 100644 --- a/backend/services/interfaces/authService.ts +++ b/backend/services/interfaces/authService.ts @@ -11,15 +11,6 @@ interface IAuthService { */ generateToken(email: string, password: string): Promise; - /** - * Generate a short-lived JWT access token and a long-lived refresh token - * when supplied OAuth ID token - * @param idToken user's ID token - * @returns AuthDTO object containing the access token, refresh token, and user info - * @throws Error if token generation fails - */ - generateTokenOAuth(idToken: string): Promise; - /** * Revoke all refresh tokens of a user * @param userId userId of user whose refresh tokens are to be revoked diff --git a/backend/services/interfaces/userService.ts b/backend/services/interfaces/userService.ts index 7b00d01..77ebb74 100644 --- a/backend/services/interfaces/userService.ts +++ b/backend/services/interfaces/userService.ts @@ -1,10 +1,4 @@ -import { - CreateUserDTO, - Role, - SignUpMethod, - UpdateUserDTO, - UserDTO, -} from "../../types"; +import { CreateUserDTO, Role, UpdateUserDTO, UserDTO } from "../../types"; interface IUserService { /** @@ -58,15 +52,10 @@ interface IUserService { * Create a user, email verification configurable * @param user the user to be created * @param authId the user's firebase auth id, optional - * @param signUpMethod the method user used to signup * @returns a UserDTO with the created user's information * @throws Error if user creation fails */ - createUser( - user: CreateUserDTO, - authId?: string, - signUpMethod?: SignUpMethod, - ): Promise; + createUser(user: CreateUserDTO, authId?: string): Promise; /** * Update a user. diff --git a/backend/types.ts b/backend/types.ts index 71ff32f..5b555b5 100644 --- a/backend/types.ts +++ b/backend/types.ts @@ -35,5 +35,3 @@ export type NodemailerConfig = { refreshToken: string; }; }; - -export type SignUpMethod = "PASSWORD" | "GOOGLE"; diff --git a/backend/utilities/firebaseRestClient.ts b/backend/utilities/firebaseRestClient.ts index 8afa69f..8b4cc61 100644 --- a/backend/utilities/firebaseRestClient.ts +++ b/backend/utilities/firebaseRestClient.ts @@ -9,8 +9,6 @@ const FIREBASE_SIGN_IN_URL = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword"; const FIREBASE_REFRESH_TOKEN_URL = "https://securetoken.googleapis.com/v1/token"; -const FIREBASE_OAUTH_SIGN_IN_URL = - "https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp"; type PasswordSignInResponse = { idToken: string; @@ -21,27 +19,6 @@ type PasswordSignInResponse = { registered: boolean; }; -type OAuthSignInResponse = { - federatedId: string; - providerId: string; - localId: string; - emailVerified: boolean; - email: string; - oauthIdToken: string; - oauthAccessToken: string; - oauthTokenSecret: string; - rawUserInfo: string; - firstName: string; - lastName: string; - fullName: string; - displayName: string; - photoUrl: string; - idToken: string; - refreshToken: string; - expiresIn: string; - needConfirmation: boolean; -}; - type RefreshTokenResponse = { expires_in: string; token_type: string; @@ -103,45 +80,6 @@ const FirebaseRestClient = { }; }, - // Docs: https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-with-oauth-credential - signInWithGoogleOAuth: async ( - idToken: string, - ): Promise => { - const response: Response = await fetch( - `${FIREBASE_OAUTH_SIGN_IN_URL}?key=${process.env.FIREBASE_WEB_API_KEY}`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - postBody: `id_token=${idToken}&providerId=google.com`, - requestUri: process.env.FIREBASE_REQUEST_URI, - returnIdpCredential: true, - returnSecureToken: true, - }), - }, - ); - - const responseJson: - | OAuthSignInResponse - | RequestError = await response.json(); - - if (!response.ok) { - const errorMessage = [ - "Failed to sign-in via Firebase REST API with OAuth, status code =", - `${response.status},`, - "error message =", - (responseJson as RequestError).error.message, - ]; - Logger.error(errorMessage.join(" ")); - - throw new Error("Failed to sign-in via Firebase REST API"); - } - - return responseJson as OAuthSignInResponse; - }, - // Docs: https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token refreshToken: async (refreshToken: string): Promise => { const response: Response = await fetch( diff --git a/frontend/package.json b/frontend/package.json index 9dda911..1e2cd01 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -32,7 +32,6 @@ "react": "^18.2.0", "react-bootstrap": "^1.5.2", "react-dom": "^18.2.0", - "react-google-login": "^5.2.2", "react-json-schema": "^1.2.2", "react-jsonschema-form": "^1.8.1", "react-router-dom": "^5.2.0", diff --git a/frontend/src/APIClients/AuthAPIClient.ts b/frontend/src/APIClients/AuthAPIClient.ts index 4410e88..9d6e27f 100644 --- a/frontend/src/APIClients/AuthAPIClient.ts +++ b/frontend/src/APIClients/AuthAPIClient.ts @@ -38,41 +38,6 @@ const login = async ( return user; }; -type LoginWithGoogleFunction = ( - options?: - | MutationFunctionOptions< - { loginWithGoogle: AuthenticatedUser }, - OperationVariables - > - | undefined, -) => Promise< - FetchResult< - { loginWithGoogle: AuthenticatedUser }, - Record, - Record - > ->; - -const loginWithGoogle = async ( - idToken: string, - loginFunction: LoginWithGoogleFunction, -): Promise => { - let user: AuthenticatedUser = null; - try { - const result = await loginFunction({ - variables: { idToken }, - }); - user = result.data?.loginWithGoogle ?? null; - if (user) { - localStorage.setItem(AUTHENTICATED_USER_KEY, JSON.stringify(user)); - } - } catch (e: unknown) { - // eslint-disable-next-line no-alert - window.alert("Failed to login"); - } - return user; -}; - type RegisterFunction = ( options?: | MutationFunctionOptions< @@ -179,4 +144,4 @@ const refresh = async (refreshFunction: RefreshFunction): Promise => { return success; }; -export default { login, logout, loginWithGoogle, register, refresh }; +export default { login, logout, register, refresh }; diff --git a/frontend/src/components/auth/Login.tsx b/frontend/src/components/auth/Login.tsx index 4454664..f7fe861 100644 --- a/frontend/src/components/auth/Login.tsx +++ b/frontend/src/components/auth/Login.tsx @@ -1,26 +1,14 @@ import React, { useContext, useState } from "react"; import { Redirect, useHistory } from "react-router-dom"; -import { - GoogleLogin, - GoogleLoginResponse, - GoogleLoginResponseOffline, -} from "react-google-login"; import { useMutation, useQuery } from "@apollo/client"; import authAPIClient from "../../APIClients/AuthAPIClient"; import { HOME_PAGE, SIGNUP_PAGE } from "../../constants/Routes"; import AuthContext from "../../contexts/AuthContext"; import { AuthenticatedUser } from "../../types/AuthTypes"; -import { LOGIN, LOGIN_WITH_GOOGLE } from "../../graphql/Mutations"; +import { LOGIN } from "../../graphql/Mutations"; import { IS_VERIFIED } from "../../graphql/Queries"; -type GoogleResponse = GoogleLoginResponse | GoogleLoginResponseOffline; - -type GoogleErrorResponse = { - error: string; - details: string; -}; - const Login = (): React.ReactElement => { const { authenticatedUser, setAuthenticatedUser } = useContext(AuthContext); const [email, setEmail] = useState(""); @@ -28,9 +16,6 @@ const Login = (): React.ReactElement => { const history = useHistory(); const [login] = useMutation<{ login: AuthenticatedUser }>(LOGIN); - const [loginWithGoogle] = useMutation<{ loginWithGoogle: AuthenticatedUser }>( - LOGIN_WITH_GOOGLE, - ); const { data } = useQuery(IS_VERIFIED, { skip: authenticatedUser === null, @@ -60,14 +45,6 @@ const Login = (): React.ReactElement => { history.push(SIGNUP_PAGE); }; - const onGoogleLoginSuccess = async (idToken: string) => { - const user: AuthenticatedUser = await authAPIClient.loginWithGoogle( - idToken, - loginWithGoogle, - ); - setAuthenticatedUser(user); - }; - if (authenticatedUser && isVerified) { return ; } @@ -101,22 +78,6 @@ const Login = (): React.ReactElement => { Log In - { - if ("tokenId" in response) { - onGoogleLoginSuccess(response.tokenId); - } else { - // eslint-disable-next-line no-alert - window.alert(response); - } - }} - onFailure={(error: GoogleErrorResponse) => - // eslint-disable-next-line no-alert - window.alert(JSON.stringify(error)) - } - />