I'm using omniauth without devise for authentication, as I like it's simplicity. In addition to omniauth-facebook I use omniauth-identity to offer email/pw-authentication.
The railscast on omniauth-identity describes how to setup a customized registration and login page. But the default routes supplied by identity (/auth/identity and /auth/identity/register) are still accessible.
I would like to have these under my control, as I want only want to let invited users register. Is there any way to override those routes supplied by a rack middleware?
Trying to just
match "/auth/identity", to: "somewhere#else"
doesn't do the trick!
Is there maybe a configuration to turn these default routes off? The documentation isn't giving any details on this...
Unfortunately I'm fairly new to Rack, so I don't have enough insight yet, to solve this issue on my own!
I'd be glad, if someone could point me in the right direction!
An OmniAuth strategy object has a method request_phase which generates a html form and shows it to user. For "omniauth-identity" strategy this would be the form you see at /auth/identity url.
You can override the request_phase method and replace the form generator with, for example, a redirect to your custom login page (assuming you have it available at /login url). Place the following along with your omniauth initialization code:
module OmniAuth
module Strategies
class Identity
def request_phase
redirect '/login'
end
end
end
end
# Your OmniAuth::Builder configuration goes here...
In addition to 1gors and iains answer:
"/auth/identity/register" is served with GET as well, to override, I had to:
class OmniAuth::Strategies::Identity
alias :original_other_phase :other_phase
def other_phase
if on_registration_path? && request.get?
redirect '/sign_up'
else
original_other_phase
end
end
end
You can set method in omniauth.rb
:on_login => SessionsController.action(:new)
for example:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :identity,
:fields => [:nickname],
:on_login => SessionsController.action(:new),
:on_registration => UsersController.action(:new),
:on_failed_registration => SessionsController.action(:registration_failure)
end
Related
I am using Devise to authenticate users to my Ruby on Rails application. Up to this point, I have been using the standard Cookie-based session to authenticate users, but now I have requirements to allow a token-based authentication, and I implemented this through a custom Warden strategy.
For the sake of this example, my custom strategy code is:
module Devise
module Strategies
class CustomAuthenticatable < Base
def valid?
params.has_key? :email
end
def authenticate!
success!(User.find_by(email: params[:email]))
#fail
end
end
end
end
So this works as expected for the first request: when I GET /api/my_controller/url?email=user#example.com the user is authenticated, and I get the expected response.
But wait: when I then make a second request: GET /api/my_controller/url, the user is still authenticated.
Upon further inspection, I see that a Set-Cookie is being sent, with a Devise session.
So here's my question:
How do I disable the Set-Cookie when using a custom strategy?
You can prevent the creation of a session, like described in here.
Prevent session creation on rails 3.2.2 for RESTful api
resource = warden.authenticate!(:scope => resource_name, :store => !(request.format.xml? || request.format.json?))
For some other options, please consider Rails 3 disabling session cookies.
I am using devise + omniauth to enable facebook/linkedin/twitter login on my website.
I have multiple models with totally different roles and both need social logins, I have been using devise+omniauth successfully unitl now as I needed that only for one login.
However now devise gives error saying I cant use omniauthable on multiple models.
I looked around and someone was helpful enough to create this wiki explaining how to use omniauth with devise without omniauthable module.
But I think since I would want to use it for different models, I would have to use different paths for signup, which this wiki doesnt explain.
I looked into omniauth and it has some scarce details about options request_path and callback_path which seem to be relevant, but I couldn't figure out what exactly needs to be done.
Any help will be much appreciated.
EDIT
This is what I have done till now.
# omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
FACEBOOK_AUTH_REGEX = /^\/(model1|model2)\/auth\/facebook\/$/
FACEBOOK_CALLBACK_REGEX = /^\/(model1|model2)\/auth\/facebook\/callback\/$/
LINKEDIN_AUTH_REGEX = /^\/(model1|model2)\/auth\/linkedin\/$/
LINKEDIN_CALLBACK_REGEX = /^\/(model1|model2)\/auth\/linkedin\/callback\/$/
facebook_callback_path = lambda do |env|
env["PATH_INFO"] =~ FACEBOOK_CALLBACK_REGEX
end
linkedin_callback_path = lambda do |env|
env["PATH_INFO"] =~ LINKEDIN_CALLBACK_REGEX
end
facebook_request_path = lambda do |env|
match_data = FACEBOOK_AUTH_REGEX.match env["PATH_INFO"]
if match_data
"/#{match_data[1]}/auth/facebook/callback/"
end
end
linkedin_request_path = lambda do |env|
match_data = LINKEDIN_AUTH_REGEX.match env["PATH_INFO"]
if match_data
"/#{match_data[1]}/auth/linkedin/callback/"
end
end
provider :facebook, FACEBOOK_ID, FACEBOOK_SECRET, :callback_path => facebook_callback_path, :request_path => facebook_request_path
provider :linkedin, LINKEDIN_ID, LINKEDIN_SECRET, :callback_path => linkedin_callback_path, :request_path => linkedin_request_path
end
#routes.rb
match "/:model_name/auth/:provider/callback/", :to => "recruiter_omniauth_callbacks#sync"
And it seems to work fine for linkedin but in facebook I get
{"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100}}
Not Sure why I get this, what are the two urls it says should be same, I think I am using :model_name/auth/facebook/callback/ everywhere so not sure what is the problem it has.
Any help?
I post an example for a similar case here with other perspective of attacking that problem, hope it helps, regards!
with omniauth in my app, to have a user use Google oAuth2 to authenticate I redirect the user to:
/users/auth/google_oauth2
If the users approves the request, then the AuthenticationsController#create is called.
With AuthenticationsController#create - I can add event tracking to record the # of users who approve google auth. What I don't have is the number that I sent to approve meaning I don't have a conversion rate.
How can I track the # of people who hit the URL around making requests to connect.
A nasty solution would be to build a filter around the method Strategy#request_call and do the tracking there.
Inside an initializer:
OmniAuth::Strategy.class_eval do
def request_call_with_tracking
log :info, "Im running before the actual request_call"
Tracker.hit(name) #name will return the provider
request_call_without_tracking
end
alias_method_chain :request_call, :tracking
end
You can achieve this by using the OmniAuth setup phase. You can pass a :setup option to an OmniAuth provider, with a proc which will be executed before the authentication is performed. You can add event tracking inside this proc.
So if you have some tracker class, you can do this:
use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
:setup => lambda { |env|
Tracker.track
}
end
For more information check out Avdi Grimm's great blog post about the subject.
I'm using Omniauth to authenticate at Twitter, but I have 2 apps registred with diferent names that I want to use depeding on the current locale(session scope).
So I need to change the provider key and secret defined at omniauth.rb file right before user calls auth/twitter( I was thinking to do a before_filter but auth/twitter is an external link to twitter and not a regular action) or a way to config Omniauth to define providers by locale instead of define for the entire application scope.
So how can I do that ? Any idea?
What you need to do is set setup to true in omniauth builder
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter , :setup => true
end
Then set add following to your routes.rb file to define which route will be called for setup
get '/people/auth/twitter/setup' => 'sessions#twitter_setup' #needed for devise setup phase hook to work
After so just set the omniauth strategy in the session controller that meet the route for setup
def twitter_setup
request.env['omniauth.strategy'].options[:consumer_key] = YOUR_DYNAMIC_KEY
request.env['omniauth.strategy'].options[:consumer_secret] = YOUR_DYNAMIC_SECRET_KEY
render :plain => "Setup complete.", :status => 404
end
this will enable you to load the apps you need
I have a rails app hosted on Heroku that am restricting access to by using a proxy service. The external server acts as intermediary for all requests and handles user authentication. Once a user has authenticated, the server (I think LDAP) adds the user name to the request header and redirects them to my app.
I would like to use the username from the request header to authenticate users in my app. Basically if the user doesn't exist I would create a user with that username (no password required) and if not I would just log them in. I will be storing the users in my app's database.
How should I do this? Is it possible to use Devise for this purpose?
Edit: I got it working with Devise/custom Warden strategy like this:
# config/initializers/my_strategy.rb
Warden::Strategies.add(:my_strategy) do
def valid?
true
end
def authenticate!
if !request.headers["my_key"]
fail!("You are not authorized to view this site.")
redirect!("proxy_url")
else
username = request.headers["my_key"]
user = User.find_by_username(username)
if user.nil?
user = User.create(:username => username)
end
success!(user)
end
end
end
#config/initializers/devise.rb
config.warden do |manager|
manager.default_strategies(:scope => :user).unshift :my_strategy
end
I need to make this as bullet proof as possible. Are there other security measures can I take to make sure someone can't spoof the request header and access my site?
I think using devise can be a little more overkill, but you can. You just need define a warden strategie. in devise or use only warden in this purpose.