请求OpenID时,id_token的Base64 / Json编码声明部分中的Google Oauth服务器的响应损坏

时间:2014-07-15 13:33:34

标签: oauth google-api openid

使用Oauth作为我网站的登录机制时,如何处理此损坏的响应?我正在实现Oauth登录,它将取代我之前使用的Open ID登录。

  1. 我将用户重定向到https://accounts.google.com/o/oauth2/auth以请求他们的许可。我正在使用范围email profile openidhttp://subdomain.mysite.example.com
  2. 的openid.realm
  3. 用户接受权限并返回code参数。
  4. 我将此代码参数连同我的应用凭据一起提交给https://accounts.google.com/o/oauth2/token
  5. Google发回包含access_tokenid_token的JSON回复。
  6. 我必须解析id_token以确定用户的身份。令牌是由句点(.)分隔的三个base64编码部分。我把它分成了几个时期,看看中间的那个有我要找的“索赔”信息。其他部分是我忽略的加密签名,因为我通过HTTPS直接与Google通信。
  7. 当我解码时,声明应该是一个JSON对象,但偶尔它是腐败的。当它被破坏时,腐败总是在开放的id部分周围。
  8. 以下是access_token的示例(此处的数据适用于我自己的帐户):

    eyJhbGciOiJSUzI1NiIsImtpZCI6IjM1MzExZDJiMWI2OTQ0NTVkYmY2ZmE4YTUyYTNmNzZkYTUwMDUwM2IifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAwNDkwNzU0NjA0MjY0MTgxNzg0IiwiYXpwIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoic3Rvc3Rlcm1AZ21haWwuY29tIiwiYXRfaGFzaCI6Im1kalkxdTlEQ2VXcEVwWC15N0h3enciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm9wZW5pZF9pZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudHMvbzgvaWQ_aWQ9QUl0T2F3bDR4NlZXVE1fbHVWSGhwb1VqTlE1VE56c3BzcjFqTF8wIiwiaWF0IjoxNDA1NDI2MDQ0LCJleHAiOjE0MDU0Mjk5NDR9.UWEZZOhJfg5CGEHd9FNnYg__tiAysmMABk_Q0wSGaq6jbXPwe91J4JXwSgpwVBa09St7zjLRL-ajswMe-qooBe_ItzaEhXPgfc6pKWBSIWeqaj-PM2lyXECWQTAwxsm8xtBXCtjJUfyyjp3ciA95g7Rz9JHPTGDJRMywkFhb-fc
    

    然后是提取的中间“声明”部分:

    eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAwNDkwNzU0NjA0MjY0MTgxNzg0IiwiYXpwIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoic3Rvc3Rlcm1AZ21haWwuY29tIiwiYXRfaGFzaCI6Im1kalkxdTlEQ2VXcEVwWC15N0h3enciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm9wZW5pZF9pZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudHMvbzgvaWQ_aWQ9QUl0T2F3bDR4NlZXVE1fbHVWSGhwb1VqTlE1VE56c3BzcjFqTF8wIiwiaWF0IjoxNDA1NDI2MDQ0LCJleHAiOjE0MDU0Mjk5NDR9
    

    哪个Base64解码为损坏的JSON对象。以下是腐败部分的摘录:

    "openid_id":"https://www.google.com/accounts/o8/idYPR]Ø]Û
    

    我原本以为是字符编码问题。我在将base64解码为字符串时使用UTF-8。我尝试过使用其他编码,但都显得很腐败。我认为这也不是字符编码相关因为腐败发生在一个应该都是ASCII的URL中。

    此错误仅在某些帐户中出现,但一旦发生,该帐户就会一致地发生。即使完全退出Google也无法解决问题。

    当我在Google Developer Console中删除我的测试应用并创建了一个包含新凭据的新应用时,我第一次看到了这个问题。我的Google帐户可以使用旧应用程序,但在新应用程序下存在问题。

    我做错了什么,或谷歌有错误吗?

2 个答案:

答案 0 :(得分:0)

您可能无法正确解码令牌。

我去了https://developers.google.com/wallet/digital/docs/jwtdecoder并粘贴了您提供的令牌:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjM1MzExZDJiMWI2OTQ0NTVkYmY2ZmE4YTUyYTNmNzZkYTUwMDUwM2IifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAwNDkwNzU0NjA0MjY0MTgxNzg0IiwiYXpwIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoic3Rvc3Rlcm1AZ21haWwuY29tIiwiYXRfaGFzaCI6Im1kalkxdTlEQ2VXcEVwWC15N0h3enciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm9wZW5pZF9pZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudHMvbzgvaWQ_aWQ9QUl0T2F3bDR4NlZXVE1fbHVWSGhwb1VqTlE1VE56c3BzcjFqTF8wIiwiaWF0IjoxNDA1NDI2MDQ0LCJleHAiOjE0MDU0Mjk5NDR9.UWEZZOhJfg5CGEHd9FNnYg__tiAysmMABk_Q0wSGaq6jbXPwe91J4JXwSgpwVBa09St7zjLRL-ajswMe-qooBe_ItzaEhXPgfc6pKWBSIWeqaj-PM2lyXECWQTAwxsm8xtBXCtjJUfyyjp3ciA95g7Rz9JHPTGDJRMywkFhb-fc

被解码为:

部首:

{ "alg": "RS256", "kid": "35311d2b1b694455dbf6fa8a52a3f76da500503b" }

权利要求:

{
  "exp": 1405429944,
  "sub": "100490754604264181784",
  "iss": "accounts.google.com",
  "email_verified": true,
  "at_hash": "mdjY1u9DCeWpEpX-y7Hwzw",
  "openid_id": "https:\/\/www.google.com\/accounts\/o8\/id?id=AItOawl4x6VWTM_luVHhpoUjNQ5TNzspsr1jL_0",
  "azp": "1003534204908-g3vul03ojalddf3t6le27o0oqehsk3f7.apps.googleusercontent.com",
  "iat": 1405426044,
  "email": "REMOVED_TO_AVOID_SPAM",
  "aud": "1003534204908-g3vul03ojalddf3t6le27o0oqehsk3f7.apps.googleusercontent.com"
}

所以你的OpenID看起来是https://www.google.com/accounts/o8/id?id=AItOawl4x6VWTM_luVHhpoUjNQ5TNzspsr1jL_0"

如果使用Java,则可以使用Apache commons Base64类获得相同的结果:

String str = "eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAwNDkwNzU0NjA0MjY0MTgxNzg0IiwiYXpwIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoic3Rvc3Rlcm1AZ21haWwuY29tIiwiYXRfaGFzaCI6Im1kalkxdTlEQ2VXcEVwWC15N0h3enciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiMTAwMzUzNDIwNDkwOC1nM3Z1bDAzb2phbGRkZjN0NmxlMjdvMG9xZWhzazNmNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm9wZW5pZF9pZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudHMvbzgvaWQ_aWQ9QUl0T2F3bDR4NlZXVE1fbHVWSGhwb1VqTlE1VE56c3BzcjFqTF8wIiwiaWF0IjoxNDA1NDI2MDQ0LCJleHAiOjE0MDU0Mjk5NDR9";
System.out.println(new String(org.apache.commons.codec.binary.Base64.decodeBase64(str.getBytes())));

答案 1 :(得分:0)

要解决此问题,我必须从com.google.appengine.repackaged.com.google.common.util.Base64切换到org.apache.commons.codec.binary.Base64;