Skip to content

Commit

Permalink
feat: add auth with google
Browse files Browse the repository at this point in the history
  • Loading branch information
TutTrue committed Aug 24, 2024
1 parent 91a8671 commit 3e7c4d5
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 18 deletions.
62 changes: 61 additions & 1 deletion src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
generateJWT,
passToExpressErrorHandler,
verifyRefreshToken,
decodeGoogleCredential,
} from "../utils";
import createError from "http-errors";
import bcrypt from "bcryptjs";
Expand Down Expand Up @@ -161,4 +162,63 @@ export const githubAuthenticator = async (
} catch (err: any) {
passToExpressErrorHandler(err, next);
}
};
};

export const googleAuthenticator = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const { googleAuthCode } = req.body;

const { name, email, googleId } = decodeGoogleCredential(googleAuthCode);
let user;

const alreadyExistingUser = await prisma.user.findFirst({
where: {
OR: [{ email }, { authType: "GOOGLE", authProviderId: googleId }],
},
});

if (
alreadyExistingUser &&
((email && !alreadyExistingUser.email) ||
(alreadyExistingUser.authType !== "GOOGLE" &&
alreadyExistingUser.authProviderId !== googleId) ||
alreadyExistingUser.name !== name)
) {
user = await prisma.user.update({
where: { id: alreadyExistingUser.id },
data: {
name,
email,
authType: "GOOGLE",
authProviderId: googleId,
},
});
} else if (alreadyExistingUser) {
res.status(200).json({
accessToken: generateJWT(alreadyExistingUser.id, email, "access"),
refreshToken: generateJWT(alreadyExistingUser.id, email, "refresh"),
});
return;
} else {
user = await prisma.user.create({
data: {
name,
email,
authType: "GOOGLE",
authProviderId: googleId,
},
});
}

res.status(200).json({
accessToken: generateJWT(user.id, email, "access"),
refreshToken: generateJWT(user.id, email, "refresh"),
});
} catch (err: any) {
passToExpressErrorHandler(err, next);
}
};
3 changes: 2 additions & 1 deletion src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export {
login,
signup,
refreshToken,
githubAuthenticator
githubAuthenticator,
googleAuthenticator
} from "./auth.controller";

export {
Expand Down
19 changes: 19 additions & 0 deletions src/middlewares/validators/auth.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,23 @@ export const githubAuthValidator = async (
err.statusCode = 400;
passToExpressErrorHandler(err, next);
}
};

const googleAuthSchema = Joi.object({
googleAuthCode: Joi.string().required(),
});

export const googleAuthValidator = async (
req: Request,
_res: Response,
next: NextFunction
) => {
try {

await googleAuthSchema.validateAsync(req.body);
next();
} catch (err: any) {
err.statusCode = 400;
passToExpressErrorHandler(err, next);
}
};
1 change: 1 addition & 0 deletions src/middlewares/validators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export {
authSignupValidator,
authRefreshTokenValidator,
githubAuthValidator,
googleAuthValidator,
} from "./auth.validator";
export { claimPostValidator } from "./claim.validator";
7 changes: 4 additions & 3 deletions src/routes/authRoutes/auth.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import express from "express";
import {
authSignupValidator,
authRefreshTokenValidator,
githubAuthValidator,
googleAuthValidator,
} from "../../middlewares/validators";
import {
signup,
login,
refreshToken,
githubAuthenticator,
googleAuthenticator,
} from "../../controllers";

const router = express.Router();

router.post("/signup", authSignupValidator, signup);
router.post("/login", login);
router.post("/refresh_token", authRefreshTokenValidator, refreshToken);
router.post("/github", githubAuthValidator, githubAuthenticator);
// router.post("/github", githubAuthValidator, githubAuthenticator);
router.post("/google", googleAuthValidator, googleAuthenticator);

export default router;
6 changes: 6 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ declare global {
iss: string;
}

export interface GoogleCredentialDecoded {
name: string;
email: string;
sub: string;
}

export interface ModifiedRequest extends Request {
isAuthenticated: boolean;
userId: number;
Expand Down
36 changes: 23 additions & 13 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import { NextFunction } from 'express';
import JWT from 'jsonwebtoken';
import { NextFunction } from "express";
import JWT from "jsonwebtoken";

export const generateJWT = (
userId: number,
email: string,
tokenType: 'access' | 'refresh'
tokenType: "access" | "refresh"
): string => {
try {
let secretVar: string;
let expiresIn: string | undefined;
switch (tokenType) {
case 'access':
secretVar = 'ACCESS_SECRET';
expiresIn = '1d';
case "access":
secretVar = "ACCESS_SECRET";
expiresIn = "1d";
break;
case 'refresh':
secretVar = 'REFRESH_SECRET';
expiresIn = '1y';
case "refresh":
secretVar = "REFRESH_SECRET";
expiresIn = "1y";
break;
}

const secret: string = process.env[secretVar] as string;
const payload = { email };
const options = {
expiresIn,
issuer: 'trustclaims.whatscookin.us',
audience: String(userId)
issuer: "trustclaims.whatscookin.us",
audience: String(userId),
};

const token = JWT.sign(payload, secret, options);
Expand All @@ -49,7 +49,7 @@ export const passToExpressErrorHandler = (err: any, next: NextFunction) => {
if (!err.statusCode) {
err.statusCode = 500;
console.log(err.message);
err.message = 'Could not process the request, check inputs and try again';
err.message = "Could not process the request, check inputs and try again";
}
next(err);
};
Expand All @@ -74,7 +74,7 @@ interface Mapping {

// handle common mis-keys
const SIMILAR_MAP: Mapping = {
howKnown: { website: 'WEB_DOCUMENT', WEBSITE: 'WEB_DOCUMENT' }
howKnown: { website: "WEB_DOCUMENT", WEBSITE: "WEB_DOCUMENT" },
};

export const poormansNormalizer = (obj: { [key: string]: any }) => {
Expand All @@ -92,3 +92,13 @@ export const poormansNormalizer = (obj: { [key: string]: any }) => {
export const makeClaimSubjectURL = (claimId: string) => {
return `https://live.linkedtrust.us/claims/${claimId}`;
};

export const decodeGoogleCredential = (accessToken: string) => {
const { name, email, sub } = JWT.decode(accessToken) as GoogleCredentialDecoded;

return {
name,
email,
googleId: sub
};
};

0 comments on commit 3e7c4d5

Please sign in to comment.