HTTPBadRequest { "error_description" : "Code has expired" , "error" : "invalid_grant" } for Oauth au



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

问题:我按照多个指南中的要求做了所有操作,并且自昨天以来一切正常,我尝试使用Yandex帐户进行身份验证,但收到HTTPBadRequest错误。

注意:我的代码没有一点变化。我所有的访问数据client_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

问题

HTTPBadRequest错误突出显示CallbacksController中的行:

@response_mess = http.request(req)

我尝试过的

1)重新启动的Rails应用程序;

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

3)删除了Yandex Oauth部分中的注册应用程序。然后再次添加新的client_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>]

更新:我收到此错误:

{"error_description": "Code has expired", "error": "invalid_grant"}

更新2:我试图联系Yandex支持。我向他们发送了我问题的简要描述和问题链接。但是没有回应。

更新 3:

我在 CHROME POSTMAN 中尝试了相同的 POST 请求,并收到了与

{"error_description": "代码已过期", "错误": "invalid_grant"}

更新 4:

我再次检查了Yandex的所有凭据client_id和密码,它们是100%有效的。

来自 OAUTH 2.0 RFC:

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.

这在Yandex网站上有进一步的解释:

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

您正在向Yandex提供无效的凭据。暂时忘记您编写的代码,因为唯一失败的部分是将数据发送到Yandex时。Yandex告诉您数据无效,并且您已与Postman确认了这一点。这意味着这是在发送无效数据:

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

因此,请仔细检查这些内容:

  1. grant_type应该是authorization_code吗?
  2. 您是否确定@authorization_code设置为一个值(而不是 nil)并且该值有效?
  3. 同样的问题@client_id
  4. 同样的问题@secret
  5. 您是否缺少redirect_uri值?

相关内容

  • 没有找到相关文章

最新更新