Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails HTTPBadRequest{“error”description:“Code has expired”,“error”:“invalid”grant}用于Oauth身份验证,Ruby on Rails_Ruby On Rails_Ruby_Oauth_Omniauth_Yandex Api - Fatal编程技术网

Ruby on rails HTTPBadRequest{“error”description:“Code has expired”,“error”:“invalid”grant}用于Oauth身份验证,Ruby on Rails

Ruby on rails HTTPBadRequest{“error”description:“Code has expired”,“error”:“invalid”grant}用于Oauth身份验证,Ruby on Rails,ruby-on-rails,ruby,oauth,omniauth,yandex-api,Ruby On Rails,Ruby,Oauth,Omniauth,Yandex Api,我的omniauth应用程序有奇怪的行为。基本上,我有一个管理面板,需要访问该面板才能通过Yandex帐户进行身份验证 问题:我按照多个指南中的要求完成了所有工作,从昨天开始,我尝试使用Yandex帐户进行身份验证,但收到HTTPBadRequest错误 注意:我的代码一点也没有更改。我的所有访问数据客户端Id和密码也没有更改 档案: gem "omniauth-yandex" 路线: devise_for :users, :controllers => { :omniauth_call

我的omniauth应用程序有奇怪的行为。基本上,我有一个管理面板,需要访问该面板才能通过Yandex帐户进行身份验证

问题:我按照多个指南中的要求完成了所有工作,从昨天开始,我尝试使用Yandex帐户进行身份验证,但收到HTTPBadRequest错误

注意:我的代码一点也没有更改。我的所有访问数据客户端Id和密码也没有更改

档案:

gem "omniauth-yandex"
路线:

devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
回拨控制器:

def yandex
    require 'net/http'
    require 'json'  # => false

    @user = User.from_omniauth(request.env["omniauth.auth"])

    @client_id = Rails.application.secrets.client_id 
    @secret =  Rails.application.secrets.password
    @authorization_code = params[:code]

    @user.update_attribute(:code, @authorization_code)
    @user.update_attribute(:state, params[:state])


    @post_body = "grant_type=authorization_code&code=#{@authorization_code}&client_id=#{@client_id}&client_secret=#{@secret}"

    @url = "https://oauth.yandex.ru/token"

    url = URI.parse(@url)
    req = Net::HTTP::Post.new(url.request_uri)
    req['host'] ="oauth.yandex.ru"
    req['Content-Length'] = @post_body.length
    req['Content-Type'] = 'application/x-www-form-urlencoded'
    req.body = @post_body
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = (url.scheme == "https")

    @response_mess = http.request(req)

    refreshhash = JSON.parse(@response_mess.body)
    access_token  = refreshhash['access_token']
    refresh_token  = refreshhash['refresh_token']
    access_token_expires_at = DateTime.now + refreshhash["expires_in"].to_i.seconds


    if access_token.present? && refresh_token.present? && access_token_expires_at.present?
        @user.update_attribute(:access_token, access_token)
        @user.update_attribute(:refresh_token, refresh_token)
        @user.update_attribute(:expires_in, access_token_expires_at)

        sign_in(@user)
        redirect_to admin_dashboard_index_path
    end

end
用户模型:

    require 'rest-client'

      devise :database_authenticatable, :registerable,
          :recoverable, :rememberable, :trackable, :validatable,
          :omniauthable, :omniauth_providers => [:yandex]

      def self.from_omniauth(auth)
          where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
            user.provider = auth.provider
            user.uid = auth.uid
            user.email =  auth.info.email
            user.code = auth.info.code
            user.state = auth.info.state
            user.password = Devise.friendly_token[0,20]
          end
      end

      def refresh_token_if_expired
          if token_expired?
            response    = RestClient.post "https://oauth.yandex.com/token",
            :grant_type => 'refresh_token',
            :refresh_token => self.refresh_token

            refreshhash = JSON.parse(response.body)

            self.access_token     = refreshhash['access_token']
            self.expires_in = DateTime.now + refreshhash["expires_in"].to_i.seconds

            self.save

            puts 'Saved'
          end
      end

      def token_expired?          
          expiry = Time.at(self.expires_in)
          logger.debug "#{expiry}"
          return true if expiry < Time.now 
          token_expires_at = expiry
          save if changed?
          false 
      end
  end
我所尝试的

Exchanging an authorization code for a token

The application sends the code, along with its ID and password, in a POST request.
POST /token HTTP/1.1
Host: oauth.yandex.
Content-type: application/x-www-form-urlencoded
Content-Length: <length of request body>
[Authorization: Basic <encoded client_id:client_secret string>]

   grant_type=authorization_code
 & code=<authorization code>
[& client_id=<application ID>]
[& client_secret=<application password>]
[& device_id=<device ID>]
[& device_name=<device name>]
1) 重启Rails应用程序

2) 已从数据库中删除用户并尝试再次登录

3) 已删除Yandex Oauth部分中的注册应用程序。然后再次添加新的客户端id和密码

来自Yandex Oauth指南

Exchanging an authorization code for a token

The application sends the code, along with its ID and password, in a POST request.
POST /token HTTP/1.1
Host: oauth.yandex.
Content-type: application/x-www-form-urlencoded
Content-Length: <length of request body>
[Authorization: Basic <encoded client_id:client_secret string>]

   grant_type=authorization_code
 & code=<authorization code>
[& client_id=<application ID>]
[& client_secret=<application password>]
[& device_id=<device ID>]
[& device_name=<device name>]
更新2:我试图联系Yandex支持部门。我向他们发送了我的问题的简要描述和问题的链接。但没有回应

更新3:

我在CHROME POSTMAN中尝试了相同的发帖请求,收到了与之相同的回复

{“错误描述”:“代码已过期”,“错误”:“授予无效”}

更新4:

我再次检查了Yandex的所有凭据客户端id和密码,它们100%有效。

来自:

这将在以下方面作进一步解释:

无法颁发访问令牌。临时授权码不是由Yandex.Money颁发的,或者已经过期,或者已经为此临时授权码颁发了访问令牌(使用相同临时授权码的访问令牌的重复请求)

您向Yandex提供的凭据无效。暂时忘记您编写的代码,因为唯一失败的部分是当它将数据发送到Yandex时。Yandex告诉你数据无效,你已经和邮递员确认了这一点。这意味着这将发送无效数据:

@post_body = "grant_type=authorization_code&code=#{@authorization_code}&client_id=#{@client_id}&client_secret=#{@secret}"
因此,请仔细检查以下事项:

  • grant\u类型
    应该是
    authorization\u代码
  • 您确定
    @authorization\u code
    设置为一个值(而不是零)并且该值有效吗
  • 对于
    @client\u id
    ,同样的问题
  • 同样的问题
    @secret
  • 是否缺少
    重定向\u uri

  • 谢谢你的努力。但我已经检查了好几次了。当我将“@secret”更改为invalid时,它会显示不同的错误:unauthorized等。“post_body”正在发送无效数据,因为从Yandex发送给我的“@authorization_code”无效。我没有任何选项可以更改。请逐行检查您的代码,并验证HTTP POST请求仅发出一次,并且
    授权\u代码
    已正确保留。我建议您这样做,因为您的代码中有
    @user.update\u属性(:code,@authorization\u code)
    ,这意味着您正在保存
    授权码
    ,尽管它是一次性使用的…因此它不能重复使用,也不应该保存。问题肯定是发送到Yandex的数据。问题不在你的代码中。@anotermh,我逐行检查了我的代码,只发出了一次POST请求。我甚至删除了POST请求,只是从params中读取了授权代码,然后将其放入Chrome Postman中,但收到了相同的输出:“代码已过期”Yandex似乎有问题,因为我在3周内没有更改任何与获取令牌相关的代码,然后它突然停止工作(Yandex支持部门甚至不想帮我。几天过去了,我的电子邮件都没有回复。
    invalid_grant
        The provided authorization grant (e.g., authorization
        code, resource owner credentials) or refresh token is
        invalid, expired, revoked, does not match the redirection
        URI used in the authorization request, or was issued to
        another client.
    
    @post_body = "grant_type=authorization_code&code=#{@authorization_code}&client_id=#{@client_id}&client_secret=#{@secret}"