0

I'm building a single page application front end with react that talks to a ruby on rails backend. I'm using devise and omniauth for user authentication and I'm trying to sign in with my google account.

I followed the instructions here (https://developers.google.com/identity/gsi/web/guides/client-library) and here (https://developers.google.com/identity/gsi/web/tools/configurator) and I have the sign in with google button running on my home page. When you click on it, you select your google account, and it successfully POSTs to the correct omniauth callback address.

The problem is it throws an ActionController::InvalidAuthenticityToken exception with the message "Can't verify CSRF token authenticity." I know this is because rails automatically injects a CSRF token into forms that are rendered, but in this case it's being sent by a javascript call from an external library. How do I send the token?

I am including the following script tag on my application.html.erb file as instructed by the docs I previously posted.

<script src="https://accounts.google.com/gsi/client" async defer></script>

I made the following react app that places the sign in with google button.

import React from 'react';

const SignInWithGoogle = () => {
  return (
    <div className='sign-in-with-google'>
      <div id="g_id_onload"
          data-client_id="xxxxx.apps.googleusercontent.com"
          data-context="signup"
          data-ux_mode="popup"
          data-login_uri="http://localhost:3000/users/auth/google_oauth2/callback"
          data-auto_prompt="false">
      </div>

      <div className="g_id_signin"
          data-type="standard"
          data-shape="rectangular"
          data-theme="outline"
          data-text="signin_with"
          data-size="large"
          data-logo_alignment="left">
      </div>
    </div>
  );
};

export default SignInWithGoogle;

ruby version: 3.2.2

rails version: 7.0.4.3

devise gem 4.9.2

omniauth gem 2.1.1

omniauth-google-oauth2 gem 1.1.1

StaticMethod
  • 593
  • 1
  • 7
  • 20
  • 1
    why does your rails back end have a form? Should be an api. – dbugger May 04 '23 at 11:07
  • The rails application is serving both the back end and the front end even though the front end is using react router to handle all the front end traffic. Ultimately I'll probably put all the static assets behind a cdn. – StaticMethod May 04 '23 at 22:56
  • APIs can't verify CSRF by default. How are you disabling CSRF checking for the API side? – Chiperific May 06 '23 at 17:54

1 Answers1

0

API endpoints can't verify CSRF tokens by default. The React FE is cross-site, the SSO response is also cross-site.

In my hybrid apps, I tend to disable CSRF selectively for all api endpoints:

  # Disable CSRF protection on urls that start with /api/v1/
  skip_before_action :verify_authenticity_token, if: :api_endpoint?

You'll need to disabled it in the OmniauthCallbacksController at least.

Chiperific
  • 4,428
  • 3
  • 21
  • 41