I'm trying to build a simple app that is just using a GitHub login for authentication for now. I am using Rails v5.2.3 for the backend, and React for the frontend. I currently have a button in my Root Component that sends an ajax request to my backend. That request will hit an action in my SessionsController
that will redirect to the /auth/github
route and begin the GitHub auth cycle.
I believe this is step is where I am getting an error.
My browser console gives me this error message:
Access to XMLHttpRequest at 'https://github.com/login/oauth/authorize?
client_id=db494fb7eadbc0c6129d&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fgithub%2Fcallback&resp
onse_type=code&state=79557eda02a2340f9c02b5254f053528314ea750704690ae' (redirected from
'http://localhost:3000/authenticate/github') from origin 'http://localhost:3000' has been blocked by CORS
policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here are some files that I believe are relevant:
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.5.1'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.3'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'omniauth-github', github: 'omniauth/omniauth-github', branch: 'master'
gem 'figaro'
gem 'rack-cors'
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem 'better_errors'
gem 'binding_of_caller'
gem 'pry-rails'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
gem 'chromedriver-helper'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
routes.rb
Rails.application.routes.draw do
get '/authenticate/:type', to: 'sessions#authenticate'
get '/auth/:provider/callback', to: 'sessions#create'
root to: 'static_pages#root'
end
initializers/github.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET']
end
sessions_controller.rb
class SessionsController < ApplicationController
def authenticate
redirect_to '/auth/github' if params[:type] == 'github'
end
def create
@user = User.find_or_create_from_oauth(auth_params)
if @user
render json: @user
else
render json: [params['error']], status: 422
end
end
private
def auth_params
request.env['omniauth.auth']
end
end
root.jsx
import React, { useState } from 'react';
import axios from 'axios';
const Root = () => {
const [name, setName] = useState('no name yet');
const githubLogin = () => {
axios.get('authenticate/github')
.then(user => setName(user.name));
}
return (
<div>
<button onClick={githubLogin}>Github Login</button>
<h1>Name: {name}</h1>
</div>
)
}
export default Root;
After a little research I saw some recommendations of adding the rack-cors
gem. I tried doing that and added this initializer.
initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
puts 'setting up cors'
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :patch, :put]
end
end
I'm pretty new when it comes to setting up oauth and am trying to figure it out, but this has me stumped. I'm not sure if my redirect is getting the Headers it needs to not get blocked, and I'm sure on where to go from here.
Any help would be appreciated. Please let me know if there is any other info that I can provide. Thank you.
You're getting the error because redirect happens in the context of the XHR.
One solution would be to make XHR to your controller and it would return a URL the client has to follow to.
Another would be to not make an XHR and use a plain link to your action.
Either way, you should make sure that you don't request GitHub URL from JS. It has to be a plain HTTP(s) request.