[英]HTTPBadRequest {“error_description”: “Code has expired”, “error”: “invalid_grant”} for Oauth authentification, Ruby on Rails
我的omniauth應用程序有奇怪的行為。 基本上,我有管理員面板,需要訪問它才能使用Yandex帳戶進行身份驗證。
問題 :我在多個指南中按要求完成了所有操作,一切正常,因為昨天我嘗試使用Yandex帳戶進行身份驗證,並收到了HTTPBadRequest錯誤。
注意 :我的代碼中沒有改變。 我的所有訪問數據client_Id和密碼都沒有改變。
的Gemfile:
gem "omniauth-yandex"
路線:
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
CallbacksController:
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}"
所以仔細檢查這些東西:
grant_type
應該是authorization_code
嗎? @authorization_code
被設置為一個值(而不是nil)並且該值是有效的嗎? @client_id
? @secret
? redirect_uri
值嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.