I'm building an ecomm service using Spree which uses Devise, it contains all the data from our users, but we are using it as a service only, via APIs, so we have an application (rails 3.1), the client/consumer, which using OmniAuth, has a custom strategy, that via Oauth2, redirects requests to the provider, shows the sign is page, and then let the request go through the authorize method, and then the whole oauth2 process works flawlessly until the callback and then the user gets logged into our consumer.
Until this part, everything works correctly, this is my strategy class:
module OmniAuth
module Strategies
class MyStrategy < OAuth2
def initialize(app, api_key = nil, secret_key = nil, options = {}, &block)
client_options = {
:site => CUSTOM_PROVIDER_URL,
:authorize_url => "#{CUSTOM_PROVIDER_URL}/auth/my_provider/authorize",
:token_url => "#{CUSTOM_PROVIDER_URL}/auth/my_provider/access_token"
}
super(app, :onyx_oauth, api_key, secret_key, client_options, &block)
end
protected
def user_data
response = @access_token.get("/auth/my_provider/user.json");
if response.status.to_i == 200
@data ||= MultiJson.decode(response.body);
else
raise 'Service error'
end
end
def request_phase
options[:scope] ||= "read"
super
end
def user_hash
user_data
end
def auth_hash
OmniAuth::Utils.deep_merge(super, {
'uid' => user_data["uid"],
'user_info' => user_data['user_info'],
'extra' => user_data['extra']
})
end
end
end
end
What I'm trying to do is to have a sign in form in the client application, and then using my custom strategy, send those credentials (email/password) to the provider (I'm thinking via HTTP_AUTHORIZATION headers), to log the user into the provider skipping the sign in form in the provider, so after devise authenticates the user, it pass through the authorize method and let the whole Oauth2 process continue.
I been trying several things that include defining a method call(env) in the strategy and set the env['HTTP_AUTHORIZATION'] with the credentials like "email:password" before calling super. I also included in request_phase method the 'HTTP_AUTHORIZATION' key in the options hash, even inside a :headers key too. My last attempt was to include it in the headers hash into the Faraday connection object within the client object (OAuth2::Client instance) of the class.
After debugging almost the whole process, and trying to include it everywhere, my provider keeps not getting that particular key in the headers, even debugging the provider when Devise is testing each strategy... but not luck after all.
I really appreciate if someone would tell me what I'm doing wrong or if what I'm trying to accomplish cannot be done in the way I'm doing it or if there is a simpler way to do it..
Thanks in advance, sorry for the very long post/question, and thanks again for your time!
I think this might be what you are looking for:
Taken from https://github.com/jackdempsey/omniauth-reddit
module OmniAuth
module Strategies
class Reddit < OmniAuth::Strategies::OAuth2
#class NoAuthorizationCodeError < StandardError; end
option :name, "reddit"
option :authorize_options, [:scope, :duration]
option :client_options, {
site: 'https://oauth.reddit.com',
token_url: 'https://ssl.reddit.com/api/v1/access_token'
}
uid { raw_info['id'] }
info do
{
name: raw_info['name']
}
end
extra do
{'raw_info' => raw_info}
end
def raw_info
@raw_info ||= access_token.get('/api/v1/me').parsed || {}
end
def build_access_token
options.token_params.merge!(:headers => {'Authorization' => basic_auth_header })
super
end
def basic_auth_header
"Basic " + Base64.strict_encode64("#{options[:client_id]}:#{options[:client_secret]}")
end
MOBILE_USER_AGENTS = 'webos|ipod|iphone|mobile'
def request_phase
options[:client_options].authorize_url = mobile_request? ? 'https://ssl.reddit.com/api/v1/authorize.compact' : 'https://ssl.reddit.com/api/v1/authorize'
super
end
def mobile_request?
ua = Rack::Request.new(@env).user_agent.to_s
ua.downcase =~ Regexp.new(MOBILE_USER_AGENTS)
end
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With