Say I have the following response from Google's OAuth2 /token
endpoint after exchanging the code obtained from the /auth
endpoint (using this example OAuth Playground request):
{
"access_token": "ya29.eQETFbFOkAs8nWHcmYXKwEi0Zz46NfsrUU_KuQLOLTwWS40y6Fb99aVzEXC0U14m61lcPMIr1hEIBA",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "1/ZagesePFconRc9yQbPxw2m1CnXZ5MNnni91GHxuHm-A",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhODc0MjBlY2YxNGU5MzRmOWY5MDRhMDE0NzY4MTMyMDNiMzk5NGIifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTEwMTY5NDg0NDc0Mzg2Mjc2MzM0IiwiYXpwIjoiNDA3NDA4NzE4MTkyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXRfaGFzaCI6ImFVQWtKRy11Nng0UlRXdUlMV3ktQ0EiLCJhdWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJpYXQiOjE0MzIwODI4NzgsImV4cCI6MTQzMjA4NjQ3OH0.xSwhf4KvEztFFhVj4YdgKFOC8aPEoLAAZcXDWIh6YBXpfjzfnwYhaQgsmCofzOl53yirpbj5h7Om5570yzlUziP5TYNIqrA3Nyaj60-ZyXY2JMIBWYYMr3SRyhXdW0Dp71tZ5IaxMFlS8fc0MhSx55ZNrCV-3qmkTLeTTY1_4Jc"
}
How do I hash the access token in order to compare it to the at_hash
claim of the ID Token?
I can verify ID Tokens locally on the server to protect against client modification, and want to verify the Access Token was the one that was issued with the id token (implying that audience and subject match the ID token's).
PHP solution:
Google_Client
available here: https://packagist.org/packages/google/apiclientThe
at_hash
ID Token claim is defined by OpenID Connect as such:The
c_hash
ID Token claim for the hybrid flow is defined similarly, the same steps can be used to verify either.Steps to generate an
at_hash
orc_hash
from the token:alg
as the ID Token itself, SHA-256 in Google's case.Here's some sample code in python to create that hash, you'll need two libraries,
pycrypto
and thegoogle-api-python-client
(for the base64 encoding & id token comparison, you could potentially substitute with an alternative). You can install them with pip like so:Then, run
python
interactively, and try the following:To try this sample with a fresh ID Token from your own account, create a request using the OAuth Playground with the
profile
scope (or use this one), exchange the code for refresh and access tokens, and copy the response intotoken_response_http_body
in the sample above (remove the linebreaks).