Authenticate Google API request token in Python

377 Views Asked by At

My locally hosted bot that's integrated with Google Hangouts API uses python's Tornado module to accept user input from Google and responds with an appropriate reply. This is the request handler on the bot server:

class incomingRequestHandler(tornado.web.RequestHandler):
    def post(self):
        recievedData = json.loads(self.request.body.decode('utf-8'))
        
        responseData = generateResponse(recievedData)
           
        self.write({ 'text' : responseData })

This works great. Now I want to authenticate the incoming requests to make sure they're only coming from Google Hangouts.

The request from Google does have an Authorization bearer token in it's header and I'm sure that's what needs to be used for verification. As such, based on this article I took the recommended measures like using id_token.verify_oauth2_token() or querying https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 but neither solution seems to work.

Could someone point me in the right direction for this? Am I using the correct token even or is this the wrong method for verifying incoming requests?

1

There are 1 best solutions below

0
Maurice Kasomwung On

This issue originated from me having no idea what a JWT was nor knowing that what I'd encountered was a JWT. Another symptom of trying to handle things yourself, I guess.

Anyway, the solution is simply to get the Google certificates from this link, use openssl to generate corresponding public keys and feed the key specified (by kid value) in the authentication token to the jwt.decode() method of python's jwt module.

Here's a snippet of the solution:

selectedKey = certs.get(jwtHeader.get('kid')) //certs is a dict containing the public keys from Google
        
checksum = jwt.decode(token, selectedKey, algorithms=["<value-of-alg>"], audience="<value-of-aud>", issuer="<value-of-iss>") //token is simply the authentication token as a string

Note the following bash command to be sued to convert Google's x509 certificates into pem format public keys:

openssl x509 -pubkey -noout -in key.pem

I don't think python has a very modular solution for the above yet. Do let me know if there is.