Answers · Keys & Services

Why does my OAuth sign-in button do nothing when clicked?

The content security policy is blocking the navigation. form-action covers the whole redirect chain a form starts, so the provider's host must be listed in config/initializers/content_security_policy.rb. The form also needs data-turbo="false", or Turbo submits it by fetch and the cross-origin redirect is blocked as an XHR instead.

Why there is no error

This is the part that wastes the afternoon. A blocked form action produces no exception, no flash, no failed request in the network tab and nothing in the Rails log. The browser simply declines to navigate. The only evidence is a console warning, which is easy to miss if the console is noisy.

Both conditions have to hold

The host has to be in form-action. Not connect-src, not default-src. form-action applies to the entire navigation the form begins, including every redirect along the way, so an OAuth flow that bounces through two hosts needs both listed.

The form needs data-turbo="false". Turbo checks the form and the submit button, so either works. Without it, Turbo intercepts the submission and issues a fetch, which turns a navigation into an XHR, which connect-src then blocks. Same dead button, different rule.

Fix and pin

bin/rspec spec/requests/content_security_policy_spec.rb spec/requests/cross_origin_forms_spec.rb

Both specs exist so this failure cannot come back silently. Add the host to config/initializers/content_security_policy.rb, add the example to spec/requests/content_security_policy_spec.rb, and the next person who tightens the policy gets a red build instead of a broken sign-in button.

The same trap, three other places

Any redirect off-site has this shape. Stripe's hosted checkout, the Stripe billing portal, and any third-party consent screen all need the host in form-action and the form marked data-turbo="false". If one of those buttons stops working after a policy change, this is why.

Check the console before anything else

Open devtools, click the button, and read the one console line. It names the directive and the blocked URL, which turns a guess into a two-minute fix. That line is the entire diagnostic, and it is the only place the failure is visible.

Related questions

How do I add sign in with Google to a Rails app?

Create an OAuth 2.0 client in Google Cloud Console, add your callback URL as an authorized redirect URI, and set the client id and secret. One Shot already has the OmniAuth callback route and the user upsert, so no code changes. Google's host also has to be in the content security policy's form-action list.

Why does sign in with Apple need a paid developer account?

The client id and private key come from the Apple Developer Program, which is a paid membership at 99 dollars a year. There is no free tier for issuing Sign in with Apple credentials. Google's OAuth client is free, so if you only want one social provider to start, Google is the one with no standing cost.

Do I need API keys to run a Rails starter kit locally?

No. Billing, email, bot checking and error reporting each sit behind an adapter that returns a real client when its credential is present and a deterministic local fake when it is not. A fresh clone runs bin/setup and bin/dev with no keys, and checkout, sign-in and gated features all work end to end.