Skip to content

Commit

Permalink
Sohail/remove google auth (#32)
Browse files Browse the repository at this point in the history
* remove google login related code

* remove SIGNUPMETHOD type

* resolve linting warnings

* fixup! resolve linting warnings

* remove react-google-login dependancy
  • Loading branch information
SohailSayed authored Mar 11, 2024
1 parent 54ad841 commit 68bbba4
Show file tree
Hide file tree
Showing 13 changed files with 9 additions and 250 deletions.
10 changes: 0 additions & 10 deletions backend/graphql/resolvers/authResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ const authResolvers = {
res.cookie("refreshToken", refreshToken, cookieOptions);
return rest;
},
loginWithGoogle: async (
_parent: undefined,
{ idToken }: { idToken: string },
{ res }: { res: Response },
): Promise<Omit<AuthDTO, "refreshToken">> => {
const authDTO = await authService.generateTokenOAuth(idToken);
const { refreshToken, ...rest } = authDTO;
res.cookie("refreshToken", refreshToken, cookieOptions);
return rest;
},
register: async (
_parent: undefined,
{ user }: { user: RegisterUserDTO },
Expand Down
1 change: 0 additions & 1 deletion backend/graphql/types/authType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 0 additions & 39 deletions backend/services/implementations/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,45 +38,6 @@ class AuthService implements IAuthService {
}
}

/* eslint-disable class-methods-use-this */
async generateTokenOAuth(idToken: string): Promise<AuthDTO> {
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<void> {
try {
const authId = await this.userService.getAuthIdById(userId);
Expand Down
21 changes: 5 additions & 16 deletions backend/services/implementations/userService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,26 +140,15 @@ class UserService implements IUserService {
return userDtos;
}

async createUser(
user: CreateUserDTO,
authId?: string,
signUpMethod = "PASSWORD",
): Promise<UserDTO> {
async createUser(user: CreateUserDTO, authId?: string): Promise<UserDTO> {

Check warning on line 143 in backend/services/implementations/userService.ts

View workflow job for this annotation

GitHub Actions / run-lint

'authId' is defined but never used
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,
Expand Down
9 changes: 0 additions & 9 deletions backend/services/interfaces/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ interface IAuthService {
*/
generateToken(email: string, password: string): Promise<AuthDTO>;

/**
* 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<AuthDTO>;

/**
* Revoke all refresh tokens of a user
* @param userId userId of user whose refresh tokens are to be revoked
Expand Down
15 changes: 2 additions & 13 deletions backend/services/interfaces/userService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
CreateUserDTO,
Role,
SignUpMethod,
UpdateUserDTO,
UserDTO,
} from "../../types";
import { CreateUserDTO, Role, UpdateUserDTO, UserDTO } from "../../types";

interface IUserService {
/**
Expand Down Expand Up @@ -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<UserDTO>;
createUser(user: CreateUserDTO, authId?: string): Promise<UserDTO>;

/**
* Update a user.
Expand Down
2 changes: 0 additions & 2 deletions backend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,3 @@ export type NodemailerConfig = {
refreshToken: string;
};
};

export type SignUpMethod = "PASSWORD" | "GOOGLE";
62 changes: 0 additions & 62 deletions backend/utilities/firebaseRestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<OAuthSignInResponse> => {
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<Token> => {
const response: Response = await fetch(
Expand Down
1 change: 0 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
37 changes: 1 addition & 36 deletions frontend/src/APIClients/AuthAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,6 @@ const login = async (
return user;
};

type LoginWithGoogleFunction = (
options?:
| MutationFunctionOptions<
{ loginWithGoogle: AuthenticatedUser },
OperationVariables
>
| undefined,
) => Promise<
FetchResult<
{ loginWithGoogle: AuthenticatedUser },
Record<string, unknown>,
Record<string, unknown>
>
>;

const loginWithGoogle = async (
idToken: string,
loginFunction: LoginWithGoogleFunction,
): Promise<AuthenticatedUser | null> => {
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<
Expand Down Expand Up @@ -179,4 +144,4 @@ const refresh = async (refreshFunction: RefreshFunction): Promise<boolean> => {
return success;
};

export default { login, logout, loginWithGoogle, register, refresh };
export default { login, logout, register, refresh };
41 changes: 1 addition & 40 deletions frontend/src/components/auth/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
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("");
const [password, setPassword] = useState("");
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,
Expand Down Expand Up @@ -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 <Redirect to={HOME_PAGE} />;
}
Expand Down Expand Up @@ -101,22 +78,6 @@ const Login = (): React.ReactElement => {
Log In
</button>
</div>
<GoogleLogin
clientId={process.env.REACT_APP_OAUTH_CLIENT_ID || ""}
buttonText="Login with Google"
onSuccess={(response: GoogleResponse): void => {
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))
}
/>
</form>
<div>
<button
Expand Down
13 changes: 0 additions & 13 deletions frontend/src/graphql/Mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,6 @@ export const LOGIN = gql`
}
`;

export const LOGIN_WITH_GOOGLE = gql`
mutation LoginWithGoogle($idToken: String!) {
loginWithGoogle(idToken: $idToken) {
id
firstName
lastName
email
role
accessToken
}
}
`;

export const REGISTER = gql`
mutation Signup_Register(
$firstName: String!
Expand Down
Loading

0 comments on commit 68bbba4

Please sign in to comment.