我正在连接到使用 OAuth2 进行身份验证的 API (seek.com.au)。我在 OAuth2 gem 上苦苦挣扎了一段时间,最后我写了如下的普通请求。虽然这是可行的,但我仍然想了解我最初的 OAuth2 实施有什么问题。
这是我当前的工作代码,**第三方*与我使用可以访问其他帐户的帐户访问 API 的事实有关。这个逻辑主要在scope
方法中实现(在这个片段的底部)。
以下包含一些额外的逻辑,但get_grant
andpost_for_token
方法应该包含所有内容。
module Seek::Base
CONFIG = YAML.load_file "#{Rails.root}/config/seek.yml"
HOST = 'http://test.api.seek.com.au/v1/'
REQUEST_URIS = {
get_grant: HOST + 'OAuth/auth',
post_for_token: HOST + 'OAuth/token',
get_applications: HOST + 'advertiser/applications'
}
def uri_for(request, params = {})
uri = REQUEST_URIS[request]
uri += '?' + params.to_param if params.any?
URI.parse uri
end
end
class Seek::OAuth2 # TODO? is instance needed?
include Seek::Base
# by account_id
@@tokens = {}
def initialize(account_id)
@account_id = account_id
end
def self.authenticate!(account_id)
new(account_id).authenticate!
end
# eg: when a request responded that the token is expired
def self.expire_token(account_id)
@@tokens.delete account_id
end
###########################################################################
############################### begin #####################################
# authentication
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth-2.0
def authenticate!
@@tokens[@account_id] ||= begin
grant = get_grant
raise Exception.new(@error) if @error
Rails.logger.info "Retrive token for #{@account_id}"
post_for_token
end
end
private
# part of t he authentication process
# as we have one account for many entities, we use third party variation
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth2/auth
def get_grant
uri = uri_for :get_grant, {response_type: :code, client_id: username, scope: scope}
response = Net::HTTP.get_response uri
params = response['location'].split('?').second
@error = params.split('error=').second
@grant_code = params.split('code=').second
end
# part of the authentication process
# see: http://developer.seek.com.au/docs/partner-api/api-methods/oauth2/token
def post_for_token
uri = uri_for :post_for_token
request = Net::HTTP::Post.new uri.path, {'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'}
request.set_form grant_type: :authorization_code, code: @grant_code, redirect_uri: ''
request.basic_auth username, password
response = Net::HTTP.new(uri.host, uri.port).request request
JSON(response.body)['access_token']
end
########################## end ############################################
###########################################################################
def username
CONFIG['credentials']['username']
end
def password
CONFIG['credentials']['password']
end
############## the scope method
############## I think I need to insert this in the OAuth request
def scope
"urn:seek:thirdparty:username:#{username},urn:seek:advertiser:identity:#{@account_id}"
end
end
这里有几行(替换authenticate!
方法)是为了做同样的事情,但遗憾的是,OAuth 返回invalid_client
.
client = OAuth2::Client.new(username, password, :site => 'http://test.api.seek.com.au/v1')
client.auth_code.authorize_url redirect_uri: ''
token = client.auth_code.get_token 'authorization_code_value',
headers: {'Authorization' => %^Basic #{Base64.encode64 "#{username}:#{password}"}^ }
我认为问题scope
在于 OAuth 创建的方法(见第一个片段的底部),但我不确定,无论如何我找不到修改它的方法。
我还在GitHub 中打开了一个问题,但我认为这已经涵盖,只是没有记录(或者我找不到)。