我的omniauth 应用程序的行为很奇怪。基本上,我有管理面板,需要访问它才能使用 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": "代码已过期", "error": "invalid_grant"}
更新 4:
我再次检查了 Yandex 的所有凭据 client_id 和密码,它们 100% 有效。