I followed this railcasts tutorial on how to implement Omniauth-identity but hit a snag.
When I try to register the user the following error pops up
ActionController::InvalidAuthenticityToken in SessionsController#create
In the console logs the following error pops up
Processing by SessionsController#create as HTML
Parameters: {"name"=>"asdasd asdasd", "email"=>"asd#yopmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "provider"=>"identity"}
Can't verify CSRF token authenticity
The user is inserted in the Identity model without problems but when the application tries to create a session it is all for naught.
Here is the relevant code I am using
Gemfile
OpenID Authentication
gem 'bcrypt-ruby', '~> 3.1.2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-google-oauth2'
gem 'omniauth-identity'
initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET']
provider :identity
end
routes
get 'auth/:provider/callback', to: 'sessions#create'
post 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
SessionsController
def create
user = User.from_omniauth(env['omniauth.auth'])
session[:user_id] = user.id
redirect_to root_url, notice: "Signed In!"
end
Users model
def self.from_omniauth(auth)
find_by_provider_and_uid(auth["provider"], auth["uid"]) || create_with_omniauth(auth)
end
The error InvalidAuthenticityToken raised when Rails check the CSRF token, you can disable CSRF protection on controller by skipping the verification skip_before_action, add to the top of your SessionsController:
skip_before_action :verify_authenticity_token, only: :create
But you must be careful and read all about the CSRF protection.
This solved my problem.
Quoting as it is from the source:
I just spent quite some time debugging this. In my case, I was following an auth0 tutorial that instructed to generate a link with <%= button_to "Login", "auth/auth0", method: :post %>. I was banging my head to a wall for a long time because of the InvalidAuthenticityToken exception.
Turns out that the path had to be "/auth/auth0" (slash in the beginning) for rails to correctly compare the path. Shrug. Maybe this helps someone else. Not sure if this is actually a Rails bug.. it seems at least little unfriendly.
Related
OK i'm not really a ROR person but I'm trying to modify an existing app (forked) from https://github.com/adamcooke/staytus
there's an /admin page which right now brings you to a haml login form with a username/password box.
What I'm attempting to do us change this functionally so that when /admin is hit devise and omniAuth will redirect to my IDP via OpenIDConnect ask the user to login with their creds, do the auth stuff and pending they get through then show the admin section...
here's what I've done thus far:
installed these gems
gem 'devise'
gem 'omniauth-rails_csrf_protection'
gem 'omniauth-azure-activedirectory-v2'
ran the devise config/install:
added config.rb
def omniauth_oidc?
result = ENV['OMNIAUTH_OIDC'] == '1'
puts "omniauth_oidc? result: #{result}"
I've tried all combinations of routes:
devise_scope :user do
devise_for :users, controllers: { omniauth_callbacks: 'admin/omniauth_callbacks' }
end
devise_scope :user do
get '/admin/omniauth_callbacks' => 'admin/omniauth_callbacks#azure_activedirectory_v2'
end
namespace :admin do
get '/omniauth_callbacks', to: 'omniauth_callbacks#azure_activedirectory_v2'
end
result
end
I've also tried " to: 'sessions#create'" routes but clearly I'm missing something here...
added OmniauthCallbacksControler
class Admin::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def azure_activedirectory_v2
puts "request.env['omniauth.auth']: #{request.env['omniauth.auth'].inspect}"
response_params = request.env['omniauth.auth']
if response_params.nil?
Rails.logger.error("request.env['omniauth.auth'] is nil")
raise "request.env['omniauth.auth'] is nil"
else
response_params = response_params['info']
end
#user = User.find_by!(email: response_params['email'])
if #user&.persisted?
sign_in_and_redirect #user, event: :authentication, location: admin_root_path
else
flash[:danger] = 'You have not yet an account!'
redirect_back(fallback_location: admin_root_path)
end
end
end
added omniauth.rb initializer
Rails.application.config.middleware.use OmniAuth::Builder do
provider :developer if Rails.env.development?
provider :azure_activedirectory_v2,
{
client_id: ENV[''],
client_secret: ENV[''],
tenant_id: ENV[']
}
end
given all of the above I still haven't gotten /admin to redirect to my IDP login ? WHY ?
So I'm trying to configure Rails with Google oauth via devise, i have followed official docs described here. After everything i get this error when clicking the google signup button
Access to fetch at 'url' (redirected from 'http://localhost:3000/users/auth/google_oauth2') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Googling around i found you need to enable CORS, naturally i did just that
in my application.rb in added this
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :patch, :put]
end
end
This is my callbacks controller
class Users::CallbacksController < Devise::OmniauthCallbacksController
skip_before_action :verify_authenticity_token
def google_oauth2
admin = User.from_omniauth(from_google_params)
redirect_to root_path
end
private
def from_google_params
#from_google_params ||= {
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image,
is_member: false
}
end
def auth
#auth ||= request.env['omniauth.auth']
end
end
EDIT
So after alot of trial n errors i have it working, kinda. So when i click the signup with google it still throws an error,
But, when clicking the link in the google console it successfully goes there, any ideas ?
Try this setup with devise at master branch and gem omniauth-rails_csrf_protection
devise.rb
config.omniauth :google_oauth2, "API_KEY", "API_SECRET"
routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
user.rb
devise :omniauthable, omniauth_providers: [:google_oauth2]
app/controllers/users/omniauth_callbacks_controller.rb:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.from_omniauth(request.env['omniauth.auth'])
if #user.persisted?
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect #user, event: :authentication
else
session['devise.google_data'] = request.env['omniauth.auth'].except('extra') # Removing extra as it can overflow some session stores
redirect_to new_user_registration_url, alert: #user.errors.full_messages.join("\n")
end
end
end
user.rb
def self.from_omniauth(access_token)
data = access_token.info
user = User.where(email: data['email']).first
unless user
user = User.create(
email: data['email'],
password: Devise.friendly_token[0,20])
end
user
end
gemfile:
gem "devise", github: "heartcombo/devise", branch: "master"
gem "omniauth-rails_csrf_protection"
gem "omniauth-google-oauth2"
view:
<%= link_to "Sign in with Google", user_omniauth_authorize_path(:google_oauth2), method: :post %>
I am currently developing a website and i have a problem with te confirmation link with devise token auth.
Everything is working right, after someones registers they get an email with a confirmation link. This link is confirming and working properly BUT when this link expires (i set it up in the configuration with config.confirm_within = 1.day ) or someone clicks this link again they get a "Routing error". So i suppose there should be a way of redirecting to the homepage when that link expires and maybe showing a message saying that they have to ask for the email confirmation again..
i have this confirmation routes:
new_api_user_confirmation GET /api/auth/confirmation/new(.:format) devise_token_auth/confirmations#new
api_user_confirmation GET /api/auth/confirmation(.:format) devise_token_auth/confirmations#show
POST /api/auth/confirmation(.:format) devise_token_auth/confirmations#create
I use the last route POST for resending the email and it is working, but the other to routes are not working and that makes sense because i am using API. But there should be a redirect url for when you get an error
Any thoughts? thank you in advance
you can override the DeviseTokenAuth::ConfirmationsController#show and redirect to root_path
DeviseTokenAuth ConfirmationsController#show
class ConfirmationsController < DeviseTokenAuth::ConfirmationsController
def show
...
else
# raise ActionController::RoutingError, 'Not Found'
redirect_to :root_path
end
...
in routes
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
# confirmations: 'devise_token_auth/confirmations',
confirmations: 'confirmations',
devise-token-auth docs
I'm using Rails 5. I'm using the Omniauth gem (but not Devise) for authentication with the following sites (from my Gemfile) ...
gem 'omniauth-oauth2', '~> 1.3.1'
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-linkedin-oauth2'
I have links on my page that look like
<%= link_to image_tag("google_plus_icon.jpg", :height => 50, :border => 0, :alt => 'Google', :title => 'Google', :class => 'loginImg'), '/auth/google' %>
My question is, right before the authentication sequence begins with the external service, I would like to catch the HTTP Referer header in my session. I would like to record this when the user clicks on the link but before the authentication sequence begins. How do I do that?
I think your best bet here would be to do a few things:
Without Devise
I would add a block that will run during the setup phase for your strategy. You'll need to add this to every strategy you want to configure.
https://github.com/omniauth/omniauth/wiki/Setup-Phase
SETUP_PROC = lambda do |env|
request = Rack::Request.new(env)
session = request.env['rack.session']
session[:preauth_referrer] ||= request.referrer
end
use OmniAuth::Builder.new do
provider :google, :setup => SETUP_PROC
end
You'll probably need to restart your application server after changing the configuration code.
With Devise
Override the OmniauthCallbacksController if you haven't already
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
# Then in routes.rb, as detailed at https://github.com/plataformatec/devise/wiki/omniauth:-overview
devise_for :users, controllers: { omniauth_callbacks: 'omniauth_callbacks' }
Add a before_filter in the new controller you just created. The passthrough method is used by the /auth/:provider endpoint by default.
prepend_before_action :store_referrer, only: [:passthrough]
Store the referrer in the session. This is necessary because you haven't authenticated your user yet
session[:preauth_referrer] = request.referrer
So the full controller would look something like the following:
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
prepend_before_filter :store_referrer, only: [:passthrough]
# Other overrides go here, for example overriding the callback methods
private
def store_referrer
session[:preauth_referrer] = request.referrer
end
end
Then when the user comes back from the authentication redirect you can associate the referrer with the user in persistent storage if you like.
As a footnote, I would recommend using the rails route url helpers instead of referencing the path directly, so something like this:
<%= link_to image_tag("google_plus_icon.jpg", :height => 50, :border => 0, :alt => 'Google', :title => 'Google', :class => 'loginImg'), user_omniauth_authorize_path(provider: :google) %>
I am using omniauth-facebook gem to authorize using facebook in my rails application.
I have followed these instructions but the problem I am facing is error about invalid credentials:
(facebook) Authentication failure! invalid_credentials: OAuth2::Error, :
{"error":{"message":"Error validating application. Invalid application ID.","type":"OAuthException","code":101}}
What is weird about this is that I am getting user info even though I get this error from facebook api.
the value of request.env['omniauth.auth']
is(server log).
#<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash expires=true
expires_at=1421256863 token="some_long_value"> extra=#<OmniAuth::AuthHash
raw_info=#<OmniAuth::AuthHash education=[#<OmniAuth::AuthHash school=
#<OmniAuth::AuthHash id="174179219354091" name="Udacity"> type="College">]
email="ashish#gmail.com" favorite_athletes=[#<OmniAuth::AuthHash id="51926382304"
name="Derrick Rose">, #<OmniAuth::AuthHash id="344128252278047" name="Sachin
Tendulkar">,.... so on
routes.rb
devise_for :users, :controllers => {:omniauth_callbacks => "omniauth_callbacks"}
config/initializers/omniauth.rb
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'key', 'secret', {:provider_ignores_state => true}
# key and secret are correctly added in above line
end
app/model/user.rb
devise :omniauthable, :omniauth_providers => [:facebook]
app/controller/omniauth_callback_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
omniauth = request.env['omniauth.auth']
# Other code to create authentication and other logic
puts "===>>> Omniauth is #{omniauth}"
end
def failure
res = request.env['omniauth.auth']
puts "======>>>>>> Authentication failed #{res}"
redirect_to root_path
end
end
Every time response goes to failure method but not to facebook method.
What I don't understand is when I am getting invalid credentials error from api then how come I get all the data from facebook. I doubt I have something wrong on my end while handling the callback from facebook.
Can anyone point where the problem can be?
I am pretty sure I am using correct application id and key I am getting data from facebook in the response.
Can anybody help me with this issue?