[Django]-Python google ouath authentication decode and verify id_token

7👍

Know this is an old post but I found it via Google so I thought somebody else might drop in…

I ended up doing:

segments = response['id_token'].split('.')

if (len(segments) != 3): 
   raise Exception('Wrong number of segments in token: %s' % id_token) 

b64string = segments[1]
b64string = b64string.encode('ascii') 
padded = b64string + '=' * (4 - len(b64string) % 4) 
padded = base64.urlsafe_b64decode(padded)

3👍

ID token(aka JSON Web Signature (JWS)) has 3 parts separated by . character:

Header.Payload.Signature

We can get each part by splitting the token:

parts = token.split(".")

Now I don’t know the reason, but these parts do not have the base64 padding. Maybe because it is not enforced(see this)? And python base64 library requires it.

The padding character is =, and the padding should be added to the base64 string so that it is length is multiple of 4 characters. For example if the string is 14 characters, it should have the padding == at the end so that it is 16 characters in total.

So the formula to calculate correct padding is this:

4 - len(base64_string) % 4

After we add the right padding and decode the string:

payload = parts[1]
padded = payload + '=' * (4 - len(payload) % 4)

base64.b64decode(padded)

what we will get is a string representation of JSON object, we can convert it to JSON with:

json.loads(base64.b64decode(padded))

Finally we can put everything in a convenience function:

import base64
import json


def parse_id_token(token: str) -> dict:
    parts = token.split(".")
    if len(parts) != 3:
        raise Exception("Incorrect id token format")

    payload = parts[1]
    padded = payload + '=' * (4 - len(payload) % 4)
    decoded = base64.b64decode(padded)
    return json.loads(decoded)

To learn more details about id token check Takahiko Kawasaki(founder of authlete.com)’s excellent article

👤Caner

1👍

Well, I figured out why…

I used base64.b46decode(id_token) to decode it.
However, I should split id_token by ‘.’ and decode them separately.
So I can get header, claims and signature from id_token.

I was just too stupid for ignoring those little ‘.’ in the string….

Leave a comment