I have a main app, this app has Users and Admins (different model and table)using devise.
The main app use doorkeeper to allow users to authenticate on another service. The client app use Omniauth to consume OAuth2.
I am now reaching a point where the client app need a backend and using the admin users from the main app make sense.
Here is my current strategy :
module OmniAuth
module Strategies
class ResaNetwork < OmniAuth::Strategies::OAuth2
option :name, :resa_network
option :client_options, {
#site: "http://dylog.ubuntu-sylario.net:3000",
site: ENV["CLIENT_OPTION_SITE"],
authorize_path: "/oauth/authorize"
}
uid do
raw_info["resource_owner_id"]
end
def raw_info
#raw_info ||= access_token.get('/api/me').parsed
end
end
end
end
For doorkeeper I will will use warden scope (I know it has nothing to do with oauth scope) user or admin depending on the oauth2 Scope in resource_owner_authenticator.
Is it possible to have a specific scope entered has a param with the signin path of omniauth? How?
Is my use of scope correct or is it a really ugly hack? For info, admin will access users data while users will only see their data in the API.
Related
I am designing a shopify app which enables customers buying product through mobile phones. The scenario is customers need to be able to sign up with omniauth and then they can get the products info from the app. However, before any customer can get products info from a shop, my shopify app should first authenticate with the shop owner using omniauth.
The problem now is devise will modify omniauth default authenticate strategy. If I use shopify_api, I auth through path auth/shopify, it can work without devise installed. If devise is installed, it will redirect auth/shopify to omniauth/shopify. I find this path is generated by devise. How can I skip devise and use the original omniauth path? Thanks.
Devsie has a good tutorial on how to separate omniauthable out of your devise model. This will allow you to configure your own omniauth settings.
Once you've set-up a provider for both providers in config/initializers/omniauth.rb and removed devise.omniauth from conifg/initializers/devise.rb, you'll need to set-up your routes to handle the response from OAuth differently.
routes.rb
devise_scope :user do
get "/auth/:action/callback", to: 'users/omniauth_callbacks', constraints: { action: /facebook/ }
end
get 'auth/:action/callback' => 'another_controller', constraints: { action: /shopify/ } # connections
Then in another_controller.rb
class AnotherController
def shopify
auth_hash = request.env['omniauth.auth']
shop = auth_hash[:uid]
token = auth_hash[:credentials][:token]
ShopifyAPI::Session.temp("#{shop}.myshopify.com", token) do
current_shop = ShopifyAPI::Shop.current
...
end
end
end
Hope this helps.
I'm in the process of setting up Doorkeeper and OAuth2 for one of my Rails Applications. My goal is to allow api access to a user depending on their access_token, so that only a user can see their 'user_show' json. So far I have my development and production applications set up and authorized on the 'oauth2/applications' route.
My '/config/initializers/doorkeeper.rb'
Doorkeeper.configure do
# Change the ORM that doorkeeper will use.
# Currently supported options are :active_record, :mongoid2, :mongoid3,
# :mongoid4, :mongo_mapper
orm :active_record
# This block will be called to check whether the resource owner is authenticated or not.
resource_owner_authenticator do
# Put your resource owner authentication logic here.
# Example implementation:
User.find_by_id(session[:current_user_id]) || redirect_to('/')
end
end
and my '/api/v1/user/controller.rb' looks as such:
class Api::V1::UserController < Api::ApiController
include ActionController::MimeResponds
before_action :doorkeeper_authorize!
def index
user = User.find(doorkeeper_token.resource_owner_id)
respond_with User.all
end
def show
user = User.find(doorkeeper_token.resource_owner_id)
respond_with user
end
end
I have tried to gain access to the OAuth Applications table to see what is being created but I cannot access it in the rails console.
Thanks in advance for the insight!
It seems that Doorkeeper doesn't find any token.
Make sure you're sending it, either from url with ?access_token=#{token} or ?bearer_token=#{token}, either giving this token in headers using Bearer Authorization.
You also need to have in mind that a token could be associated only to an app, without a resource owner. So resource_owner_id value could be nil even with a valid token. It depends on what grant flow you're using (client credential flow is not associated with a resource owner). See https://github.com/doorkeeper-gem/doorkeeper/wiki#flows
For the OAuth tables, try with Doorkeeper::AccessToken.all in a rails console.
Hope this helped
My end goal is for users to have multiple 3rd party authentications at the same time.
Right now, I am using Devise to create users. Users can sign up via email or facebook or google and it works. But now, after they have already signed up, I need them to also verify with, say, youtube or soundcloud. So the user was created with devise, but I also need them to verify with other things.
Since Devise hogs omniauth for it's own purposes, I can't use omniauth on the side.
As I see it I have three options:
Try to monkeypatch devise and get it to allow multiple authentications at the same time on one user
Do oauth by hand on the side adjacent to current Devise implementation
Scrap Devise and do something different
I would greatly appreciate any advice or other options
I think this may be what you need: http://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on/
They open sourced their code too!
Provider: https://github.com/joshsoftware/sso-devise-omniauth-provider
Client: https://github.com/joshsoftware/sso-devise-omniauth-client
Or even better, check out this: http://communityguides.heroku.com/articles/16
Try to monkeypatch devise and get it to allow multiple authentications at the same time on one use
You don't need to monkeypatch devise --- you can have your own oauth controller the has
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# handle if already a twitter user
# handle if a new user
# use the `sign_in user` to sign_in the user
end
def twitter
# handle if already a facebook user
# handle if a new user
end
end
and use it in routes
devise_for :user,
:controllers => {
:omniauth_callbacks => "users/omniauth_callbacks"
}
I am using authlogic and omniauth for authentication in my Rails 3.0.10 app.
However when I get the callback from the omniauth provider, I am not able to create a new user session so as to sign in the user.
In other responses (and even in the authlogic docs), it says that using UserSession.create(#user, true) should be able to create and persist a new session.
However, this does not work for me. It only works if the #user has a password in the database (by inserting a password directly in the db).
But there is no password when using third-party authentication providers, hence I cannot sign in users.
Any ideas how to sign in a user without a password in authlogic?
Thanks.
You can do something like this in your User model:
acts_as_authentic do |config|
external = Proc.new { |r| r.externally_authenticated? }
config.merge_validates_confirmation_of_password_field_options(:unless => external)
config.merge_validates_length_of_password_confirmation_field_options(:unless => external)
config.merge_validates_length_of_password_field_options(:unless => external)
end
externally_authenticated? is just a method on the user that checks what is providing the user information, and if it's one of the omniauth providers, returns true.
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.