-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Implement Google Oauth login #2278
base: develop
Are you sure you want to change the base?
Feature: Implement Google Oauth login #2278
Conversation
scope: ["email"], | ||
state: redirectURL, | ||
})(req, res, next); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- can we remove the
else
block here? as we're doing an early return above?
try { | ||
const redirectUrl = new URL(req.query.state); | ||
|
||
if (`.${redirectUrl.hostname}`.endsWith(`.${rdsUiUrl.hostname}`)) { | ||
// Matching *.realdevsquad.com | ||
authRedirectionUrl = redirectUrl; | ||
} else { | ||
logger.error(`Malicious redirect URL provided URL: ${redirectUrl}, Will redirect to RDS`); | ||
} | ||
} catch (error) { | ||
logger.error("Invalid redirect URL provided", error); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- do we need a try catch here?
return passport.authenticate("google", { session: false }, async (err, accessToken, user) => { | ||
if (err) { | ||
logger.error(err); | ||
return res.boom.unauthorized("User cannot be authenticated"); | ||
} | ||
const userData = { | ||
email: user.emails[0].value, | ||
created_at: Date.now(), | ||
updated_at: null, | ||
}; | ||
|
||
const userDataFromDB = await users.fetchUser({ email: userData.email }); | ||
|
||
if (userDataFromDB.userExists) { | ||
if (userDataFromDB.user.roles.developer === true) { | ||
const errorMessage = encodeURIComponent("Google login is restricted for developer role."); | ||
return res.redirect(`${authRedirectionUrl}?error=${errorMessage}`); | ||
} | ||
} | ||
|
||
const { userId, incompleteUserDetails } = await users.addOrUpdate(userData); | ||
|
||
const token = authService.generateAuthToken({ userId }); | ||
|
||
const cookieOptions = { | ||
domain: rdsUiUrl.hostname, | ||
expires: new Date(Date.now() + config.get("userToken.ttl") * 1000), | ||
httpOnly: true, | ||
secure: true, | ||
sameSite: "lax", | ||
}; | ||
|
||
res.cookie(config.get("userToken.cookieName"), token, cookieOptions); | ||
|
||
if (incompleteUserDetails) authRedirectionUrl = "https://my.realdevsquad.com/new-signup"; | ||
|
||
return res.redirect(authRedirectionUrl); | ||
})(req, res, next); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- let's move the logic to a different function instead of adding it inside the callback function of the
passport.authenticate
method.
github_created_at: Number(new Date(user._json.created_at).getTime()), | ||
github_user_id: user.id, | ||
created_at: Date.now(), | ||
updated_at: null, | ||
}; | ||
|
||
if (userData.email === null) { | ||
const res = await fetch("https://api.github.com/user/emails", { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- let's move the base path (https://api.github.com) inside an env variable, to allow it to be configurable for different environments if the situation arises.
github_created_at: Number(new Date(user._json.created_at).getTime()), | ||
github_user_id: user.id, | ||
created_at: Date.now(), | ||
updated_at: null, | ||
}; | ||
|
||
if (userData.email === null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- this will also check for undefined along with null.
if (userData.email === null) { | |
if (!userData.email) { |
if (user && !user.empty && user.docs !== null) { | ||
await userModel.doc(user.docs[0].id).set({ ...userData, updated_at: Date.now() }, { merge: true }); | ||
const { created_at: createdAt, ...updatedUserData } = userData; | ||
await userModel.doc(user.docs[0].id).set({ ...updatedUserData, updated_at: Date.now() }, { merge: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- can
user.docs
be empty? if yes are we handling that case?
user = await userModel.where("github_id", "==", userData.github_id).limit(1).get(); | ||
} | ||
|
||
if (userData.email && (!user || (user && user.empty))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- if we're already doing a
!user
check do we need to do(user && user.empty))
can we just do!user || user.empty
?
@@ -9,6 +9,10 @@ | |||
|
|||
router.get("/github/callback", auth.githubAuthCallback); | |||
|
|||
router.get("/google/login", auth.googleAuthLogin); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
authorization
@@ -9,6 +9,10 @@ | |||
|
|||
router.get("/github/callback", auth.githubAuthCallback); | |||
|
|||
router.get("/google/login", auth.googleAuthLogin); | |||
|
|||
router.get("/google/callback", auth.googleAuthCallback); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Date: 02/12/2024
Developer Name: Utkarsh Bansal
Issue Ticket Number
#2216
Description
If the person is a developer they have to login via GitHub but a non developer should be able to login by their Google Account.
Documentation Updated?
Under Feature Flag
Database Changes
Breaking Changes
Development Tested?
Screenshots
Screenshot 1
google-login-test-local.mp4
Test Coverage
Screenshot 1
Additional Notes
Need to generate oauth credentials for staging as well as prod from google cloud console.