Как внедрить заголовки http_authorization с использованием omniauth и oauth2 в consumer, чтобы аутентификация происходила в provider?

#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 должен быть предоставлен с тем же именем политики, чтобы получить токен. Есть идеи, как я могу этого добиться?