def decode_access_token(auth_header, CLIENT_ID): # Get discovery document try: token = auth_header.split(" ")[1].strip() decoded_token = jt.decode(token.decode('utf-8'), verify=False) alg = jwt.get_unverified_header(token)['alg'] kid = jwt.get_unverified_header(token)['kid'] # Validate the token values validated = token_validation(decoded_token, alg, kid, CLIENT_ID) # Validate keys for key in DIRTY_KEYS: #Validate the key try: KEYS.append(jws.verify(token, key, algorithms=[alg])) except JWSError: return JWSError if validated == True: # Verify email address is held email = "" if 'email' in decoded_token: # Id token email = decoded_token['email'] else: email = get_user_data(get_discovery_document(decoded_token)['userinfo_endpoint'], auth_header)['email'] return get_gravitar(email) else: return validated except: return {'Error' : 'Could not decode Token'} # Default Error return {'Error' : 'Unexpected error occurred'}
def is_valid(token): if not token: return False try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError, e: raise APIError("invalid_header", "Invalid header: %s" % e, 401)
def _decode_claims(self, token): """Decode the claims in a token.""" from jose import jwt, exceptions as jose_exceptions try: header = jwt.get_unverified_header(token) except jose_exceptions.JWTError as err: raise ValueError(str(err)) from None kid = header.get('kid') if kid is None: raise ValueError("No kid in header") # Locate the key for this kid key = None for key_dict in self.jwt_keyset['keys']: if key_dict['kid'] == kid: key = key_dict break if not key: raise ValueError( "Unable to locate kid ({}) in keyset".format(kid)) try: return jwt.decode( token, key, audience=self.cognito_client_id, options={ 'verify_exp': False, }) except jose_exceptions.JWTError as err: raise ValueError(str(err)) from None
def verify_id_token(id_token): keys = GoogleKeys.fetch_public_keys() headers = jwt.get_unverified_header(id_token) #print '--- headers ---' #print headers #print '--- claims ---' claims = json.loads(jwt.get_unverified_claims(id_token)) #print claims error_message = None if not headers.get('kid'): error_message = 'Firebase Auth ID token has no "kid" claim' elif headers.get('alg') != ALGORITHM: error_message = 'Firebase Auth ID token has incorrect algorithm' elif claims.get('aud') != PROJECT_ID: error_message = 'Firebase Auth ID token has incorrect "aud" claim' elif claims.get('iss') != 'https://securetoken.google.com/' + PROJECT_ID: error_message = 'Firebase Auth ID token has incorrect "iss" claim' elif not claims.get('sub') or len(claims['sub']) > 128: error_message = 'Firebase Auth ID token has invalid "sub" claim' if error_message: raise Exception(error_message) key = cert_to_public_rsa_key(keys[headers['kid']]) result = jwt.decode(id_token, key, algorithms=[ALGORITHM], audience=PROJECT_ID) #print '--- verification ---' #print result return result
def process_jwt_token(): authorization = request.cookies.get( 'jwt', request.headers.get( 'Authorization', None )) if authorization is None: response = make_response('Not JWT token') response.status_code = 401 return response msg = "" ss = authorization.split(' ', 1) if len(ss) != 2: msg = "Unauthorized" else: type, token = ss[0], ss[1] if type.lower() == 'bearer': try: headers = jwt.get_unverified_header(token) payload = jwt.decode( token, app.config['oauth'].get('jwt_key'), algorithms=[headers['alg']], audience=app.config['oauth']['organization'], issuer='itsyouonline') # case JWT is for an organization if 'globalid' in payload and payload['globalid'] == app.config['oauth'].get('organization'): return # case JWT is for a user if 'scope' in payload and 'user:memberof:%s' % app.config[ 'oauth'].get('organization') in payload['scope']: return msg = 'Unauthorized' except exceptions.ExpiredSignatureError as e: msg = 'Your JWT has expired' except exceptions.JOSEError as e: msg = 'JWT Error: %s' % str(e) except Exception as e: msg = 'Unexpected error : %s' % str(e) else: msg = 'Your JWT is invalid' logger.error(msg) response = make_response(msg) response.status_code = 401 return response
def _get_user_info(self, request): access_token = self._get_token_auth_header(request) id_token = request.META.get("HTTP_IDTOKEN") # JWT Validator # Per https://auth0.com/docs/quickstart/backend/python/01-authorization#create-the-jwt-validation-decorator unverified_header = jwt.get_unverified_header(id_token) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if not rsa_key: raise AuthError({"code": "rsa_key", "description": "rsa_key is empty"}, 401) try: user_info = jwt.decode( id_token, rsa_key, algorithms=['RS256'], audience=AUTH0_CLIENTID, access_token=access_token, issuer="https://"+AUTH0_DOMAIN+"/" ) return user_info except jwt.ExpiredSignatureError: raise AuthError("Token is expired") except jwt.JWTClaimsError: raise AuthError("Incorrect claims: please check the audience and issuer") except Exception: raise AuthError("Invalid header: Unable to parse authentication")
def verify_decode_jwt(token): jsonurl = urlopen(f"https://{AUTH0_DOMAIN}/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if "kid" not in unverified_header: raise AuthError( { "code": "invalid_header", "message": "Authorization malformed" }, 401) for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer="https://" + AUTH0_DOMAIN + "/") return payload except jwt.ExpiredSignatureError: raise AuthError( { "code": "token_expired", "message": "Token expired" }, 401) except jwt.JWTClaimsError: raise AuthError( { "code": "invalid_claims", "message": "Incorrect claims. Please, check the audience and issuer." }, 401, ) except Exception: raise AuthError( { "code": "invalid_header", "message": "Unable to parse authentication token" }, 400) raise AuthError( { "code": "invalid_header", "message": "Unable to find the appropriate key." }, 400)
def verify_decode_jwt(token): # Get public key from Auth0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) # Get data in header unverified_header = jwt.get_unverified_header(token) # Check validity of Auth0 token if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) rsa_key = {} for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # Verify the token if rsa_key: try: # Validate JWT using key payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def _get_user_info(self, access_token, id_token): """ Extracts the user info payload from the Id Token. Example return value: { "at_hash": "<HASH>", "aud": "<HASH>", "email_verified": true, "email": "*****@*****.**", "exp": 1551259495, "family_name": "Surname", "given_name": "Firstname", "https://sso.mozilla.com/claim/groups": [ "all_scm_level_1", "all_scm_level_2", "all_scm_level_3", # ... ], "iat": 1550654695, "iss": "https://auth.mozilla.auth0.com/", "name": "Firstname Surname", "nickname": "Firstname Surname", "nonce": "<HASH>", "picture": "<GRAVATAR_URL>", "sub": "ad|Mozilla-LDAP|fsurname", "updated_at": "2019-02-20T09:24:55.449Z", } """ # JWT Validator # Per https://auth0.com/docs/quickstart/backend/python/01-authorization#create-the-jwt-validation-decorator try: unverified_header = jwt.get_unverified_header(id_token) except jwt.JWTError: raise AuthError('Unable to decode the Id token header') if 'kid' not in unverified_header: raise AuthError('Id token header missing RSA key ID') rsa_key = None for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } break if not rsa_key: raise AuthError('Id token using unrecognised RSA key ID') try: # https://python-jose.readthedocs.io/en/latest/jwt/api.html#jose.jwt.decode user_info = jwt.decode(id_token, rsa_key, algorithms=['RS256'], audience=AUTH0_CLIENTID, access_token=access_token, issuer="https://" + AUTH0_DOMAIN + "/") return user_info except jwt.ExpiredSignatureError: raise AuthError('Id token is expired') except jwt.JWTClaimsError: raise AuthError( "Incorrect claims: please check the audience and issuer") except jwt.JWTError: raise AuthError("Invalid header: Unable to parse authentication")
def verify_decode_jwt(token): ''' @INPUTS token: a json web token (string) it should be an Auth0 token with key id (kid) it should verify the token using Auth0 /.well-known/jwks.json it should decode the payload from the token it should validate the claims return the decoded payload ''' jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 401) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 401)
def decorated(*args, **kwargs): token = get_token_auth_header() jsonurl = urlopen("https://" + AUTH0_DOMAIN + "/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError( { "code": "invalid_header1", "description": "Invalid header. " "Use an RS256 signed JWT Access Token" }, 401) if unverified_header["alg"] == "HS256": raise AuthError( { "code": "invalid_header2", "description": "Invalid header. " "Use an RS256 signed JWT Access Token" }, 401) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_IDENTIFIER, issuer="https://" + AUTH0_DOMAIN + "/") except jwt.ExpiredSignatureError: raise AuthError( { "code": "token_expired", "description": "token is expired" }, 401) except jwt.JWTClaimsError: raise AuthError( { "code": "invalid_claims", "description": "incorrect claims," " please check the audience and issuer" }, 401) except Exception: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication" " token." }, 401) _request_ctx_stack.top.current_user = payload return f(*args, **kwargs) raise AuthError( { "code": "invalid_header", "description": "Unable to find appropriate key" }, 401)
def validate_token(self, token): """ Validate token (Taken from http://openid.net/specs/openid-connect-core-1_0.html#TokenResponseValidation) """ """ Step 1 If encrypted, decrypt it using the keys and algorithms specified in the meta_data If encryption was negotiated but not provided, REJECT Skipping Okta has not implemented encrypted JWT """ try: decoded_token = jwt_python.decode(token, verify=False) except jwt_python.exceptions.DecodeError: raise InvalidToken("Unable to decode jwt") dirty_alg = jwt.get_unverified_header(token)["alg"] dirty_kid = jwt.get_unverified_header(token)["kid"] key = self._jwks(dirty_kid) if key: # Validate the key using jose-jws try: jws.verify(token, key, algorithms=[dirty_alg]) except (JWTError, JWSError) as err: raise InvalidTokenSignature("Invalid token signature") from err else: raise InvalidTokenSignature("Unable to fetch public signing key") """ Step 2 Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) MUST exactly match the value of the iss (issuer) Claim. Redundant, since we will validate in Step 3, the "iss" claim matches host we requested the token from """ if decoded_token["iss"] != self.config.issuer: """Step 3 Client MUST validate: aud (audience) contains the same `client_id` registered iss (issuer) identified as the aud (audience) aud (audience) Claim MAY contain an array with more than one element (Currently NOT IMPLEMENTED by Okta) The ID Token MUST be rejected if the ID Token does not list the Client as a valid audience, or if it contains additional audiences not trusted by the Client. """ raise IssuerDoesNotMatch("Issuer does not match") if decoded_token["aud"] != self.config.client_id: raise InvalidClientID("Audience does not match client_id") """ Step 6 : TLS server validation not implemented by Okta If ID Token is received via direct communication between Client and Token Endpoint, TLS server validation may be used to validate the issuer in place of checking token signature. MUST validate according to JWS algorithm specialized in JWT alg Header. MUST use keys provided. """ """ Step 7 The alg value SHOULD default to RS256 or sent in id_token_signed_response_alg param during Registration We don't need to test this. Okta always signs in RS256 """ """ Step 8 : Not implemented due to Okta configuration If JWT alg Header uses MAC based algorithm (HS256, HS384, etc) the octets of UTF-8 of the client_secret corresponding to the client_id are contained in the aud (audience) are used to validate the signature. For MAC based, if aud is multi-valued or if azp value is different than aud value - behavior is unspecified. """ if decoded_token["exp"] < int(time.time()): """Step 9 The current time MUST be before the time represented by exp """ raise TokenExpired if decoded_token["iat"] < (int(time.time()) - 100000): """Step 10 - Defined 'too far away time' : approx 24hrs The iat can be used to reject tokens that were issued too far away from current time, limiting the time that nonces need to be stored to prevent attacks. """ raise TokenTooFarAway("iat too far in the past ( > 1 day)") if self.nonce is not None and "nonce" in decoded_token: """Step 11 If a nonce value is sent in the Authentication Request, a nonce MUST be present and be the same value as the one sent in the Authentication Request. Client SHOULD check for nonce value to prevent replay attacks. """ if self.nonce != decoded_token["nonce"]: raise NonceDoesNotMatch( "nonce value does not match Authentication Request nonce") """ Step 12: Not implemented by Okta If acr was requested, check that the asserted Claim Value is appropriate """ """ Step 13 If auth_time was requested, check claim value and request re-authentication if too much time elapsed We relax this requirement during jwt validation. The Okta Session should be handled inside Okta See https://developer.okta.com/docs/api/resources/sessions """ return decoded_token
def verify_decode_jwt(token): #jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jsonurl = urlopen(f"https://" + AUTH0_DOMAIN + "/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) print("unver_header", unverified_header) rsa_key = {} if 'kid' not in unverified_header: print('FAIl') raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') print("payload", payload) return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Check audience and issuer' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 401) print("rsa_key", rsa_key) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to locate the appropriate key' }, 401)
async def get_current_token( security_scopes: SecurityScopes, token: str = Depends(hydra_scheme)) -> dict: async with AsyncClient() as session: resp = await session.get(settings.hydra_url + "/.well-known/jwks.json") jwks = resp.json() unverified_header = jwt.get_unverified_header(token) rsa_key = dict() for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"], } if rsa_key: try: payload = jwt.decode(token, rsa_key, audience="", algorithms=settings.hydra_algorithms, issuer=settings.hydra_issuer_url + "/", options={'verify_aud': False}) except jwt.ExpiredSignatureError as e: raise AuthError( { "code": "token_expired", "description": "Token is expired", "error": str(e) }, 401) except jwt.JWTClaimsError as e: raise AuthError( { "code": "invalid_claims", "description": "Incorrect claims, please check the audience and issuer", "error": str(e) }, 401, ) except Exception as e: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication token.", "error": str(e) }, 401, ) token_scopes = payload.get("scp", "") for scope in security_scopes.scopes: if scope not in token_scopes: raise AuthError( { "code": "Unauthorized", "description": "You don't have access to this resource. {} scopes required" .format(" ".join(security_scopes.scopes)), }, 403) return payload
def verify_decode_jwt(token): try: jwt_unverified_headers = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError({ 'status': 401, 'message': 'invalid jwt token' }, status_code=401) public_keys_url = f' https://{AUTH0_DOMAIN}/.well-known/jwks.json' response = requests.get(public_keys_url) jwks = response.json() if response.status_code == 200 else None if 'kid' not in jwt_unverified_headers: raise AuthError({ 'status': 401, 'message': 'invalid jwt token' }, status_code=401) if jwks: matched_key = {} if 'keys' in jwks: for key in jwks['keys']: if key['kid'] == jwt_unverified_headers['kid']: matched_key = key if matched_key: try: issuer = f'https://{AUTH0_DOMAIN}/' decoded_jwt = jwt.decode( token, matched_key, algorithms=JWT_TOKEN_ENCRYPTION_ALGORITHMS, audience=AUTH0_JWT_API_AUDIENCE, issuer=issuer) return decoded_jwt except jwt.ExpiredSignatureError: raise AuthError({ 'status': 401, 'message': 'token has expired' }, status_code=401) except jwt.JWTClaimsError: raise AuthError( { 'status': 401, 'message': 'invalid claim in jwt token' }, status_code=401) except jwt.JWTError: raise AuthError({ 'status': 401, 'message': 'invalid signature' }, status_code=401) except Exception: print(sys.exc_info()) raise AuthError( { 'status': 401, 'message': 'invalid auth token' }, status_code=401) except Exception: print(sys.exc_info()) raise AuthError({ 'status': 500, 'message': 'token has expired' }, status_code=500) raise AuthError( { 'code': 'invalid token', 'description': 'please provide a valid token.' }, 401) raise AuthError( { 'code': 'invalid token', 'description': 'please provide a valid token.' }, 401)
def decorated(*args, **kwargs): token = get_token_auth_header() # Commented the next two lines because they are causing data type related errors # jsonurl = urlopen("https://souhail.auth0.com/.well-known/jwks.json") # jwks = json.loads(jsonurl.read()) # The previous two lines were replace by the next two one, in order to load the json file as usual jsonurl_requests = requests.get( "https://"+AUTH0_DOMAIN+"/.well-known/jwks.json") jwks = jsonurl_requests.json() try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError({"code": "invalid_header", "description": "Invalid header. " "Use an RS256 signed JWT Access Token"}, 401) if unverified_header["alg"] == "HS256": raise AuthError({"code": "invalid_header", "description": "Invalid header. " "Use an RS256 signed JWT Access Token"}, 401) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if rsa_key: try: payload = jwt.decode( token, rsa_key, algorithms=ALGORITHMS, audience=AUTH0_AUDIENCE, issuer="https://"+AUTH0_DOMAIN+"/" ) # The next lines commented out as they are causing the mis-interpretation of the payload #, # issuer=AUTH0_DOMAIN except jwt.ExpiredSignatureError: raise AuthError({"code": "token_expired", "description": "token is expired"}, 401) except jwt.JWTClaimsError: raise AuthError({"code": "invalid_claims", "description": "incorrect claims," " please check the audience and issuer"}, 401) except Exception: raise AuthError({"code": "invalid_header", "description": "Unable to parse authentication" " token."}, 400) _request_ctx_stack.top.current_user = payload return f(*args, **kwargs) raise AuthError({"code": "invalid_header", "description": "Unable to find appropriate key"}, 400)
def verify_decode_jwt(token): """ Decodes JWT Token or raises appropiate Error Messages """ # Verify token jsonurl = urlopen(f"https://{AUTH0_DOMAIN}/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) # Check if Key id is in unverified header if "kid" not in unverified_header: raise AuthError( { "code": "invalid_header", "description": "Authorization malformed." }, 401) rsa_key = {} # initialize empty private rsa key as dict for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"], } if rsa_key: try: payload = jwt.decode( token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer="https://" + AUTH0_DOMAIN + "/", ) return payload # Raise Error if token is not valide anymore. except jwt.ExpiredSignatureError: raise AuthError( { "code": "token_expired", "description": "Token expired." }, 401) except jwt.JWTClaimsError: raise AuthError( { "code": "invalid_claims", "description": "Incorrect claims.\ Please, check the audience and issuer.", }, 401, ) except Exception: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication token.", }, 400, ) # If no payload has been returned yet, raise error. raise AuthError( { "code": "invalid_header", "description": "Unable to find the appropriate key.", }, 400, )
def verify_decode_jwt(token): """ Used to verify and decode the token NOTES: https://stackoverflow.com/questions/50236117/scraping-ssl-certificate-verify-failed-error-for-http-en-wikipedia-org :param token: :return: payload """ # GET THE PUBLIC KEY FROM AUTH0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) # GET THE DATA IN THE HEADER unverified_header = jwt.get_unverified_header(token) # CHOOSE OUR KEY rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # Verify key if rsa_key: try: # USE THE KEY TO VALIDATE THE JWT payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def check_auth(): """Determines if the Access Token is valid """ domain_base = "https://" + AUTH0_DOMAIN + "/" token = get_token_auth_header() if token in auth0_cache: return auth0_cache[token] # check token validity jsonurl = urlopen(domain_base + ".well-known/jwks.json") jwks = json.loads(jsonurl.read()) try: unverified_header = jwt.get_unverified_header(token) except JWTError: raise AuthError({"code": "improper_token", "description": "Token cannot be validated"}, 403) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } break else: raise AuthError({"code": "invalid_header", "description": "Unable to find appropriate key"}, 403) try: payload = jwt.decode( token, rsa_key, algorithms=AUTH0_ALGORITHMS, audience=AUTH0_API_AUDIENCE, issuer=domain_base ) except jwt.ExpiredSignatureError: raise AuthError({"code": "token_expired", "description": "Token is expired"}, 403) except jwt.JWTClaimsError: raise AuthError({"code": "invalid_claims", "description": "Incorrect claims," "please check the audience and issuer"}, 403) except Exception: raise AuthError({"code": "invalid_header", "description": "Unable to parse authentication" " token."}, 403) # check scope unverified_claims = jwt.get_unverified_claims(token) if unverified_claims.get("scope"): token_scopes = unverified_claims["scope"].split() for token_scope in token_scopes: if token_scope == AUTH0_REQUIRED_SCOPE: _request_ctx_stack.top.current_user = payload auth0_cache[token] = True return True raise AuthError({"code": "access_denied", "description": "Access not allowed"}, 403)
def verify_decode_jwt(token): url_string = "https://{}/.well-known/jwks.json".format(AUTH0_DOMAIN) json_url = urlopen(url_string) jwks = json.loads(json_url.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_authorization_header', 'description': 'Authorization Header is malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://{}/'.format(AUTH0_DOMAIN)) return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_authorization_header', 'description': 'Unable to parse authentication token.' }, 401) raise AuthError( { 'code': 'invalid_authorization_header', 'description': 'Unable to find the appropriate key.' }, 401)
def get_id_token_payload(token): """Determines if the access token is valid """ print("Enter get_id_token_payload") print("requires_auth token = " + token) jsonurl = urlopen("https://" + AUTH0_DOMAIN + "/.well-known/jwks.json") jwks = json.loads(jsonurl.read().decode("utf8")) print("jwks" + jsonurl.read().decode("utf8")) try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError( { "code": "invalid_header", "description": "Invalid header. " "Use an RS256 signed JWT Access Token" }, 401) if unverified_header["alg"] == "HS256": raise AuthError( { "code": "invalid_header HS", "description": "Invalid header. " "Use an HS S256 signed JWT Access Token" }, 401) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } print("rsa_key =", rsa_key) if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience="QN3TAKTeDu4U4i6tfVI2JCs7hXSxdePG", issuer="https://" + AUTH0_DOMAIN + "/") print("payload :", json.dumps(payload, indent=2)) #return json.dumps(payload, indent=2) return payload except jwt.ExpiredSignatureError: raise AuthError( { "code": "token_expired", "description": "token is expired" }, 401) except jwt.JWTClaimsError as e: print(e) #print(API_IDENTIFIER) raise AuthError( { "code": "invalid_claims", "description": "incorrect claims," " please check the audience and issuer" }, 401) except Exception: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication" " token." }, 401)
def verify_decode_jwt(token): """ Reference: - Identity and Access Management course's videos - https://github.com/udacity/FSND/tree/master/BasicFlaskAuth """ jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def verify_decode_jwt(token): # Retrieve the JSON Web Key Set (JWKS) that is used to verify JWT issued by Auth0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} # Filter out any key missing a public key and a kid property. if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) # Find the signing key using the value of the kid property. for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # Decode jwt token if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def verify_decode_jwt(token): """Verify a json web token and decode the payload from it Args: string: a json web token Returns: the decoded payload """ jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) if 'kid' not in unverified_header: raise AuthError( { 'status': 'invalid_header', 'message': 'Authorization malformed.' }, 401) rsa_key = {} for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'], } if not rsa_key: raise AuthError( { 'status': 'invalid_header', 'message': 'Unabble to find the appropriate key.' }, 401) try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer=f'https://{AUTH0_DOMAIN}/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'status': 'token_expired', 'message': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'status': 'invalid_claims', 'message': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'status': 'invalid_header', 'message': 'Unable to parse authentication token.' }, 401)
def verify_decode_jwt(token): # get the public key of the auth server jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) # decode the payload from the token unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) # if key id match, then build the RSA key for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError as ex: print(ex) raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError as ex: print(ex) raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception as ex: print(ex) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 401)
def verify_decode_jwt(self, token): json_url = urlopen(self.JSON_URL) jwks = json.loads(json_url.read()) try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError( { 'code': 401, 'message': 'Error decoding token headers.' }, 401) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 401, 'message': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=self.ALGORITHMS, audience=self.API_AUDIENCE, issuer='https://' + self.AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError({ 'code': 401, 'message': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 401, 'message': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 401, 'message': 'Unable to parse authentication token.' }, 401) raise AuthError( { 'code': 401, 'message': 'Unable to find the appropriate key.' }, 401)
def verify_decode_jwt(token): jsonurl = urlopen( f'https://{os.environ["AUTH0_DOMAIN"]}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode( token, rsa_key, algorithms=os.environ['ALGORITHMS'], audience=os.environ['API_AUDIENCE'], issuer=f'https://{os.environ["AUTH0_DOMAIN"]}/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims, please, check the audience and issuer' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key' }, 401)
def verify_decode_jwt(token): #GET THE PUBLI KEY FROM AUTH0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) #GET THE DATA IN THE HEADER unverified_header = jwt.get_unverified_header(token) print("check kid") print('kid' not in unverified_header) #CHOOSE OUR KEY rsa_key = {} if 'kid' not in unverified_header: #raise AuthError({ # 'code': 'invalid_header', # 'description': 'Authorization malformed' #}, 401) abort(401) print("kid present") for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } print("rsa key created") #Finally verify if rsa_key: try: #use the key to validate the jwt payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') print('token verified') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired' }, 401) #abort(401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims' }, 401) #abort(401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to pass token' }, 400)
def verify_decode_jwt(token): jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if not rsa_key: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400) else: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, options=JWT_VALIDATION_CONFIG, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) # catch the rest of exceptions except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) return payload
def verify_decode_jwt(token): """ Checks that jwt is valid and return decoded token in a dict Params: - token [type: str]: JWT passed from authentication - Raises [code#, code]: - [401, 'token_expired]: Token is expired - [401, 'invalid_claims]: Incorrect claims - [400, 'invalid_header]: unable to parse authentication token - [400, 'invalid_header]: Unable to find appropriate key """ # get the public key from auth0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) # get the data in header unverified_header = jwt.get_unverified_header(token) # get key rsa_key = {} if 'kid' not in unverified_header: raise AuthError({ 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: # use the key to validate the JWT payload = jwt.decode( token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/' ) return payload # token is experpied except jwt.ExpiredSignatureError: raise AuthError({ 'code': 'token_expired', 'description': 'Token expired.' }, 401) # user does not have valid claim except jwt.JWTClaimsError: raise AuthError({ 'code': 'invalid_claims', 'description': """Incorrect claims. Please check the audience and issuer.""" }, 401) # token has error except Exception: raise AuthError({ 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError({ 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def verify_decode_jwt(token): # Get public key from Auth0 jsonurl = urlopen(f"https://{AUTH0_DOMAIN}/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) # Extract header data from the token unverified_header = jwt.get_unverified_header(token) # Initialize RSA Key rsa_key = dict() # Raize 401 error if token header doesn't contain: kid if "kid" not in unverified_header: raise AuthError( {"code": "invalid_header", "description": "Authorization malformed."}, 401, ) for key in jwks["keys"]: # Create the RSA Key of a match exists if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"], } if rsa_key: try: # Validate the token payload = jwt.decode( token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer="https://" + AUTH0_DOMAIN + "/", ) return payload # Check for JWT errors except jwt.ExpiredSignatureError: raise AuthError( {"code": "token_expired", "description": "Token expired."}, 401 ) except jwt.JWTClaimsError: raise AuthError( { "code": "invalid_claims", "description": "Incorrect claims. Please, check the audience and issuer.", }, 401, ) except Exception: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication token.", }, 400, ) # Raise 400 error if Key not found raise AuthError( { "code": "invalid_header", "description": "Unable to find the appropriate key.", }, 400, )
def verify_decode_jwt(token): # Verify token jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) # Check if Key id is in unverified header if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) rsa_key = {} for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: # Use Auth Config to decode JWT payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload # Raise if token is not valid except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) # Error if wrong audience except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) # In all other Error cases except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) # raise error if no payload. raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def verify_decode_jwt(token): # GET THE PUBLIC KEY FROM AUTH0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) # GET THE DATA IN THE HEADER unverified_header = jwt.get_unverified_header(token) # CHOOSE OUR KEY rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # Finally, verify!!! if rsa_key: try: # USE THE KEY TO VALIDATE THE JWT payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def verify_jwt(request): if 'Authorization' not in request.headers: raise AuthError( { "code": "invalid_header", "description": "Invalid header. " "No authorization provided" }, 401) auth_header = request.headers['Authorization'].split() token = auth_header[1] jsonurl = urlopen("https://" + DOMAIN + "/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError: raise AuthError( { "code": "invalid_header", "description": "Invalid header. " "Use an RS256 signed JWT Access Token" }, 401) if unverified_header["alg"] == "HS256": raise AuthError( { "code": "invalid_header", "description": "Invalid header. " "Use an RS256 signed JWT Access Token" }, 401) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=CLIENT_ID, issuer="https://" + DOMAIN + "/") except jwt.ExpiredSignatureError: raise AuthError( { "code": "token_expired", "description": "token is expired" }, 401) except jwt.JWTClaimsError: raise AuthError( { "code": "invalid_claims", "description": "incorrect claims," " please check the audience and issuer" }, 401) except Exception: raise AuthError( { "code": "invalid_header", "description": "Unable to parse authentication" " token." }, 401) return payload else: raise AuthError( { "code": "no_rsa_key", "description": "No RSA key in JWKS" }, 401)
def decorated(*args, **kwargs): auth = request.headers.get('Authorization', None) if not auth: return handle_error( { 'code': 'authorization_header_missing', 'description': 'Authorization header is expected' }, 401) parts = auth.split() if parts[0].lower() != 'bearer': return handle_error( { 'code': 'invalid_header', 'description': 'Authorization header must start with' 'Bearer' }, 401) elif len(parts) == 1: return handle_error( { 'code': 'invalid_header', 'description': 'Token not found' }, 401) elif len(parts) > 2: return handle_error( { 'code': 'invalid_header', 'description': 'Authorization header must be' 'Bearer + \s + token' }, 401) token = parts[1] jsonurl = urllib.urlopen('https://' + auth0_domain + '/.well-known/jwks.json') jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=unverified_header['alg'], audience=api_audience, issuer='https://' + auth0_domain + '/') except jwt.ExpiredSignatureError: return handle_error( { 'code': 'token_expired', 'description': 'token is expired' }, 401) except jwt.JWTClaimsError: return handle_error( { 'code': 'invalid_claims', 'description': 'incorrect claims, please check the audience and issuer' }, 401) except Exception: return handle_error( { 'code': 'invalid_header', 'description': 'Unable to parse authentication' ' token.' }, 400) _app_ctx_stack.top.current_user = payload return f(*args, **kwargs) return handle_error( { 'code': 'invalid_header', 'description': 'Unable to find appropriate key' }, 400)
def verify_decode_jwt(token): # print('token passed to function',token) try: # GET THE PUBLIC KEY FROM AUTH0 jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json', context=ssl_context) # print('verify 2') jwks = json.loads(jsonurl.read()) # print('verify 3') # GET THE DATA IN THE HEADER unverified_header = jwt.get_unverified_header(token) # print('verify 4', unverified_header) # CHOOSE OUR KEY rsa_key = {} if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # Finally, verify!!! if rsa_key: try: # USE THE KEY TO VALIDATE THE JWT payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload # Expired token except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) # Token error in audience or issuer except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) # Catch any other exceptions that arise except Exception as e: traceback.print_exc() raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) # If no RSA key raise an auth error raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400) # Traceback is helping in debugging during dev except Exception as e: traceback.print_exc()
def verify_decode_jwt(token): # print('In verify', token) jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json') # print('After jsonurl') jwks = json.loads(jsonurl.read()) # print('Before unverified header', jwks) unverified_header = jwt.get_unverified_header(token) rsa_key = {} # print('before if kid', unverified_header['kid']) if 'kid' not in unverified_header: raise AuthError( { 'code': 'invalid_header', 'description': 'Authorization malformed.' }, 401) for key in jwks['keys']: if key['kid'] == unverified_header['kid']: rsa_key = { 'kty': key['kty'], 'kid': key['kid'], 'use': key['use'], 'n': key['n'], 'e': key['e'] } # print('Before rsa_key', rsa_key) if rsa_key: try: # print('Inside Try') payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer='https://' + AUTH0_DOMAIN + '/') return payload except jwt.ExpiredSignatureError: raise AuthError( { 'code': 'token_expired', 'description': 'Token expired.' }, 401) except jwt.JWTClaimsError: raise AuthError( { 'code': 'invalid_claims', 'description': 'Incorrect claims. Please, check the audience and issuer.' }, 401) except Exception: raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to parse authentication token.' }, 400) raise AuthError( { 'code': 'invalid_header', 'description': 'Unable to find the appropriate key.' }, 400)
def _get_user_info(self, access_token, id_token): """ Extracts the user info payload from the Id Token. Example return value: { "at_hash": "<HASH>", "aud": "<HASH>", "email_verified": true, "email": "*****@*****.**", "exp": 1551259495, "family_name": "Surname", "given_name": "Firstname", "https://sso.mozilla.com/claim/groups": [ "all_scm_level_1", "all_scm_level_2", "all_scm_level_3", # ... ], "iat": 1550654695, "iss": "https://auth.mozilla.auth0.com/", "name": "Firstname Surname", "nickname": "Firstname Surname", "nonce": "<HASH>", "picture": "<GRAVATAR_URL>", "sub": "ad|Mozilla-LDAP|fsurname", "updated_at": "2019-02-20T09:24:55.449Z", } """ # JWT Validator # Per https://auth0.com/docs/quickstart/backend/python/01-authorization#create-the-jwt-validation-decorator try: unverified_header = jwt.get_unverified_header(id_token) except jwt.JWTError: raise AuthError('Unable to decode the Id token header') if 'kid' not in unverified_header: raise AuthError('Id token header missing RSA key ID') rsa_key = None for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } break if not rsa_key: raise AuthError('Id token using unrecognised RSA key ID') try: # https://python-jose.readthedocs.io/en/latest/jwt/api.html#jose.jwt.decode user_info = jwt.decode( id_token, rsa_key, algorithms=['RS256'], audience=AUTH0_CLIENTID, access_token=access_token, issuer="https://"+AUTH0_DOMAIN+"/" ) return user_info except jwt.ExpiredSignatureError: raise AuthError('Id token is expired') except jwt.JWTClaimsError: raise AuthError("Incorrect claims: please check the audience and issuer") except jwt.JWTError: raise AuthError("Invalid header: Unable to parse authentication")