我遇到了为谷歌任务验证用户身份的问题。
首先,它对用户进行身份验证,并将事情做到完美。但在第二次旅行中,它抛出了一个错误。
Signet::AuthorizationError - Authorization failed. Server message:
{
"error" : "invalid_grant"
}:
以下是代码:
def api_client code=""
@client ||= (begin
client = Google::APIClient.new
client.authorization.client_id = settings.credentials["client_id"]
client.authorization.client_secret = settings.credentials["client_secret"]
client.authorization.scope = settings.credentials["scope"]
client.authorization.access_token = "" #settings.credentials["access_token"]
client.authorization.redirect_uri = to('/callbackfunction')
client.authorization.code = code
client
end)
end
get '/callbackfunction' do
code = params[:code]
c = api_client code
c.authorization.fetch_access_token!
result = c.execute("tasks.tasklists.list",{"UserId"=>"me"})
unless result.response.status == 401
p "#{JSON.parse(result.body)}"
else
redirect ("/oauth2authorize")
end
end
get '/oauth2authorize' do
redirect api_client.authorization.authorization_uri.to_s, 303
end
执行第二个请求有什么问题?
更新:这是用户同意的链接和参数。
https://accounts.google.com/o/oauth2/auth?
access_type=offline&
approval_prompt=force&
client_id=somevalue&
redirect_uri=http://localhost:4567/oauth2callback&
response_type=code&
scope=https://www.googleapis.com/auth/tasks
问题已解决。
解决方案:
在回调函数中,通过用户同意提供的代码接收的令牌存储在数据库中。
然后在其他函数中,只需从数据库中检索这些令牌,并使用它来处理您想要的针对谷歌任务API的任何内容。
get '/callbackfunction' do
code = params[:code]
c = api_client code
c.authorization.fetch_access_token!
# store the tokens in the database.
end
get '/tasklists' do
# Retrieve the codes from the database and create a client
result = client.execute("tasks.tasklists.list",{"UserId"=>"me"})
unless result.response.status == 401
p "#{JSON.parse(result.body)}"
else
redirect "/oauth2authorize"
end
end
我使用rails,并且我只将令牌存储在DB中。然后使用脚本,在调用execute之前设置新的客户端,下面是代码。
client = Google::APIClient.new(:application_name => 'my-app', :application_version => '1.0')
client.authorization.scope = 'https://www.googleapis.com/auth/analytics.readonly'
client.authorization.client_id = Settings.ga.app_key
client.authorization.client_secret = Settings.ga.app_secret
client.authorization.access_token = auth.token
client.authorization.refresh_token = true
client.authorization.update_token!({access_token: auth.token})
client.authorization.fetch_access_token!
if client.authorization.refresh_token && client.authorization.expired?
client.authorization.fetch_access_token!
end
puts "Getting accounts list..."
result = client.execute(:api_method => analytics.management.accounts.list)
puts " ===========> #{result.inspect}"
items = JSON.parse(result.response.body)['items']
但是,它给出了和您所面临的错误相同的错误,
/signet-0.4.5/lib/signet/oauth_2/client.rb:875:in `fetch_access_token': Authorization failed. Server message: (Signet::AuthorizationError)
{
"error" : "invalid_grant"
}
from /signet-0.4.5/lib/signet/oauth_2/client.rb:888:in `fetch_access_token!'
请说明为什么它不能使用给定的令牌?我已经使用了oauth2,所以用户已经获得了授权。现在我想访问api并获取数据。。。
===================更新================
好的,有两个问题,
权限将添加到devise.rb,
config.omniauth :google_oauth2, Settings.ga.app_key,Settings.ga.app_secret,{ access_type: "offline", approval_prompt: "" , :scope => "userinfo.email, userinfo.profile, plus.me, analytics.readonly"
}
refresh_token必须传递给API调用,否则无法授权。
我希望这对面临类似问题的人有所帮助。