6

我正在为连接到 Google Drive 的应用程序使用服务器端流验证。

我能够检索访问代码并交换 access_token 和用户信息。然后我坚持刷新令牌。因此,我可以确认 client_id 和 client_secret 是正确的,但是当我使用 refresh_token 获取新的 access_token 时,我得到了 400 响应。这是详细信息,我记录了来自初始令牌请求的响应,并且可以确认存储到数据库中的 refresh_token 与 Google 响应中的响应相匹配。

但是当我尝试使用 refresh_token(以编程方式和 httpie)时,我得到了下面的响应。为什么?

 % http --verbose POST https://accounts.google.com/o/oauth2/token Content-Type:application/x-www-form-urlencoded refresh_token=1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc client_id=XXXX client_secret=XXXX grant_type=refresh_token                              
POST /o/oauth2/token HTTP/1.1
Content-Length: 198
Host: accounts.google.com
b'Accept': application/json
b'Accept-Encoding': gzip, deflate, compress
b'Content-Type': application/x-www-form-urlencoded
b'User-Agent': HTTPie/0.6.0

{"refresh_token": "1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc", "client_id": "XXXX", "client_secret": "XXXX", "grant_type": "refresh_token"}

HTTP/1.1 400 Bad Request
Alternate-Protocol: 443:quic
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json
Date: Mon, 16 Sep 2013 03:42:06 GMT
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Server: GSE
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

{
    "error": "invalid_request"
}

这是我的 Web 应用程序为这个特定用户第一次登录时的日志输出,我坚持了 refresh_token:

[debug] application - retrieved authentication code, proceeding to get token and user info
[debug] application - successfully parsed user and token: GoogleOAuthPacket(User(117397424875078935066,XXXX,XXXX,XXXX,https://lh6.googleusercontent.com/-lbSmIO8BHMA/AAAAAAAAAAI/AAAAAAAAAAA/6ncAxM6DQuM/photo.jpg,1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc),ya29.AHES6ZT0Mn0t7zWDJW-rU6c4eEnCr76MuP14hkLSC60lX0Ve7tGrbA,3600)
[debug] application - response for token request was: {
  "access_token" : "ya29.AHES6ZT0Mn0t7zWDJW-rU6c4eEnCr76MuP14hkLSC60lX0Ve7tGrbA",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZhODc3Mzc3MGFmNTkyMWM5OWZjMWRmYzVmN2U3NTA2YTFjOTQyZDUifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTE3Mzk3NDI0ODc1MDc4OTM1MDY2IiwiYXRfaGFzaCI6Ijk0dENwbzlxNzhUYXFPOWgwWkI3dHciLCJoZCI6Im15bWFpbC5sYXVzZC5uZXQiLCJlbWFpbCI6InNjb2xpbmNydTAwMUBteW1haWwubGF1c2QubmV0IiwiYXpwIjoiNjQyMzAxMzYzNDQ0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIiwiYXVkIjoiNjQyMzAxMzYzNDQ0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiaWF0IjoxMzc5Mjk5NDQwLCJleHAiOjEzNzkzMDMzNDB9.f5lBChQCxSfNfTWqSm-uR0ueoq78w2JlJOg3zFG-Wpav8Jx6ypwshcXCA0EQjFlAckBaQ_kA1uUpToidg5nGa3B-0ftMLnuGLnO-J65zyEYyMjo4Y3wFezpy9toHOk_8rPIzZ8_jzpuLKlxuqMnz0EdK-3Mik0p6pSbkZgX8lww",
  "refresh_token" : "1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc"
}
[debug] application - response for user request was: {
  "sub" : "117397424875078935066",
  "name" : "XXXX",
  "given_name" : "XXXXX",
  "family_name" : "XXXX",
  "picture" : "https://lh6.googleusercontent.com/-lbSmIO8BHMA/AAAAAAAAAAI/AAAAAAAAAAA/6ncAxM6DQuM/photo.jpg",
  "email" : "XXXX",
  "email_verified" : true,
  "hd" : "XXXX"
}
[debug] application - user User(117397424875078935066,XXXX, XXXX,XXXX,https://lh6.googleusercontent.com/-lbSmIO8BHMA/AAAAAAAAAAI/AAAAAAAAAAA/6ncAxM6DQuM/photo.jpg,1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc) not found, proceeding to save in database
[debug] application - successfully persisted user, proceeding to save token to cache
4

2 回答 2

15

好吧,我想通了。这就是 Google OAauth 网站所说的发布请求需要的样子:

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded

client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
refresh_token=1/6BMfW9j53gdGImsiyUH5kU5RsR4zwI9lUVX-tqf8JXQ&
grant_type=refresh_token

如果我将我的 httpie 更改为使用 --form 开关而不是添加 ContentType 标头,那么我确实会得到一个访问令牌:

 % http --verbose --form POST https://accounts.google.com/o/oauth2/token refresh_token=1/nJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc client_id=XXXX client_secret=XXXX grant_type=refresh_token                                                                       POST /o/oauth2/token HTTP/1.1
Content-Length: 175
Content-Type: application/x-www-form-urlencoded
Host: accounts.google.com
b'Accept': */*
b'Accept-Encoding': gzip, deflate, compress
b'Content-Type': application/x-www-form-urlencoded; charset=utf-8
b'User-Agent': HTTPie/0.6.0

refresh_token=1%2FnJZGF7hIySVtVCl8I-Y3KfXAPk84gD0X6ym7hQS8gcc&client_id=XXXX&client_secret=XXXX&grant_type=refresh_token

HTTP/1.1 200 OK
Alternate-Protocol: 443:quic
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json
Date: Mon, 16 Sep 2013 05:20:21 GMT
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Server: GSE
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

{
  "access_token": "XXXX", 
  "expires_in": 3600, 
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjRlNDZiMGQ4Zjg1OWRhMDNjOGM3MmY5YTM3ZWM0NTFjM2RjNTM0NmUifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTE3Mzk3NDI0ODc1MDc4OTM1MDY2IiwiYXRfaGFzaCI6IkJvT0lCZVVXcmthRzRBY2NpajZkaEEiLCJhdWQiOiI2NDIzMDEzNjM0NDQuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJlbWFpbCI6InNjb2xpbmNydTAwMUBteW1haWwubGF1c2QubmV0IiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIiwiYXpwIjoiNjQyMzAxMzYzNDQ0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiaGQiOiJteW1haWwubGF1c2QubmV0IiwiaWF0IjoxMzc5MzA4NTIxLCJleHAiOjEzNzkzMTI0MjF9.XtEDuIaEK5qe0SIFVr2l88zu3FpPBKl3_9z0D0wMCOxE-lnC4abrL71uxvMbVHvTVNbcFRs5RPHTrwPtidfw44MoukZLwVaW1c1TYBet2yuC3bZeoe7HPBZxzdMmpqBiYZOkvru3o_S5kaGp1csKzttd_fZ9nkzXITSMHxHAtbk", 
  "token_type": "Bearer"
}

所以,我需要有Content-Type: "application/x-www-form-urlencoded; charset=utf-8", 而不是Content-Type: "application/x-www-form-urlencoded"and 来解决问题。

于 2013-09-16T06:12:21.303 回答
0

就我而言,我正在使用基于 iOS 移动应用程序的身份验证,但我忘记了要获取可在服务器端使用的刷新令牌,您必须在移动应用程序上获取授权码,然后将其发送到服务器,并且服务器使用该授权代码从对 Google 的 REST 调用中获取其刷新令牌(请参阅https://developers.google.com/identity/sign-in/ios/offline-access?hl=en)。

于 2016-12-25T23:35:47.203 回答