Ejemplo n.º 1
0
    def validate_and_return_id_token(self, id_token, access_token):
        """
        Validates the id_token according to the steps at
        http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation.
        """
        client_id, client_secret = self.get_key_and_secret()

        key = self.find_valid_key(id_token)
        alg = key['alg']
        rsakey = jwk.construct(key)

        try:
            claims = jwt.decode(
                id_token,
                rsakey.to_pem().decode('utf-8'),
                algorithms=[alg],
                audience=client_id,
                issuer=self.id_token_issuer(),
                access_token=access_token,
                options=self.JWT_DECODE_OPTIONS,
            )
        except ExpiredSignatureError:
            raise AuthTokenError(self, 'Signature has expired')
        except JWTClaimsError:
            raise AuthTokenError(self, 'Invalid claims')
        except JWTError:
            raise AuthTokenError(self, 'Invalid signature')

        self.validate_claims(claims)

        return claims
Ejemplo n.º 2
0
    def validate_and_return_id_token(self, id_token, access_token):
        """
        Validates the id_token according to the steps at
        http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation.
        """
        client_id, client_secret = self.get_key_and_secret()

        key = self.find_valid_key(id_token)

        if not key:
            raise AuthTokenError(self, 'Signature verification failed')

        rsakey = jwk.construct(key, algorithm=ALGORITHMS.RS256)

        try:
            claims = jwt.decode(
                id_token,
                rsakey.to_pem().decode('utf-8'),
                algorithms=[ALGORITHMS.HS256, ALGORITHMS.RS256, ALGORITHMS.ES256],
                audience=client_id,
                issuer=self.id_token_issuer(),
                access_token=access_token,
                options=self.JWT_DECODE_OPTIONS,
            )
        except ExpiredSignatureError:
            raise AuthTokenError(self, 'Signature has expired')
        except JWTClaimsError as error:
            raise AuthTokenError(self, str(error))
        except JWTError:
            raise AuthTokenError(self, 'Invalid signature')

        self.validate_claims(claims)
    def request_access_token(self, *args, **kwargs):
        response = super(ADFSOAuth2, self).request_access_token(*args, **kwargs)

        try:
            self.token_payload = jwt.decode(
                response.get('access_token'),
                audience=self.get_scope_argument()[self.SCOPE_PARAMETER_NAME],
                key=self.get_token_key(),
                leeway=self.setting('LEEWAY', 0),
                iss=self.issuer_url(),
                options=dict(
                    verify_signature=True,
                    verify_exp=True,
                    verify_nbf=False,
                    verify_iat=self.setting('VERIFY_IAT', True),
                    verify_aud=True,
                    verify_iss=True,
                    require_exp=True,
                    require_iat=True,
                    require_nbf=False
                )
            )
        except jwt.InvalidTokenError as exc:
            raise AuthTokenError(self, exc)

        return response
Ejemplo n.º 4
0
    def user_data(self, access_token, *args, **kwargs):
        response = kwargs.get('response')
        id_token = response.get('id_token')

        # decode the JWT header as JSON dict
        jwt_header = json.loads(
            base64.b64decode(id_token.split('.', 1)[0]).decode()
        )

        # get key id and algorithm
        key_id = jwt_header['kid']
        algorithm = jwt_header['alg']
        verify = os.environ.get('OAUTH2_VERIFY', False)
        key = ''
        try:
            # retrieve certificate for key_id
            if verify:
                certificate = self.get_certificate(key_id)
                key = certificate.public_key()

            return jwt_decode(
                id_token,
                verify=verify,
                key=key,
                algorithms=algorithm,
                audience=self.setting('KEY')
            )
        except (DecodeError, ExpiredSignature) as error:
            raise AuthTokenError(self, error)
Ejemplo n.º 5
0
    def validate_claims(self, id_token):
        if id_token['iss'] != self.id_token_issuer():
            raise AuthTokenError(self, 'Invalid issuer')

        client_id, __ = self.get_key_and_secret()

        if isinstance(id_token['aud'], six.string_types):
            id_token['aud'] = [id_token['aud']]

        if client_id not in id_token['aud']:
            raise AuthTokenError(self, 'Invalid audience')

        if len(id_token['aud']) > 1 and 'azp' not in id_token:
            raise AuthTokenError(self, 'Incorrect id_token: azp')

        if 'azp' in id_token and id_token['azp'] != client_id:
            raise AuthTokenError(self, 'Incorrect id_token: azp')

        utc_timestamp = timegm(datetime.datetime.utcnow().utctimetuple())
        if utc_timestamp > id_token['exp']:
            raise AuthTokenError(self, 'Signature has expired')

        if 'nbf' in id_token and utc_timestamp < id_token['nbf']:
            raise AuthTokenError(self, 'Incorrect id_token: nbf')

        # Verify the token was issued in the last 10 minutes
        iat_leeway = self.setting('ID_TOKEN_MAX_AGE', self.ID_TOKEN_MAX_AGE)
        if utc_timestamp > id_token['iat'] + iat_leeway:
            raise AuthTokenError(self, 'Incorrect id_token: iat')
Ejemplo n.º 6
0
    def validate_claims(self, id_token):
        """Validate decoded JWT token."""

        if id_token["iss"] != self.id_token_issuer():
            raise AuthTokenError(self, "Invalid issuer")

        client_id = self.setting("KEY")

        if isinstance(id_token["aud"], str):
            id_token["aud"] = [id_token["aud"]]

        if client_id not in id_token["aud"]:
            raise AuthTokenError(self, "Invalid audience")

        if len(id_token["aud"]) > 1 and "azp" not in id_token:
            raise AuthTokenError(self, "Incorrect id_token: azp")

        if "azp" in id_token and id_token["azp"] != client_id:
            raise AuthTokenError(self, "Incorrect id_token: azp")

        utc_timestamp = timegm(datetime.datetime.utcnow().utctimetuple())
        if utc_timestamp > id_token["exp"]:
            raise AuthTokenError(self, "Signature has expired")

        if "nbf" in id_token and utc_timestamp < id_token["nbf"]:
            raise AuthTokenError(self, "Incorrect id_token: nbf")

        # Verify the token was issued in the last 10 minutes
        iat_leeway = self.setting("ID_TOKEN_MAX_AGE", self.ID_TOKEN_MAX_AGE)
        if utc_timestamp > id_token["iat"] + iat_leeway:
            raise AuthTokenError(self, "Incorrect id_token: iat")
Ejemplo n.º 7
0
    def validate_claims(self, id_token):
        utc_timestamp = timegm(datetime.datetime.utcnow().utctimetuple())

        if 'nbf' in id_token and utc_timestamp < id_token['nbf']:
            raise AuthTokenError(self, 'Incorrect id_token: nbf')

        # Verify the token was issued in the last 10 minutes
        iat_leeway = self.setting('ID_TOKEN_MAX_AGE', self.ID_TOKEN_MAX_AGE)
        if utc_timestamp > id_token['iat'] + iat_leeway:
            raise AuthTokenError(self, 'Incorrect id_token: iat')

        # Validate the nonce to ensure the request was not modified
        nonce = id_token.get('nonce')
        if not nonce:
            raise AuthTokenError(self, 'Incorrect id_token: nonce')

        nonce_obj = self.get_nonce(nonce)
        if nonce_obj:
            self.remove_nonce(nonce_obj.id)
        else:
            raise AuthTokenError(self, 'Incorrect id_token: nonce')
Ejemplo n.º 8
0
    def get_unauthorized_token(self):
        """Get unauthorized token from session passed on state parameter."""
        unauthed_tokens = self.session.get('_utoken')
        if not unauthed_tokens:
            raise AuthTokenError(self, 'Missing unauthorized token')

        data_token = self.data.get(self.OAUTH_TOKEN_PARAMETER_NAME)

        if data_token is None:
            raise AuthTokenError(self, 'Missing unauthorized token')

        token = None
        utoken = unauthed_tokens
        orig_utoken = utoken
        if not isinstance(utoken, dict):
            utoken = parse_qs(utoken)
        if utoken.get(self.OAUTH_TOKEN_PARAMETER_NAME) == data_token:
            token = utoken
        else:
            raise AuthTokenError(self, 'Incorrect tokens')
        return token
Ejemplo n.º 9
0
    def validate_and_return_id_token(self, id_token, access_token):
        """
        Validates the id_token according to the steps at
        http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation.
        """
        key = self.find_valid_key(id_token)

        if not key:
            raise AuthTokenError(self, "Signature verification failed")

        alg = key["alg"]
        rsa_key = jwk.construct(key)

        k = {
            "alg":
            rsa_key._algorithm,  # pylint: disable=protected-access
            "kty":
            "oct",
            "k":
            base64.urlsafe_b64encode(
                rsa_key.prepared_key).rstrip(b"=").decode("utf-8"),
        }

        try:
            claims = jwt.decode(
                id_token,
                k,
                algorithms=[alg],
                audience=self.setting("KEY"),
                issuer=self.id_token_issuer(),
                options=self.JWT_DECODE_OPTIONS,
            )
        except ExpiredSignatureError as error:
            raise AuthTokenError(self, "Signature has expired") from error
        except JWTClaimsError as error:
            raise AuthTokenError(self, str(error)) from error
        except JWTError as error:
            raise AuthTokenError(self, "Invalid signature") from error

        self.validate_claims(claims)
Ejemplo n.º 10
0
    def validate_logout_claims(self, id_token: dict) -> None:
        """ Validated logout_token claims
            http://openid.net/specs/openid-connect-backchannel-1_0.html#LogoutToken
         """

        if id_token['iss'] != self.id_token_issuer():
            raise AuthTokenError(self, 'Invalid issuer')

        client_id, _ = self.get_key_and_secret()

        if isinstance(id_token['aud'], str):
            id_token['aud'] = [id_token['aud']]

        if client_id not in id_token['aud']:
            raise AuthTokenError(self, 'Invalid audience')

        if len(id_token['aud']) > 1 and 'azp' not in id_token:
            raise AuthTokenError(self, 'Incorrect logout_token: azp')

        utc_timestamp = timegm(datetime.datetime.utcnow().utctimetuple())
        if 'exp' in id_token and utc_timestamp > id_token['exp']:
            raise AuthTokenError(self, 'Signature has expired')

        # Verify the token was issued in the last 10 minutes
        iat_leeway = self.setting('ID_TOKEN_MAX_AGE', self.ID_TOKEN_MAX_AGE)
        if utc_timestamp > id_token['iat'] + iat_leeway:
            raise AuthTokenError(self, 'Incorrect logout_token: iat')

        if 'sid' not in id_token:
            raise AuthTokenError(self, 'Incorrect logout_token: sid')
Ejemplo n.º 11
0
    def validate_and_return_logout_token(
            self, jws: str) -> dict:  # noqa invalid-name
        """ Validated logout_token """
        try:
            # Decode the JWT and raise an error if the sig is invalid
            id_token = JWS().verify_compact(jws.encode('utf-8'),
                                            self.get_jwks_keys())
        except JWKESTException:
            raise AuthTokenError(self, 'Signature verification failed')

        self.validate_logout_claims(id_token)

        return id_token
Ejemplo n.º 12
0
    def user_data(self, access_token, *args, **kwargs):
        response = kwargs.get('response')
        id_token = response.get('id_token')

        # get key id and algorithm
        key_id = get_unverified_header(id_token)['kid']
        key = ''
        verify = os.environ.get('OAUTH2_VERIFY', False)
        try:
            # retrieve certificate for key_id
            if verify:
                certificate = self.get_certificate(key_id)
                key = certificate.public_key()

            options = {'verify_signature': verify}
            return jwt_decode(
                id_token,
                key=key,
                algorithms=['RS256'],
                audience=self.setting('KEY'),
                options=options,
            )
        except (DecodeError, ExpiredSignatureError) as error:
            raise AuthTokenError(self, error)