Skip to content

Instantly share code, notes, and snippets.

@tmpapageorgiou
Last active December 10, 2018 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmpapageorgiou/0c1188283f5ee450b517ffe2f8912c98 to your computer and use it in GitHub Desktop.
Save tmpapageorgiou/0c1188283f5ee450b517ffe2f8912c98 to your computer and use it in GitHub Desktop.
Using modulus and expoent directly to validate azure ad jwt token
import jwt
import requests
import base64
from jose.utils import base64url_decode
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
from cryptography.hazmat.primitives import serialization
def ensure_bytes(key):
if isinstance(key, str):
key = key.encode('utf-8')
return str(key)
def decode_value(val):
decoded = base64url_decode(ensure_bytes(val))
return int(decoded.encode('hex'), 16)
def rsa_pem_from_jwk(jwk):
return RSAPublicNumbers(
n=decode_value(jwk['n']),
e=decode_value(jwk['e'])
).public_key(default_backend()).public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
class InvalidAuthorizationToken(Exception):
def __init__(self, details):
super().__init__('Invalid authorization token: ' + details)
def get_kid(token):
headers = jwt.get_unverified_header(token)
if not headers:
raise InvalidAuthorizationToken('missing headers')
try:
return headers['kid']
except KeyError:
raise InvalidAuthorizationToken('missing kid')
def get_jwk(token):
kid = get_kid(token)
jwks = get_jwks(token)
for jwk in jwks.get('keys'):
if jwk.get('kid') == kid:
return jwk
raise InvalidAuthorizationToken('kid not recognized')
def get_public_key(token):
return rsa_pem_from_jwk(get_jwk(token))
def validate_jwt(jwt_to_validate):
public_key = get_public_key(jwt_to_validate)
options = {'verify_aud': False, 'verify_exp': False}
import ipdb; ipdb.set_trace() # BREAKPOINT
decoded = jwt.decode(jwt_to_validate,
public_key,
verify=True,
algorithms=['RS256'],
audience=valid_audiences,
options=options)
# do what you wish with decoded token:
# if we get here, the JWT is validated
print(decoded)
def main():
import sys
import traceback
if len(sys.argv) < 2:
print('Please provide a JWT as script argument')
return
jwt = sys.argv[1]
if not jwt:
print('Please pass a valid JWT')
try:
validate_jwt(jwt)
except Exception as ex:
traceback.print_exc()
print('The JWT is not valid!')
else:
print('The JWT is valid!')
def get_jwks(token):
token_header = jwt.get_unverified_header(token)
res = requests.get('https://login.microsoftonline.com/common/.well-known/openid-configuration')
jwk_uri = res.json()['jwks_uri']
res = requests.get(jwk_uri)
return res.json()
valid_audiences = 'https://graph.microsoft.com'
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment