Rails 3.1 OAuth Provider invalid_grant с devise_oauth2_providable

Я пытаюсь настроить провайдера oauth2, используя приложение, которое уже имеет omniauth и devise. Теперь user.rb:

class User < ActiveRecord::Base

  has_many :authentications
  has_many :graphs

  devise :database_authenticatable,
    :registerable, 
    :recoverable, 
    :rememberable, 
    :trackable, 
    :validatable, 
    :omniauthable, 
    :token_authenticatable,
    :oauth2_providable, 
    :oauth2_password_grantable,
    :oauth2_refresh_token_grantable,
    :oauth2_authorization_code_grantable

.......

}

Все остальное реализовано, как и ожидалось, но я получаю следующую ошибку, когда запускаю все это локально и пытаюсь использовать гем oauth2 (0.5.0) для подключения к моему клиенту.

Я заканчиваю:

http://localhost:8080/oauth/callback?code=2ebd3d9d149b22becec37da7a8f1eb0d

что вызывает исключение:

e.to_yaml
"--- !ruby/exception:OAuth2::Error\nresponse: &70266332040280 !ruby/object:OAuth2::Response\n  response: &70266332040340 !ruby/object:Faraday::Response\n    env:\n      :method: :post\n      :body: ! '{\"error\":\"invalid_grant\",\"error_description\":\"invalid authorization\n        code request\"}'\n      :url: !ruby/object:Addressable::URI\n        validation_deferred: false\n        scheme: http\n        normalized_scheme: !!null \n        uri_string: !!null \n        hash: !!null \n        host: localhost\n        authority: !!null \n        normalized_host: !!null \n        port: 3000\n        normalized_port: !!null \n        path: /oauth2/token\n        normalized_path: !!null \n        query: !!null \n        normalized_query: !!null \n      :request_headers:\n        Content-Type: application/x-www-form-urlencoded\n      :parallel_manager: !!null \n      :request:\n        :proxy: !!null \n      :ssl: {}\n      :status: 400\n      :response_headers:\n        content-type: application/json\n        x-ua-compatible: IE=Edge\n        cache-control: no-cache\n        x-runtime: '0.119701'\n        content-length: '82'\n        server: WEBrick/1.3.1 (Ruby/1.9.2/2011-02-18)\n        date: Wed, 05 Oct 2011 14:40:10 GMT\n        connection: close\n      :response: *70266332040340\n    on_complete_callbacks: []\n  options:\n    :parse: !!null \n  error: !ruby/exception:OAuth2::Error\n    response: *70266332040280\n    code: invalid_grant\n    description: invalid authorization code request\n  parsed:\n    error: invalid_grant\n    error_description: invalid authorization code request\ncode: invalid_grant\ndescription: invalid authorization code request\n"

Я также заметил, что состояние не указано, что в последнем черновике (http://tools.ietf.org/html/draft-ietf-oauth-v2-22) требуется для обратного вызова. Может ли это быть проблемой?

Что касается вывода, я не получаю никаких очевидных ошибок в выводе сервера:

http://pastie.org/2644028

Теперь стоит отметить еще одну вещь: я вижу, что происходит несколько SELECT, но я никогда не вижу, чтобы какие-либо данные были вставлены в различные таблицы, особенно не в коды авторизации, что происходит непосредственно перед тем, как это исключение выдается.


person Phil Sturgeon    schedule 05.10.2011    source источник


Ответы (2)


Посмотрев на запросы, похоже, что текущее время превышает значение expired_at. Ниже приведен код devise_oauth2_providable, вызывающий эту ошибку:

module Devise
  module Strategies
    class Oauth2AuthorizationCodeGrantTypeStrategy < Oauth2GrantTypeStrategy
      def grant_type
        'authorization_code'
      end

      def authenticate!
        if client && code = AuthorizationCode.valid.find_by_token(params[:code])
          success! code.user
        elsif !halted?
          oauth_error! :invalid_grant, 'invalid authorization code request'
        end
      end
    end
  end
end

Эта допустимая область проверяет, превышает ли текущее время значение поля expires_at кода авторизации или равно ему.

person Jon Hinson    schedule 10.10.2011
comment
Обычно, попросив всех о помощи, я снова решил это. Я перебрал всю сеть форков, исправил на github и заработал! github.com/philsturgeon/devise_oauth2_providable Что вы изменили в этом коде? Если это будет исправлено в моей вилке, я дам вам 250 баллов за изучение этого! - person Phil Sturgeon; 10.10.2011
comment
О, я не вносил никаких изменений в код. Я только что заметил, что запрос code = AuthorizationCode.valid.find_by_token(params[:code]) возвращал nil, поскольку срок действия авторизации_кода истек, что вызывало ошибку invalid_grant. - person Jon Hinson; 10.10.2011
comment
АА, вижу. Да, я зашел так далеко, токены не были найдены, потому что ни один из них не был вставлен в базу данных, как я упоминал в посте. Я больше не уверен в точном исправлении, но объединение нескольких действительных исправлений в мою вилку, похоже, помогло. Спасибо! - person Phil Sturgeon; 10.10.2011

Я не гений Rails, но я хорошо разбираюсь в GitHub, и мне удалось найти несколько человек, делающих коммиты для своих форков. Объединив несколько корректно выглядящих исправлений в одном месте, мне удалось создать форк, который у меня отлично работал:

https://github.com/socialcast/devise_oauth2_providable/pull/17

Я установил это в качестве источника в Gemfile, и теперь обратный вызов работает нормально!

Теперь мне просто нужно придумать, как остановить истечение срока действия токенов доступа или как-то внедрить user_id в чертов ответ... Работай, работай, работай.

person Phil Sturgeon    schedule 10.10.2011