spencercdixon
spencercdixon

Reputation: 232

Client side OAuth with google calendar api using React frontend and Rails backend

So I'm trying to do google oauth to get a refresh token for my users (not actually using google oauth to save the user). I had everything working when I used the client side OAuth for google api but they don't provide a refresh token when you do that handshake, only an access_token. I need a persisted refresh_token since I'm going to be making a lot of requests to the users google calendars.

So I set up omniauth on my rails server to make the flow go like this:

user clicks authenticate with google (client side) -->

popup screen goes to backend server (localhost:3001/users/auth/google_oauth2) -->

backend rails server redirects to google for authentication -->

they authenticate with google and get redirected to backend server's callback (localhost:3001/users/auth/google_oauth2/callback) -->

backend server saves token for appropriate user and then redirects back to client side app on localhost:3000 (nothing needs to be done on client, just need the token saved on my server for future use)

I do however need to know that the authentication was successful so I can dispatch appropriate actions in react/redux. In redux-auth they check for the access_token inside the popup.location URI. Problem is when I use this server side popup flow I get this nasty http/https error:

SecurityError (original image: https://i.sstatic.net/CSokt.jpg)

If instead of redirecting back to the client I just redirect to a view in my backend server I could then have a script on that page that just does window.close() which works but seems hacky to me. Another potential solution I was thinking was to try and use the window.postMessage api but I don't know if that has great browser support/also seems hacky. I could emit a message to the other window (the main client app) from the popup saying the oauth was successful so my react code and do whatever it needs to do.

I feel like I'm just approaching this whole flow completely wrong or I'm missing something obvious.

I also feel like if I just had HTTPS on everything it would all work since before when it was 100% client side the popup worked beautifully and I didn't get this SecurityError. I spent some time figuring out how to get my webpack dev server using https and tried doing the same with rails (think I did something wrong on the rails side) but it was still not working. Also feel like I shouldn't need to force HTTPS on all my development servers in order to get it working...

If anyone has any thoughts or could give me some direction that would be much appreciated!!

Upvotes: 3

Views: 3216

Answers (1)

Jazib
Jazib

Reputation: 1230

You are approaching this the wrong way. Google's authentication and their APIs do have confusing documentation. I was also stuck with similar situation and after spending considerable time, I found the right way to do this.

From your question, I believe this seems like the relevant link: https://developers.google.com/identity/sign-in/web/server-side-flow

And following it, here is how your flow should look like:

enter image description here

To map it on your problem, this is what you will do:

  1. user clicks authenticate with google (client side)
  2. Client requests Google for authorization that includes your scopes and receives a one time authorization code.
  3. Client Sends this authorization code to your ruby server.
  4. Ruby server uses the authorization code to exchange it with access_token and persisted refresh_token which you shall use in your subsequent requests to google apis.

Hope it helps.

Upvotes: 3

Related Questions