def _verify_signature(token, pkey_data): try: # construct the public key public_key = jwk.construct(pkey_data) except JOSEError as e: raise TokenVerifyError(str(e)) from e # get the last two sections of the token, # message and signature (encoded in base64) message, encoded_signature = str(token).rsplit(".", 1) # decode the signature decoded_signature = base64url_decode(encoded_signature.encode("utf-8")) # verify the signature if not public_key.verify(message.encode("utf8"), decoded_signature): raise TokenVerifyError("Signature verification failed")
def _find_pkey(self, headers): kid = headers["kid"] # search for the kid in the downloaded public keys key_index = -1 for i in range(len(self.jwk_keys)): if kid == self.jwk_keys[i]["kid"]: key_index = i break if key_index == -1: raise TokenVerifyError("Public key not found in jwks.json") return self.jwk_keys[key_index]
def verify(self, token, current_time=None): """ https://github.com/awslabs/aws-support-tools/blob/master/Cognito/decode-verify-jwt/decode-verify-jwt.py """ if not token: raise TokenVerifyError("No token provided") headers = self._extract_headers(token) pkey_data = self._find_pkey(headers) self._verify_signature(token, pkey_data) claims = self._extract_claims(token) self._check_expiration(claims, current_time) self._check_audience(claims) self.claims = claims
def _check_audience(self, claims): # and the Audience (use claims['client_id'] if verifying an access token) audience = claims["aud"] if "aud" in claims else claims["client_id"] if audience != self.user_pool_client_id: raise TokenVerifyError("Token was not issued for this audience")
def _check_expiration(claims, current_time): if not current_time: current_time = time.time() if current_time > claims["exp"]: raise TokenVerifyError( "Token is expired") # probably another exception
def _extract_claims(token): try: claims = jwt.get_unverified_claims(token) return claims except JOSEError as e: raise TokenVerifyError(str(e)) from e
def _extract_headers(token): try: headers = jwt.get_unverified_headers(token) return headers except JOSEError as e: raise TokenVerifyError(str(e)) from e
def verify(token): if token != "good_token": raise TokenVerifyError("test")