Exemplo n.º 1
0
def fetch_jwk_for(id_token=None):
    if id_token is None:
        raise NameError('id_token is required')

    jwks_uri = "{}/v1/keys".format(config['oidc']['issuer'])

    unverified_header = jws.get_unverified_header(id_token)
    key_id = None
    if 'kid' in unverified_header:
        key_id = unverified_header['kid']
    else:
        raise ValueError('The id_token header must contain a "kid"')
    if key_id in public_key_cache:
        return public_key_cache[key_id]

    r = requests.get(jwks_uri)
    jwks = r.json()
    for key in jwks['keys']:
        jwk_id = key['kid']
        public_key_cache[jwk_id] = key

    if key_id in public_key_cache:
        return public_key_cache[key_id]
    else:
        raise RuntimeError("Unable to fetch public key from jwks_uri")
Exemplo n.º 2
0
def fetch_jwt_public_key_for(id_token=None):
    if id_token is None:
        raise NameError('id_token is required')

    dirty_header = jws.get_unverified_header(id_token)
    cleaned_key_id = None
    if 'kid' in dirty_header:
        dirty_key_id = dirty_header['kid']
        cleaned_key_id = re.sub(not_alpha_numeric, '', dirty_key_id)
    else:
        raise ValueError('The id_token header must contain a "kid"')
    if cleaned_key_id in public_keys:
        return public_keys[cleaned_key_id]

    unverified_claims = jwt.get_unverified_claims(id_token)
    dirty_url = urlparse.urlparse(unverified_claims['iss'])
    if domain_name_for(dirty_url) not in allowed_domains:
        raise ValueError('The domain in the issuer claim is not allowed')
    cleaned_issuer = dirty_url.geturl()
    oidc_discovery_url = "{}/.well-known/openid-configuration".format(
        cleaned_issuer)
    r = requests.get(oidc_discovery_url)
    openid_configuration = r.json()
    jwks_uri = openid_configuration['jwks_uri']
    r = requests.get(jwks_uri)
    jwks = r.json()
    for key in jwks['keys']:
        jwk_id = key['kid']
        public_keys[jwk_id] = key

    if cleaned_key_id in public_keys:
        return public_keys[cleaned_key_id]
    else:
        raise RuntimeError("Unable to fetch public key from jwks_uri")
Exemplo n.º 3
0
def checkJWKS(token):
    jwks = False
    tokendecode = None
    tokendecodeheader = None
    pubcert = None
    message = None
    #not a JWT at all -- not an error condition, just a reality.
    try:
        tokendecode = jjws.get_unverified_claims(token)
        tokendecodeheader = jjws.get_unverified_header(token)
        jwks = True
    except Exception as e:
        print(e)
        return False

    for uri in JWKSUri.objects.all():
        jwks_json = _getjwks(uri.URL)
        if not jwks_json:
            break
        for key in jwks_json.get('keys', None):
            try:
                jwks = _decode_with_cert(token, key, hint=uri.hint)
                if jwks:
                    return jwks
            except Exception as e:
                print("check JWKS %s" % e)
                continue
        continue
    return False
Exemplo n.º 4
0
def fetch_jwk_for(issuer, id_token=None):
    if id_token is None:
        raise NameError('id_token is required')

    # FIXME: This should be pulled from the OpenID connect Discovery Document
    jwks_uri = '{}/v1/keys'.format(issuer)

    unverified_header = jws.get_unverified_header(id_token)
    key_id = None

    if 'kid' in unverified_header:
        key_id = unverified_header['kid']
    else:
        raise ValueError('The id_token header must contain a "kid"')

    if key_id in settings.PUBLIC_KEY_CACHE:
        return settings.PUBLIC_KEY_CACHE[key_id]

    r = requests.get(jwks_uri)
    jwks = r.json()

    for key in jwks['keys']:
        jwk_id = key['kid']
        settings.PUBLIC_KEY_CACHE[jwk_id] = key

    if key_id in settings.PUBLIC_KEY_CACHE:
        return settings.PUBLIC_KEY_CACHE[key_id]
    else:
        raise RuntimeError('Unable to fetch public key from jwks_uri')
Exemplo n.º 5
0
def fetch_jwt_public_key_for(id_token=None):
    if id_token is None:
        raise NameError('id_token is required')

    dirty_header = jws.get_unverified_header(id_token)
    cleaned_key_id = None
    if 'kid' in dirty_header:
        dirty_key_id = dirty_header['kid']
        cleaned_key_id = re.sub(not_alpha_numeric, '', dirty_key_id)
    else:
        raise ValueError('The id_token header must contain a "kid"')
    if cleaned_key_id in public_keys:
        return public_keys[cleaned_key_id]

    unverified_claims = jwt.get_unverified_claims(id_token)
    dirty_url = urlparse.urlparse(unverified_claims['iss'])
    if domain_name_for(dirty_url) not in allowed_domains:
        raise ValueError('The domain in the issuer claim is not allowed')
    cleaned_issuer = dirty_url.geturl()
    oidc_discovery_url = "{}/.well-known/openid-configuration".format(
        cleaned_issuer)
    r = requests.get(oidc_discovery_url)
    openid_configuration = r.json()
    jwks_uri = openid_configuration['jwks_uri']
    r = requests.get(jwks_uri)
    jwks = r.json()
    for key in jwks['keys']:
        jwk_id = key['kid']
        public_keys[jwk_id] = key

    if cleaned_key_id in public_keys:
        return public_keys[cleaned_key_id]
    else:
        raise RuntimeError("Unable to fetch public key from jwks_uri")
Exemplo n.º 6
0
 def _try_decode(self, openid_credentials: dict) -> dict:
     id_token = openid_credentials["id_token"]
     # "access_token" must only be provided if claim is provided, else "jwt.decode" throws...
     if b"at_hash" in jws.get_unverified_claims(id_token):
         access_token = openid_credentials["access_token"]
     else:
         access_token = None
     header = jws.get_unverified_header(id_token)
     verified_id_token = jwt.decode(
         id_token,
         self._jwk_pkey.key(header["kid"]),
         issuer=self._issuer,
         access_token=access_token,
         audience=self._client_id,
     )
     return verified_id_token
Exemplo n.º 7
0
    def __checkJwsExpiration(self, payload):
        '''
        Check if JWS signature has not expired.
        '''

        header = jws.get_unverified_header(payload)

        if 'exp' not in header:
            raise HyperwalletException('While trying to verify JWS signature no [exp] header is found')

        exp = header['exp']

        if not isinstance(exp, (int, long)):
            raise HyperwalletException('Wrong value in [exp] header of JWS signature, must be integer')

        if exp < int(time.time()):
            raise HyperwalletException('JWS signature has expired, checked by [exp] JWS header')
Exemplo n.º 8
0
def _decode_with_cert(token, key, hint=None):
    kid = key.get('kid', None)
    tokenkid = None
    pubcert = None
    jwtson = None

    tokendecode = jjws.get_unverified_claims(token)
    tokenkid = jjws.get_unverified_header(token).get("kid")

    if (tokenkid and kid) and (kid == tokenkid):
        try:
            jwtson = jjwt.decode(token,
                                 key,
                                 algorithms='RS256',
                                 options={'verify_aud': False})
            return jwtson
        except Exception as e:
            print("kid in token: Cannot be introspected in JWKS %s" % e)
Exemplo n.º 9
0
def jwt_launch_via_json():
    from jose import jwk, jws, jwt
    from jose.utils import base64url_decode
    import requests

    #from keys import public_key, private_key
    print("=-=-=-=-=-=- REQUEST FORM -=-=-=-=-=")
    print(json.dumps(request.form, indent=2))

    #jwt
    id_token = request.form.get('id_token')
    audience = '407321823'

    #key id
    kid = jws.get_unverified_header(id_token)['kid']

    #get platform web keys from lti-ri
    r = requests.get(settings.JSON_KEY_URL)

    #todo - get key based on KID
    web_keys = r.json()['keys'][0]

    #create key from web keys
    key = jwk.construct(web_keys)

    try:
        #Verify JWT
        lti_data = jwt.decode(id_token,
                              web_keys,
                              algorithms=['RS256'],
                              audience=audience)

        print("=-=-=-=-=-=- LTI DATA -=-=-=-=-=")
        print(lti_data)

        return "Hello %s! <br> JWT Successfully Decoded and verified." % lti_data[
            'name']

    except:
        return "There was an error verifying the JWT."

    return "Should not get here"
Exemplo n.º 10
0
def decode(token, key, algorithms=None, options=None, audience=None,
           issuer=None, subject=None, access_token=None):
    """Verifies a JWT string's signature and validates reserved claims.

    Args:
        token (str): A signed JWS to be verified.
        key (str or dict): A key to attempt to verify the payload with. Can be
            individual JWK or JWK set.
        algorithms (str or list): Valid algorithms that should be used to verify the JWS.
        audience (str): The intended audience of the token.  If the "aud" claim is
            included in the claim set, then the audience must be included and must equal
            the provided claim.
        issuer (str or iterable): Acceptable value(s) for the issuer of the token.
            If the "iss" claim is included in the claim set, then the issuer must be
            given and the claim in the token must be among the acceptable values.
        subject (str): The subject of the token.  If the "sub" claim is
            included in the claim set, then the subject must be included and must equal
            the provided claim.
        access_token (str): An access token string. If the "at_hash" claim is included in the
            claim set, then the access_token must be included, and it must match
            the "at_hash" claim.
        options (dict): A dictionary of options for skipping validation steps.

            defaults = {
                'verify_signature': True,
                'verify_aud': True,
                'verify_iat': True,
                'verify_exp': True,
                'verify_nbf': True,
                'verify_iss': True,
                'verify_sub': True,
                'verify_jti': True,
                'verify_at_hash': True,
                'require_aud': False,
                'require_iat': False,
                'require_exp': False,
                'require_nbf': False,
                'require_iss': False,
                'require_sub': False,
                'require_jti': False,
                'require_at_hash': False,
                'leeway': 0,
            }

    Returns:
        dict: The dict representation of the claims set, assuming the signature is valid
            and all requested data validation passes.

    Raises:
        JWTError: If the signature is invalid in any way.
        ExpiredSignatureError: If the signature has expired.
        JWTClaimsError: If any claim is invalid in any way.

    Examples:

        >>> payload = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8'
        >>> jwt.decode(payload, 'secret', algorithms='HS256')

    """

    defaults = {
        'verify_signature': True,
        'verify_aud': True,
        'verify_iat': True,
        'verify_exp': True,
        'verify_nbf': True,
        'verify_iss': True,
        'verify_sub': True,
        'verify_jti': True,
        'verify_at_hash': True,
        'require_aud': False,
        'require_iat': False,
        'require_exp': False,
        'require_nbf': False,
        'require_iss': False,
        'require_sub': False,
        'require_jti': False,
        'require_at_hash': False,
        'leeway': 0,
    }

    if options:
        defaults.update(options)

    verify_signature = defaults.get('verify_signature', True)

    try:
        payload = jws.verify(token, key, algorithms, verify=verify_signature)
    except JWSError as e:
        raise JWTError(e)

    # Needed for at_hash verification
    algorithm = jws.get_unverified_header(token)['alg']

    try:
        claims = json.loads(payload.decode('utf-8'))
    except ValueError as e:
        raise JWTError('Invalid payload string: %s' % e)

    if not isinstance(claims, Mapping):
        raise JWTError('Invalid payload string: must be a json object')

    _validate_claims(claims, audience=audience, issuer=issuer,
                     subject=subject, algorithm=algorithm,
                     access_token=access_token,
                     options=defaults)

    return claims
Exemplo n.º 11
0
def decode(token, key, algorithms=None, options=None, audience=None,
           issuer=None, subject=None, access_token=None):
    """Verifies a JWT string's signature and validates reserved claims.

    Args:
        token (str): A signed JWS to be verified.
        key (str): A key to attempt to verify the payload with.
        algorithms (str or list): Valid algorithms that should be used to verify the JWS.
        audience (str): The intended audience of the token.  If the "aud" claim is
            included in the claim set, then the audience must be included and must equal
            the provided claim.
        issuer (str or iterable): Acceptable value(s) for the issuer of the token.
            If the "iss" claim is included in the claim set, then the issuer must be
            given and the claim in the token must be among the acceptable values.
        subject (str): The subject of the token.  If the "sub" claim is
            included in the claim set, then the subject must be included and must equal
            the provided claim.
        access_token (str): An access token returned alongside the id_token during
            the authorization grant flow. If the "at_hash" claim is included in the
            claim set, then the access_token must be included, and it must match
            the "at_hash" claim.
        options (dict): A dictionary of options for skipping validation steps.

            defaults = {
                'verify_signature': True,
                'verify_aud': True,
                'verify_iat': True,
                'verify_exp': True,
                'verify_nbf': True,
                'verify_iss': True,
                'verify_sub': True,
                'verify_jti': True,
                'leeway': 0,
            }

    Returns:
        dict: The dict representation of the claims set, assuming the signature is valid
            and all requested data validation passes.

    Raises:
        JWTError: If the signature is invalid in any way.

    Examples:

        >>> payload = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8'
        >>> jwt.decode(payload, 'secret', algorithms='HS256')

    """

    defaults = {
        'verify_signature': True,
        'verify_aud': True,
        'verify_iat': True,
        'verify_exp': True,
        'verify_nbf': True,
        'verify_iss': True,
        'verify_sub': True,
        'verify_jti': True,
        'verify_at_hash': True,
        'leeway': 0,
    }

    if options:
        defaults.update(options)

    verify_signature = defaults.get('verify_signature', True)

    try:
        payload = jws.verify(token, key, algorithms, verify=verify_signature)
    except JWSError as e:
        raise JWTError(e)

    # Needed for at_hash verification
    algorithm = jws.get_unverified_header(token)['alg']

    try:
        claims = json.loads(payload.decode('utf-8'))
    except ValueError as e:
        raise JWTError('Invalid payload string: %s' % e)

    if not isinstance(claims, Mapping):
        raise JWTError('Invalid payload string: must be a json object')

    _validate_claims(claims, audience=audience, issuer=issuer,
                     subject=subject, algorithm=algorithm,
                     access_token=access_token,
                     options=defaults)

    return claims
Exemplo n.º 12
0
def get_token_algorithm(token):
    unverified_header = jws.get_unverified_header(token)
    return unverified_header.get('alg')