Hello I want to know how to get the keys to verify the access token. I got the x5c from https://login.microsoftonline.com/{{tenantid}}/discovery/keys?appid={{app-id}}
but if i put this key in jwt-decode function its failing. Do i need to do some processing on this key. Its a public key, do i need to know the private key to validate the signature or only public key is enough.
Can you please tell me some basic algo to validate the access_token.
Signature validation of my Azure access token, Private-key?
I agree with Junnas's comment you need a public key to verify the signature with an Azure access token.
You can use the below code to decode the access token with the public key using the PyJwt
library.
Code:
import requests
import jwt
from cryptography.hazmat.primitives import serialization
import json
tenant_id = 'xxxx'
client_id = 'xxxx'
client_secret = 'xxxxx'
token_endpoint = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
data = {
"grant_type": "client_credentials",
"client_id": f"{client_id}",
"client_secret": f"{client_secret}",
"scope": "api://your-client-id/.default"
}
response = requests.post(token_endpoint, data=data)
access_token = response.json()["access_token"]
print(access_token)
response1 = requests.get("https://login.microsoftonline.com/fb134080-e4d2-45f4-9562-f3a0c218f3b0/discovery/keys")
keys = response1.json()['keys']
token_headers = jwt.get_unverified_header(response.json()['access_token'])
token_alg = token_headers['alg']
token_kid = token_headers['kid']
public_key = None
for key in keys:
if key['kid'] == token_kid:
public_key = key
rsa_pem_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(public_key))
rsa_pem_key_bytes = rsa_pem_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
decoded_token = jwt.decode(
response.json()['access_token'],
key=rsa_pem_key_bytes,
verify=True,
options={"verify_signature": True},
algorithms=['RS256'],
audience="api://client_id",
issuer="https://sts.windows.net/tenant_id/"
)
s = json.dumps(decoded_token)
q = json.dumps(json.loads(s), indent=2)
print(q)
Output:
{
"aud": "api://xxxxx",
"iss": "https://sts.windows.net/xxxx",
"iat": 169028xxx,
"nbf": 1690284xxx,
"exp": 1690371xxx,
"aio": "E2ZgYFDetxxxxxvq/ydjjk/BwA=",
"appid": "d8xxxxx",
"appidacr": "1",
"idp": "https://sts.windows.net/xxxxx,
"oid": "dxxxxx",
"rh": "xxxxx",
"roles": [
"tread.all"
],
"sub": "dxxxxxx5",
"tid": "fxxx",
"uti": "wJxxxxxA",
"ver": "1.0"
}
Note: If you are using MS Graph API scopes https://graph.microsoft.com/.default
the results JWT would contain a "nonce" in the JWT Header and is not meant to be validated. Except you own API scopes.
Reference: