#ruby-on-rails-3 #rack #omniauth #oauth-2.0 #http-authentication
#ruby-on-rails-3 #стойка #omniauth #oauth-2.0 #http-аутентификация
Вопрос:
Я создаю службу ecomm с использованием Spree, которая использует Devise, она содержит все данные от наших пользователей, но мы используем ее только как сервис, через API, поэтому у нас есть приложение (rails 3.1), клиент / потребитель, который использует OmniAuth, имеет пользовательскую стратегию, которая черезOauth2 перенаправляет запросы поставщику, показывает страницу sign is, а затем позволяет запросу проходить через метод авторизации, а затем весь процесс oauth2 работает безупречно до обратного вызова, а затем пользователь входит в систему нашего потребителя.
До тех пор, пока эта часть не будет работать правильно, это мой класс стратегии:
module OmniAuth
module Strategies
class MyStrategy < OAuth2
def initialize(app, api_key = nil, secret_key = nil, options = {}, amp;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, amp;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
Что я пытаюсь сделать, так это ввести форму входа в клиентское приложение, а затем, используя мою пользовательскую стратегию, отправить эти учетные данные (email / пароль) поставщику (я думаю, через заголовки HTTP_AUTHORIZATION), чтобы зарегистрировать пользователя в провайдере, пропустив форму входа в провайдере, поэтому после того, как devise аутентифицирует пользователя, он проходит через метод авторизации и позволяет продолжить весь процесс Oauth2.
Я пробовал несколько вещей, которые включают определение вызова метода (env) в стратегии и установку env [‘HTTP_AUTHORIZATION’] с учетными данными, такими как «email: password», перед вызовом super. Я также включил в метод request_phase ключ ‘HTTP_AUTHORIZATION’ в хэш параметров, даже внутри ключа :headers . Моей последней попыткой было включить его в хэш заголовков в объект подключения Фарадея внутри объекта client (OAuth2::Client instance) класса.
После отладки почти всего процесса и попытки включить его везде мой провайдер продолжает не получать этот конкретный ключ в заголовках, даже отлаживая провайдера, когда Devise тестирует каждую стратегию… но, в конце концов, не повезло.
Я действительно признателен, если кто-нибудь скажет мне, что я делаю неправильно, или если то, что я пытаюсь выполнить, не может быть выполнено так, как я это делаю, или если есть более простой способ сделать это..
Заранее спасибо, извините за очень длинный пост / вопрос и еще раз спасибо за ваше время!
Комментарии:
1. Когда-нибудь это работало? Я столкнулся с той же проблемой…
Ответ №1:
Я думаю, это может быть то, что вы ищете:
Взято из 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
Комментарии:
1. Как мы можем обработать то же самое для token_url? Я должен предоставить другой token_url на основе имени политики. authorize_url может быть предоставлено другое значение на основе политики в методе request_phase. После завершения авторизации token_url должен быть предоставлен с тем же именем политики, чтобы получить токен. Есть идеи, как я могу этого добиться?