예제 #1
0
def jwt_decode_handler(token):
    options = {"verify_exp": api_settings.JWT_VERIFY_EXPIRATION}
    # get user from token, BEFORE verification, to get user secret key
    unverified_payload = jwt.decode(token, None, False)
    secret_key = jwt_get_secret_key(unverified_payload)
    verified_payload = jwt.decode(
        token,
        api_settings.JWT_PUBLIC_KEY or secret_key,
        api_settings.JWT_VERIFY,
        options=options,
        leeway=api_settings.JWT_LEEWAY,
        audience=api_settings.JWT_AUDIENCE,
        issuer=api_settings.JWT_ISSUER,
        algorithms=[api_settings.JWT_ALGORITHM],
    )
    User = get_user_model()  # noqa: N806
    user = User.objects.get(pk=verified_payload.get("id"))
    user_issued_at = timegm(user.issued_at.utctimetuple())
    if verified_payload.get('orig_iat') < user_issued_at:
        raise InvalidTokenError()
    try:
        if isinstance(token, bytes):
            token = token.decode()
        token_denied = user.denied_tokens.get(token=token)
        if token_denied:
            raise InvalidTokenError()
    except DeniedToken.DoesNotExist:
        return verified_payload
예제 #2
0
def change_user_email(token: str) -> None:
    try:
        jwt_payload = decode_jwt_token(token)
    except (
        ExpiredSignatureError,
        InvalidSignatureError,
        DecodeError,
        InvalidTokenError,
    ) as error:
        raise InvalidTokenError() from error

    if not {"exp", "new_email", "current_email"} <= set(jwt_payload):
        raise InvalidTokenError()

    new_email = sanitize_email(jwt_payload["new_email"])
    if find_user_by_email(new_email):
        return

    current_user = find_user_by_email(jwt_payload["current_email"])
    if not current_user:
        return

    current_user.email = new_email
    sessions = UserSession.query.filter_by(userId=current_user.id)
    repository.delete(*sessions)
    repository.save(current_user)

    logger.info("User has changed their email", extra={"user": current_user.id})

    return
예제 #3
0
def change_user_email(token: str) -> None:
    try:
        jwt_payload = decode_jwt_token(token)
    except (
            ExpiredSignatureError,
            InvalidSignatureError,
            DecodeError,
            InvalidTokenError,
    ) as error:
        raise InvalidTokenError() from error

    if not {"exp", "new_email", "current_email"} <= set(jwt_payload):
        raise InvalidTokenError()

    new_email = jwt_payload["new_email"]
    if User.query.filter_by(email=new_email).first():
        return

    current_email = jwt_payload["current_email"]
    current_user = User.query.filter_by(email=current_email).first()
    if not current_user:
        return

    current_user.email = new_email
    sessions = UserSession.query.filter_by(userId=current_user.id)
    repository.delete(*sessions)
    repository.save(current_user)

    return
예제 #4
0
    def wrapper(*args, **kwargs):
        mandatory_authorization_type = "Bearer "
        authorization_header = request.headers.get("Authorization")

        if authorization_header and mandatory_authorization_type in authorization_header:
            adage_jwt = authorization_header.replace(
                mandatory_authorization_type, "")
            try:
                adage_jwt_decoded = user_utils.decode_jwt_token_rs256(
                    adage_jwt)
            except InvalidSignatureError as invalid_signature_error:
                logger.error("Signature of adage jwt cannot be verified",
                             extra={"error": invalid_signature_error})
                raise ForbiddenError({"Authorization": "Unrecognized token"})
            except ExpiredSignatureError as expired_signature_error:
                logger.warning("Token has expired",
                               extra={"error": expired_signature_error})
                raise InvalidTokenError("Token expired")

            if not adage_jwt_decoded.get("exp"):
                logger.warning("Token does not contain an expiration date")
                raise InvalidTokenError("No expiration date provided")

            authenticated_information = AuthenticatedInformation(
                civility=adage_jwt_decoded.get("civilite"),
                lastname=adage_jwt_decoded.get("nom"),
                firstname=adage_jwt_decoded.get("prenom"),
                email=adage_jwt_decoded.get("mail"),
                uai=adage_jwt_decoded.get("uai"),
            )
            kwargs["authenticated_information"] = authenticated_information
            return route_function(*args, **kwargs)

        raise ForbiddenError({"Authorization": "Unrecognized token"})
예제 #5
0
    def get_jwk_from_jwt(self, unverified_header):
        try:
            token_kid = unverified_header["kid"]
        except KeyError:
            raise InvalidTokenError("Key ID header parameter is missing")

        for jwk in self.jwk_set["keys"]:
            if jwk["kid"] == token_kid:
                return jwk

        raise InvalidTokenError("no key found")
예제 #6
0
async def _jwt_access_token_decode(token):
    try:
        decoded = jwt_decode(token.encode(), **jwe_settings)
        return {"expires": decoded.get("expires"), "session_id": decoded.get("session_id")}
    except DecodeError as e:
        log.error(e)
        raise InvalidTokenError("Invalid token")
예제 #7
0
 def test_removes_invalid_tokens(self):
     error = InvalidTokenError()
     self.mock_jwt_decode.side_effect = error
     self.assertEqual(DukeDSAPIToken.objects.count(), 1,
                      'Should have one token in database')
     remove_invalid_dukeds_tokens(self.user)
     self.assertTrue(self.mock_jwt_decode.called, 'Should call jwt decode')
     self.assertEqual(DukeDSAPIToken.objects.count(), 0,
                      'Should have removed token')
예제 #8
0
 def test_fails_bad_token(self):
     error = InvalidTokenError()
     self.mock_jwt_decode.side_effect = error
     authenticated_user = self.dukeds_backend.authenticate(self.key)
     self.assertIsNone(authenticated_user,
                       'Should not authenticate user with bad token')
     self.assertTrue(self.mock_jwt_decode.called, 'Should call jwt decode')
     self.assertEqual(self.dukeds_backend.failure_reason, error,
                      'should fail because of our invalid token error')
예제 #9
0
 def decode_jwt(self, authorization_header, verify: typing.Optional[bool] = True):
     if not authorization_header:
         raise InvalidTokenError('Authorization headers is missing')
     logger.debug('found authorization header: ' +
                  str(authorization_header))
     jwt_token = authorization_header.replace('Bearer ', '')
     public_key = self.get_public_key()
     logger.debug('got public key' + str(public_key))
     decoded = self.__get_jwt_data(jwt_token, verify, public_key)
     logger.info('jwt was decoded successfully')
     logger.debug('JWT value - ' + str(decoded))
     return decoded
예제 #10
0
 def verify_token(cls, token, verify_exp=True):
     if verify_exp:
         options = None
     else:
         options = {'verify_exp': False}
     try:
         payload = jwt.decode(token,
                              current_app.secret_key,
                              verify=True,
                              algorithms=['HS512'],
                              options=options,
                              require_exp=True)
     except jwt.InvalidTokenError as e:
         raise InvalidTokenError(403, str(e))
     if any(('is_admin' not in payload, 'refresh_exp' not in payload, 'uid'
             not in payload)):
         raise InvalidTokenError(403, 'invalid token')
     # 如果刷新时间过期,则认为 token 无效
     if payload['refresh_exp'] < timegm(datetime.utcnow().utctimetuple()):
         raise InvalidTokenError(403, 'invalid token')
     u = User.query.get(payload.get('uid'))
     if u is None:
         raise InvalidTokenError(403, 'user not exist')
     return u
예제 #11
0
    def decode_auth_token(token):
        """
        Decode an authentication token provided by JWT
        :param token: The string/bytes token object
        :return: The user associated and related payload
        """
        try:
            payload = jwt.decode(token.encode(), app.config.get("SECRET_KEY"))
            user = User.query.filter(User.email == payload["sub"]).first()

            if not user:
                raise InvalidTokenError()
            return user, payload
        except jwt.ExpiredSignatureError:
            raise Unauthorized("This token has expired")
        except jwt.InvalidTokenError:
            traceback.print_exc()
            raise Unauthorized("Unable to authenticate with that information")
예제 #12
0
 def _get_claims(self, request, obj=None):  # pylint: disable=too-many-return-statements
     """Get JWT claims"""
     if self.http_header == 'Authorization':  # pylint: disable=comparison-with-callable
         try:
             if request.authorization is None:
                 return {}
         except (ValueError,
                 AttributeError):  # invalid authorization header
             return {}
         (auth_type, token) = request.authorization
         if auth_type != self.auth_type:  # pylint: disable=comparison-with-callable
             return {}
     else:
         token = request.headers.get(self.http_header)
     if not token:
         return {}
     try:
         configuration = self.configuration
         # pylint: disable=no-member
         algorithm = configuration.algorithm if configuration is not None else 'RS512'
         if algorithm.startswith('HS'):
             # pylint: disable=no-member
             key = configuration.secret if configuration is not None else None
         else:  # RS256/RS512
             # pylint: disable=no-member
             key = configuration.public_key if configuration is not None else None
         claims = jwt.decode(token,
                             key,
                             algorithms=[algorithm],
                             leeway=self.leeway,
                             audience=self.audience)
         if obj and obj != claims.get('obj'):
             raise InvalidTokenError('Bad token object!')
         return claims
     except InvalidTokenError as exc:
         LOGGER.warning('Invalid JWT token from %s: %s',
                        getattr(request, 'remote_addr', '--'), exc)
         return {}