0

Got access token using azure.identity ClientSecretCredential client credential flow but when trying to decode using the PyJwt library giving me the below error.

ValueError: Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm.

decoding like below:

 jwt.decode(
            token,
            client_secret, # same client secret used in generating the access token
            options={"verify_signature": True},
            algorithms=["RS256"],
        )

If i keep the verify_signature to false then i'm able to decode. Also tried passing issue and audience while decoding but didnt work.

 issuer="https://login.microsoftonline.com/<tenant-id>/",
 aud="<client_id>"
m9m9m
  • 1,655
  • 3
  • 21
  • 41

1 Answers1

0

I tried in my environment and got the below results:

You can use the below code to decode the access token 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"]


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"
}

enter image description here

If you are using MS Graph API scopes https://graph.microsoft.com/.default the results JWT would contain a "nonce" in JWT Header and is not meant to be validated.

So, I created it with my own API as like below:

enter image description here

Reference:

Using an Azure AD tenant ID - and a valid token issued for a 'app registration'. The signature verification is is failing - Stack Overflow by Rukmini.

Venkatesan
  • 3,748
  • 1
  • 3
  • 15