GoogleTokenResponse.getIdToken() returns 空
GoogleTokenResponse.getIdToken() returns null
我们通过 Google 进行的服务器 OAuth 验证已开始在 GoogleTokenResponse.parseIdToken():
中抛出 NullPointerException
java.lang.NullPointerException:
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:462)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse.parseIdToken(GoogleTokenResponse.java:106)
这是今天开始的新行为。我们的服务器代码没有变化(它已经工作了几个月)。只有来自一个 Android 设备的凭据才会出现问题——我有另一个可以正常工作。刷新客户端的服务器访问令牌并不能解决问题。
GoogleTokenResponse 由 GoogleAuthorizationCodeTokenRequest() 创建,调用成功,当我记录 GoogleTokenResponse 时它看起来有效:
{"access_token":"ya29.mwJvM...","expires_in":3600,"token_type":"Bearer"}
更新:测试了更多,发现 tokenResponse.getIdToken() 是 returning null,所以我假设这就是我调用 parseIdToken() 时导致 NPE 的原因。
当 GoogleAuthorizationCodeTokenRequest() 显然成功并且有访问令牌时,什么会导致 getIdToken() return 为空?
最终解决方案:此问题似乎是由 Google Play Services 在 2016 年初更新以匿名化 PlayerID 间歇性触发的。我们能够通过将访问令牌的服务器验证更改为更新的方法而不是依赖旧的 getIdToken()/parseIdToken() 方法来解决我们的问题。有关详细信息,请参阅下面的最新更新
两天后,出现此故障的 Android 设备神秘地重新开始工作。因此,原因可能是客户端 Google 播放服务状态中的 t运行sient 错误,该错误已自我更正。修复发生在设备重启后。
不过我不确定是不是这个原因。 Play Services 也发生了一些变化,以在不暴露 G+ 用户 ID 的情况下启用身份验证——另一种解释是服务器没有被赋予检索 ID 的范围。 (如果那是原因,那么修复一定是由 Google 部署的,因为我们没有做任何更改)
我们会继续关注,如果有其他人遇到此问题请发表评论。
4/19/16 此问题发生在另一台设备上。我想知道这是否与此处描述的 Google Play 授权更改有关 http://android-developers.blogspot.com/2016/01/play-games-permissions-are-changing-in.html?m=1
这个解释有点稀疏,但它确实说 "The user_id returned by token info may no longer be present with the new model. And even if it is present, the value won’t be the same as the new player ID"
在这种情况下,问题发生在
之后
- 设备之前已通过 Google 旧 G+ 风格的 Play 服务授权
- 应用程序数据已清除,因此需要重新授权
- 在重新授权 GPS 期间提示输入新的 GPS-only 播放器 ID(不是真实姓名),这让我想知道它是否将该设备切换到新的非 G+ ID
- 然后服务器调用 tokenResponse.getIdToken() 返回 null
我还不确定发生了什么,但正在研究两个值得关注的领域:
1) 尽管上面引用的 Google 文档说 "existing players ... will continue to get their Google+ ID" 我想知道这是否是按客户端管理的。这将是一个大问题,因为我们使用该 ID 为用户跨设备存储云状态,因此如果最初在新玩家 ID 之前设置帐户的用户随后在第二台设备上安装了该应用程序,他们可以登录gplay 但两个帐户不匹配
2) 如果是这个原因,那么我们的服务器代码无法使用新的非 G+ 播放器 ID,或者当设备 t[=73 时存在 google 后端错误=]两者之间的位置。这仍然令人困惑,因为我们之前的问题在几天后确实自我纠正,这意味着服务器代码没问题——但我肯定希望对 google 后端身份验证的错误的替代解释错了!
--- 更新
我认为这个问题与新的 GPS 匿名 PlayerID 更改有关。很难调试,因为 Google 的遗留服务器身份验证流程似乎需要非空 GoogleTokenResponse.getIdToken(),对于新创建的 GPS PlayerID 失败,但在 12-24 小时后问题似乎可以自我纠正,遗留 Google 身份验证调用开始成功,包括返回非空 getIdToken()。
不过,我尝试在上面的 google 信息页面的第 7 步中实施新的 PlayerID 流程,该流程通过 www.googleapis 将访问令牌(从服务器授权代码生成)转换为玩家 ID .com/games/v1/applications//验证/
即使在 getToken() returns null:
时,此代码也成功地从 accessToken 中检索了玩家 ID
// URL: www.googleapis.com/games/v1/applications/<app_id>/verify/
URL url = new URL("https://www.googleapis.com/games/v1/applications/" + GPlayServicesAppId + "/verify/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Authorization", "OAuth " + accessToken);
httpConnection.setRequestMethod("GET");
int responseCode = httpConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
...
}
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
String responseJson = (read contents of reader)
// Example response: { "kind": "games#applicationVerifyResponse", "player_id": "11520..."}
我 运行 进行了一些测试,据我所知,新方法适用于旧版 G+ getToken() 方法适用的所有情况,并修复了它不适用的情况,所以我相信我们可以切换到上面代码片段中的新方法,希望它是可靠的。
我们通过 Google 进行的服务器 OAuth 验证已开始在 GoogleTokenResponse.parseIdToken():
中抛出 NullPointerExceptionjava.lang.NullPointerException:
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:462)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse.parseIdToken(GoogleTokenResponse.java:106)
这是今天开始的新行为。我们的服务器代码没有变化(它已经工作了几个月)。只有来自一个 Android 设备的凭据才会出现问题——我有另一个可以正常工作。刷新客户端的服务器访问令牌并不能解决问题。
GoogleTokenResponse 由 GoogleAuthorizationCodeTokenRequest() 创建,调用成功,当我记录 GoogleTokenResponse 时它看起来有效:
{"access_token":"ya29.mwJvM...","expires_in":3600,"token_type":"Bearer"}
更新:测试了更多,发现 tokenResponse.getIdToken() 是 returning null,所以我假设这就是我调用 parseIdToken() 时导致 NPE 的原因。
当 GoogleAuthorizationCodeTokenRequest() 显然成功并且有访问令牌时,什么会导致 getIdToken() return 为空?
最终解决方案:此问题似乎是由 Google Play Services 在 2016 年初更新以匿名化 PlayerID 间歇性触发的。我们能够通过将访问令牌的服务器验证更改为更新的方法而不是依赖旧的 getIdToken()/parseIdToken() 方法来解决我们的问题。有关详细信息,请参阅下面的最新更新
两天后,出现此故障的 Android 设备神秘地重新开始工作。因此,原因可能是客户端 Google 播放服务状态中的 t运行sient 错误,该错误已自我更正。修复发生在设备重启后。
不过我不确定是不是这个原因。 Play Services 也发生了一些变化,以在不暴露 G+ 用户 ID 的情况下启用身份验证——另一种解释是服务器没有被赋予检索 ID 的范围。 (如果那是原因,那么修复一定是由 Google 部署的,因为我们没有做任何更改)
我们会继续关注,如果有其他人遇到此问题请发表评论。
4/19/16 此问题发生在另一台设备上。我想知道这是否与此处描述的 Google Play 授权更改有关 http://android-developers.blogspot.com/2016/01/play-games-permissions-are-changing-in.html?m=1
这个解释有点稀疏,但它确实说 "The user_id returned by token info may no longer be present with the new model. And even if it is present, the value won’t be the same as the new player ID"
在这种情况下,问题发生在
之后- 设备之前已通过 Google 旧 G+ 风格的 Play 服务授权
- 应用程序数据已清除,因此需要重新授权
- 在重新授权 GPS 期间提示输入新的 GPS-only 播放器 ID(不是真实姓名),这让我想知道它是否将该设备切换到新的非 G+ ID
- 然后服务器调用 tokenResponse.getIdToken() 返回 null
我还不确定发生了什么,但正在研究两个值得关注的领域:
1) 尽管上面引用的 Google 文档说 "existing players ... will continue to get their Google+ ID" 我想知道这是否是按客户端管理的。这将是一个大问题,因为我们使用该 ID 为用户跨设备存储云状态,因此如果最初在新玩家 ID 之前设置帐户的用户随后在第二台设备上安装了该应用程序,他们可以登录gplay 但两个帐户不匹配
2) 如果是这个原因,那么我们的服务器代码无法使用新的非 G+ 播放器 ID,或者当设备 t[=73 时存在 google 后端错误=]两者之间的位置。这仍然令人困惑,因为我们之前的问题在几天后确实自我纠正,这意味着服务器代码没问题——但我肯定希望对 google 后端身份验证的错误的替代解释错了!
--- 更新
我认为这个问题与新的 GPS 匿名 PlayerID 更改有关。很难调试,因为 Google 的遗留服务器身份验证流程似乎需要非空 GoogleTokenResponse.getIdToken(),对于新创建的 GPS PlayerID 失败,但在 12-24 小时后问题似乎可以自我纠正,遗留 Google 身份验证调用开始成功,包括返回非空 getIdToken()。
不过,我尝试在上面的 google 信息页面的第 7 步中实施新的 PlayerID 流程,该流程通过 www.googleapis 将访问令牌(从服务器授权代码生成)转换为玩家 ID .com/games/v1/applications//验证/
即使在 getToken() returns null:
时,此代码也成功地从 accessToken 中检索了玩家 ID// URL: www.googleapis.com/games/v1/applications/<app_id>/verify/
URL url = new URL("https://www.googleapis.com/games/v1/applications/" + GPlayServicesAppId + "/verify/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Authorization", "OAuth " + accessToken);
httpConnection.setRequestMethod("GET");
int responseCode = httpConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
...
}
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
String responseJson = (read contents of reader)
// Example response: { "kind": "games#applicationVerifyResponse", "player_id": "11520..."}
我 运行 进行了一些测试,据我所知,新方法适用于旧版 G+ getToken() 方法适用的所有情况,并修复了它不适用的情况,所以我相信我们可以切换到上面代码片段中的新方法,希望它是可靠的。