首页 > 解决方案 > 在 Django 中使用 google.oauth2 id_token.verify_oauth2_token() 时出现“不正确的填充”错误

问题描述

我正在尝试从 React 前端到我的 Django 后端验证用户提交的 google 身份验证 JWT。我让我的前端使用 JWT 向后端发送一个请求,然后我的后端从请求中提取它并通过谷歌的推荐令牌身份验证处理它。我的问题是,每次我通过 id_token.verify_ouath2_token() 处理从我的前端收到的 JWT 时,最终都会引发关于“不正确填充”的错误,最终源于令牌的 base64 编码。

但是,当通过复制粘贴我从 POST 请求中提取的令牌来手动测试它时,它工作得非常好并且不会引发错误。所以在我处理发布请求的某个地方出了点问题,但我不确定是什么。我尝试用 utf-8 和 ascii 解码 POST 请求,并简单地将 JWT 保留为我提取的字节形式。所有这些都会引发相同的错误,我很困惑。

这是我的代码:views.py

def login(request):
    if request.method == "POST":
        print(request.body.decode("ascii")) # For decoding. By copy/pasting this output into id_token.verify_oauth2_token instead of the token variable, the function returns successfully
        try:
            token = request.body.decode("ascii")
            # Specify the CLIENT_ID of the app that accesses the backend:
            idinfo = id_token.verify_oauth2_token(token, requests.Request(), "MY CLIENT ID")

    # ID token is valid. Get the user's Google Account ID from the decoded token.
            userid = idinfo['sub']
            return(HttpResponse(userid))
        except ValueError as e:
            # Invalid token
            print(e)
            return(HttpResponse("Failure"))
    else:
        pass

和回溯

  File "C:\Users\E\Google Drive\Projects\Django Project\Website\BackEnd\test\Main\views.py", line 80, in login
    idinfo = id_token.verify_oauth2_token(token, requests.Request(), "MY CLIENT ID")
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\oauth2\id_token.py", line 147, in verify_oauth2_token
    id_token, request, audience=audience, certs_url=_GOOGLE_OAUTH2_CERTS_URL
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\oauth2\id_token.py", line 126, in verify_token
    return jwt.decode(id_token, certs=certs, audience=audience)
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\auth\jwt.py", line 230, in decode
    header, payload, signed_section, signature = _unverified_decode(token)
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\auth\jwt.py", line 148, in _unverified_decode
    signature = _helpers.padded_urlsafe_b64decode(signature)
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\site-packages\google\auth\_helpers.py", line 215, in padded_urlsafe_b64decode
    return base64.urlsafe_b64decode(padded)
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\base64.py", line 133, in urlsafe_b64decode
    return b64decode(s)
  File "C:\Users\E\AppData\Local\Programs\Python\Python36-32\lib\base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

标签: pythondjangooauth-2.0jwt

解决方案


经过一些实验,我想通了。看起来 request.body.decode("ascii") 最终生成了用双引号括起来的 JWT,而双引号是导致问题的原因。从字符串中剥离它们后,它可以完美地工作。

views.py 中的最终代码

@csrf_exempt
def login(request):
    if request.method == "POST":
        try:
            token = request.body.decode("ascii").strip("\"") 
            # Specify the CLIENT_ID of the app that accesses the backend:
            idinfo = id_token.verify_oauth2_token(token, requests.Request(), "MY CLIENT ID")

推荐阅读