Can you explain the login flow of the app for me. I am a little bit confused of how to create login with Google from React and Nodejs like this app
Login is processed by passport.js. When you click Login with Google button, you move to '/auth/google' page which uses passport-google-auth package.(look server/config/routes.js#L28) This package sends authentication object to Google. Then, Google responds and redirects you to '/auth/google/callback', which uses passport-strategy(see server/config/passport/google and server/db/mongo/passport/google) Then server now has user info in req.user and you are logged in.
Hey, i want to add a question to this if i may.
Looking at https://github.com/reactGo/reactGo/blob/master/server/db/mongo/passport/google.js#L6
I see the if (req.user), but when i'm trying to log in through google, not ever i got inside if the... whats it for? Am i missing something?
@slavab89 you can find the answer commented in config/passport/google
OAuth Strategy taken modified from https://github.com/sahat/hackathon-starter/blob/master/config/passport.js
- User is already logged in.
- Check if there is an existing account with a provider id.
- If there is, return an error message. (Account merging not supported)
- Else link new OAuth account with currently logged-in user.
- User is not logged in.
- Check if it's a returning user.
- If returning user, sign in and we are done.
- Else check if there is an existing account with user's email.
- If there is, return an error message.
- Else create a new account.
Normally this check if a user is already logged in with local strategy (username + password) and is trying to login with google.
In my app, since I only have google (youtube) login, i've completely removed this if statement and its contents.
Thanks! i'm also using only google login so i'll remove this piece of code :D :D
Also, if anyone stumbles upon this issue and thinks:
"Hey, i have some login flow that's working and all is great, but how do i handle errors?
If a user tries to login to the app through google / facebook / twitter passport but i want to block him for whatever reason (say he's not in the db or i didnt authorize him yet), how do i do that?"
Well... I've looked pretty hard for this and apparently you can do the following (its not in the passport docs or example!!! no idea why)
app.get('/auth/google', passport.authenticate('google', {
scope: ['openid email profile'],
prompt: 'select_account' // This actually always makes you choose the account that you want to login with, can be handy sometimes
}));
app.get('/auth/google/callback',
passport.authenticate('google', { failWithError: true }),
(req, res, next) => { // Will get here if its a successful login
res.redirect('/');
},
(err, req, res, next) => { // Will get here if you though an error
res.redirect('/?loginError=' + encodeURIComponent(err));
}
);
The magic is the failWithError that's passed.
When its turned on, it will not throw you out or redirect you to some unknown location,
it will just fall back to the next middleware that in this case is an express error handler.
This signature of the error handler is mandatory,
express will not consider this a error handler function if it wont have this signature.
On a successful it would pass to the regular next middleware that just redirects you or does whatever.
Using this method gives you the ability to not only redirect to a different location but also pass additional data though query params that you can later use for showing the exact error that occurred.
If query params is a problem then its also possible to store some data on the session and then the front can access this data.
We're cleaning the project of stale issues therefore i'm closing this. If you still have any issue, please comment here or open a new issue.
Most helpful comment
Thanks! i'm also using only google login so i'll remove this piece of code :D :D
Also, if anyone stumbles upon this issue and thinks:
"Hey, i have some login flow that's working and all is great, but how do i handle errors?
If a user tries to login to the app through google / facebook / twitter passport but i want to block him for whatever reason (say he's not in the db or i didnt authorize him yet), how do i do that?"
Well... I've looked pretty hard for this and apparently you can do the following (its not in the passport docs or example!!! no idea why)
The magic is the failWithError that's passed.
When its turned on, it will not throw you out or redirect you to some unknown location,
it will just fall back to the next middleware that in this case is an express error handler.
This signature of the error handler is mandatory,
express will not consider this a error handler function if it wont have this signature.
On a successful it would pass to the regular next middleware that just redirects you or does whatever.
Using this method gives you the ability to not only redirect to a different location but also pass additional data though query params that you can later use for showing the exact error that occurred.
If query params is a problem then its also possible to store some data on the session and then the front can access this data.