Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passport & JWT & Google/Facebook Strategy - How do I combine JWT and Google/Facebook Strategy?

Tags:

This question is for anyone who is familiar with

  • Node.js
  • Express
  • Passport
  • JWT Authentication with passport (JSON Web Tokens)
  • Facebook OAuth2.0 OR Google OAuth2.0

I have been doing some online courses and understand how to do the two following things:

  1. Authentication using Passport Local Strategy + JWT Tokens
  2. Authentication using Passport Google/Facebook Strategy + Cookie/sessions.

I am trying to combine the content from these two courses basically. I want to use Google Strategy + JWT Authentication. I want to use JWT instead of cookies because my app is going to be a web/mobile/tablet app, and I need to be accessing the api from different domains.

There are two issues I am having with this: To kick off the Google/facebook OAuth pipelines, you need to call either '/auth/facebook' or '/auth/google'. Both Oauth flows work basically the same so when I say '/auth/google' from now on, I am referring to either. Now the issue I'm having is: On the client, do I call the '/auth/google' route with a href button link or an axios/ajax call? If I use the href or axios/ajax approach I am still getting problems with both solutions.

The href approach problem: When I assign an <a> tag with a href to '/auth/google' the authentication works perfectly fine. The user gets pushed through the Google Auth flow, they log in and the '/auth/google/callback' route gets called. The problem I have now is how do I correctly send the JWT token back to the client from '/auth/google/callback'?

After a lot of googling I have seen that people have simply passed the the JWT back to the client from the oauth callback in the redirect query param. For example:

res.redirect(301, `/dashboard?token=${tokenForUser(req.user)}`); 

The issue I have with this is that now the the ability to authenticate is saved in my browser history! I could log out (destroying the token saved in localStorage), and then simply look at my browser url history, go back to the url that contains the token in the query param, and I would automatically log in again without having to go through the Google Strategy! This is a huge security flaw and is obviously the incorrect way to approach it.

The axios/ajax approach problem: Now before I explain the problem with this issue, I know for sure that If I get this working, it will solve all issues I was having with the previous href problem. If I manage to call '/google/auth' from an axios.get() call and receive the JWT in the response body, I will not be sending the token as url param, and it will not get saved in the browser history! Perfect right? well there is still some problems with this approach :(

When try to call axios.get('/auth/google') I get the following error:

enter image description here

How I've tried to solve the problem:

  • I installed cors to my npm server, and added app.use(cors()); to my index.js.
  • I took a stab and added "http://localhost:3000" to the "Authorised JavaScript origins" in Google developer console.

Neither of these solutions solved the issue, so now I really feel stuck. I want to use the axios/ajax approach, but I'm not sure how to get past this cors error.

Sorry for such a long message, but I really felt I had to give you all the information in order for you to properly help me.

Thanks again, looking forward to hear from you!

like image 450
Vaderico Avatar asked Sep 24 '17 06:09

Vaderico


People also ask

How long do passport last Singapore?

From 1 Oct 2021, Singapore passports issued for citizens aged 16 and above are valid for 10 years. For more information, browse the FAQs. For citizens below the age of 16, the passport validity is 5 years.

How fast can I get my passport Singapore?

Currently, the average waiting time for passport processing is at least six weeks from the time of application. It could take even longer if there is a greater surge in the number of applications or there are issues with the application such as the photograph submitted does not meet the requirements.

How long will my passport take?

The vast majority of all passport applications are being dealt with well within 10 weeks. However, a passport can only be issued once all the checks have been completed satisfactorily and will take longer if applications are submitted with missing or incomplete information.

How much to make Singapore passport?

The passport application fee will remain unchanged at S$70. For applications submitted in person at Singapore's overseas missions, an equivalent of S$80 in foreign currency will be charged.


2 Answers

I solved this in this way:

  1. On Front-End (can be mobile app) I made login request to Google (or Facebook) and after the user selected his account and logged in I got back response that contained google auth token and basic user info.
  2. Then I sent that google auth token to backend where my API sent one more request to the Google API to confirm that token. (See step 5)
  3. After successful request comes you get basic user info and e-mail. At this point, you can assume that user login via Google is good since google check returned that it's okay.
  4. Then you just signup or login user with that email and create that JWT token.
  5. Return token to your client and just use it for future requests.

I hope it helps. I implemented this multiple times and it showed like a good solution.

like image 76
vedran Avatar answered Oct 01 '22 10:10

vedran


Though there is good answer, I wanted to add more information with example.

  • Passport's google/facebook strategy is session based, it stores user info in cookie which is not advisable. So we need to disable it first

To disable session we need modify our redirect router. For example if we have redirect path /google/redirect like following, we need to pass { session: false } object as parameter.

router.get('/google/redirect', passport.authenticate('google', { session: false }), (req, res)=> {     console.log(":::::::::: user in the redirect", req.user);     //GENERATE JWT TOKEN USING USER     res.send(TOKEN); }) 

So where does this user come from? This user comes from passport's callback function. In the previous snippet we have added passport.authenticate(....) This middlewire initiates passport's google-strategy's callback which deals with the user. For example

passport.use(     new GoogleStrategy({         callbackURL: '/google/redirect',         clientID: YOUR_GOOGLE_CLIENT_ID         clientSecret: YOUR_GOOGLE_SECRET_KEY     },      (accessToken, refreshToken, profile, done)=>{         console.log('passport callback function fired');          // FETCH USER FROM DB, IF DOESN'T EXIST CREATE ONE          done(null, user);      }) ) 

That's it. We have successfully combined JWT and Google/Facebook Strategy.

like image 45
Ramjan Ali Avatar answered Oct 01 '22 10:10

Ramjan Ali