コード例 #1
0
def test_signing_and_acceptance_of_multiple_algorithms(monkeypatch, user,
                                                       call_auth_endpoint,
                                                       rsa_keys):

    monkeypatch.setattr(api_settings, "JWT_PRIVATE_KEY",
                        rsa_keys["secret"]["rsa1"])
    monkeypatch.setattr(api_settings, "JWT_PUBLIC_KEY",
                        rsa_keys["public"]["rsa1"])

    for algo in [["HS256", "RS256"], ["RS256", "HS256"]]:
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)

        response = call_auth_endpoint("username", "password")
        token = response.json()["token"]

        # check needs to succeed no matter which algo is first
        algo = [algo[1], algo[0]]
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        assert response.status_code == status.HTTP_201_CREATED
        assert payload["user_id"] == user.id
        assert payload["username"] == user.get_username()

        # changing the signature raises exception
        token += "a"
        with raises(InvalidSignatureError):
            assert JSONWebTokenAuthentication.jwt_decode_token(token) == None
コード例 #2
0
def test_InvalidAlgorithmError():

    hdr = '{"alg": "bad", "typ": "JWT"}'
    jwt = b64encode(hdr.encode("ascii")) + "..".encode("ascii")

    with raises(InvalidAlgorithmError):
        assert JSONWebTokenAuthentication.jwt_decode_token(jwt) == None
コード例 #3
0
def test_keys_with_key_id(monkeypatch, user, call_auth_endpoint, rsa_keys):

    monkeypatch.setattr(api_settings, "JWT_PRIVATE_KEY",
                        {"rsa1": rsa_keys["secret"]["rsa1"]})
    monkeypatch.setattr(api_settings, "JWT_PUBLIC_KEY", rsa_keys["public"])

    secret_key = OrderedDict([("hash1", "one"), ("hash2", "two")])
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", secret_key)

    for kid, algo in {
            "hash1": ["HS256", "RS256"],
            "rsa1": ["RS256", "HS256"]
    }.items():
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)

        response = call_auth_endpoint("username", "password")
        token = response.json()["token"]

        # check needs to succeed no matter which algo is first
        algo = [algo[1], algo[0]]
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)
        hdr = get_unverified_header(token)

        assert hdr["kid"] == kid
        assert response.status_code == status.HTTP_201_CREATED
        assert payload["user_id"] == user.id
        assert payload["username"] == user.get_username()
コード例 #4
0
    def save(self, **kwargs):
        token = self.validated_data.get('token')

        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        iat = payload.get('iat', unix_epoch())
        expires_at_unix_time = iat + api_settings.JWT_EXPIRATION_DELTA.total_seconds(
        )

        # For refreshed tokens, record the token id of the original token.
        # This allows us to invalidate the whole family of tokens from
        # the same original authentication event.
        token_id = payload.get('orig_jti') or payload.get('jti')

        self.validated_data.update({
            'token_id':
            token_id,
            'user':
            check_user(payload),
            'expires_at':
            make_aware(datetime.utcfromtimestamp(expires_at_unix_time)),
        })

        # Don't store the token if we can rely on token IDs.
        # The token values are still sensitive until they expire.
        if api_settings.JWT_TOKEN_ID == 'require':
            del self.validated_data['token']

        return super(BlacklistTokenSerializer, self).save(**kwargs)
コード例 #5
0
def test_valid_credentials_return_jwt_uuid4_token_id(user, call_auth_endpoint):
    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    pattern = r'[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}\Z'
    assert re.match(pattern, payload['jti'])
コード例 #6
0
    def test_auth__valid_credentials__returns_jwt_token(self):
        response = call_auth_endpoint(self.client, "foobar", "foo")

        token = response.json()['token']
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        self.assertEqual(response.status_code, HTTP_200_OK)
        self.assertEqual(payload['user_id'], self.active_user.id)
        self.assertEqual(payload['username'], self.active_user.get_username())
コード例 #7
0
def test_valid_credentials_return_jwt_without_token_id_when_configured_off(
        monkeypatch, user, call_auth_endpoint):
    monkeypatch.setattr(api_settings, "JWT_TOKEN_ID", "off")
    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert "jti" not in payload
コード例 #8
0
def test_valid_credentials_return_jwt(user, call_auth_endpoint):
    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_200_OK
    assert payload["user_id"] == user.id
    assert payload["username"] == user.get_username()
コード例 #9
0
def test_obtain_token_command_should_produce_valid_token(monkeypatch, user):
    output = StringIO()
    monkeypatch.setattr(settings, "DEBUG", True)
    call_command('obtain_token', str(user.pk), stdout=output)
    output.seek(0)
    printed_token = output.read()

    payload = JSONWebTokenAuthentication.jwt_decode_token(
        printed_token.strip().encode())
    assert payload['user_id'] == user.pk
コード例 #10
0
def test_valid_token__returns_new_token_with_new_token_id(
        call_auth_refresh_endpoint, user):
    payload = JSONWebTokenAuthentication.jwt_create_payload(user)
    auth_token = JSONWebTokenAuthentication.jwt_encode_payload(payload)

    refresh_response = call_auth_refresh_endpoint(auth_token)
    refresh_token = refresh_response.json()["token"]
    refresh_token_payload = JSONWebTokenAuthentication.jwt_decode_token(
        refresh_token)
    assert refresh_token_payload["jti"] != str(payload["jti"])
コード例 #11
0
def _check_payload(token):
    try:
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)
    except jwt.ExpiredSignature:
        msg = _('Token has expired.')
        raise serializers.ValidationError(msg)
    except jwt.DecodeError:
        msg = _('Error decoding token.')
        raise serializers.ValidationError(msg)

    return payload
コード例 #12
0
def test_valid_token__returns_new_token_preserving_original_token_id_for_subsequent_refreshes(
        call_auth_refresh_endpoint, user):
    payload = JSONWebTokenAuthentication.jwt_create_payload(user)
    payload["orig_jti"] = uuid.uuid4()
    auth_token = JSONWebTokenAuthentication.jwt_encode_payload(payload)

    refresh_response = call_auth_refresh_endpoint(auth_token)
    refresh_token = refresh_response.json()["token"]
    refresh_token_payload = JSONWebTokenAuthentication.jwt_decode_token(
        refresh_token)
    assert refresh_token_payload["orig_jti"] == str(payload["orig_jti"])
コード例 #13
0
def test_valid_token__returns_new_token_preserving_token_id_for_first_refresh(
        call_auth_refresh_endpoint, user):
    payload = JSONWebTokenAuthentication.jwt_create_payload(user)
    auth_token = JSONWebTokenAuthentication.jwt_encode_payload(payload)
    assert "orig_jti" not in payload

    refresh_response = call_auth_refresh_endpoint(auth_token)
    refresh_token = refresh_response.json()["token"]
    refresh_token_payload = JSONWebTokenAuthentication.jwt_decode_token(
        refresh_token)
    assert refresh_token_payload["orig_jti"] == str(payload["jti"])
コード例 #14
0
def test_valid_credentials_with_no_user_id_setting_returns_jwt(
        monkeypatch, user, call_auth_endpoint):
    monkeypatch.setattr(api_settings, "JWT_PAYLOAD_INCLUDE_USER_ID", False)

    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_200_OK
    assert "user_id" not in payload
    assert payload["username"] == user.get_username()
コード例 #15
0
def test_insist_on_key_id(monkeypatch, user, call_auth_endpoint):

    secret = "averybadone"

    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", secret)

    response = call_auth_endpoint("username", "password")
    assert response.status_code == status.HTTP_201_CREATED

    token = response.json()["token"]

    # check if key is still accepted when giving it a name
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", {"kid": secret})

    payload = JSONWebTokenAuthentication.jwt_decode_token(token)
    assert payload["user_id"] == user.id
    assert payload["username"] == user.get_username()

    # check if we insist on the key beging named
    monkeypatch.setattr(api_settings, "JWT_INSIST_ON_KID", True)
    with raises(InvalidTokenError):
        assert JSONWebTokenAuthentication.jwt_decode_token(token) == None
コード例 #16
0
    def test_auth__valid_credentials_with_no_user_id_setting__returns_jwt_token(
            self, mock_settings):
        mock_settings = setup_default_mocked_api_settings(mock_settings)
        mock_settings.JWT_PAYLOAD_INCLUDE_USER_ID = False

        response = call_auth_endpoint(self.client, "foobar", "foo")

        token = response.json()['token']
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        self.assertEqual(response.status_code, HTTP_200_OK)
        self.assertNotIn('user_id', payload)
        self.assertEqual(payload['username'], self.active_user.get_username())
コード例 #17
0
def test_keys_key_id_not_found(monkeypatch, user, call_auth_endpoint):

    secret_key = OrderedDict([("hash1", "one"), ("hash2", "two")])
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", secret_key)

    response = call_auth_endpoint("username", "password")
    token = response.json()["token"]

    secret_key = OrderedDict(hash3="three")
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", secret_key)

    with raises(InvalidTokenError):
        assert JSONWebTokenAuthentication.jwt_decode_token(token) == None
コード例 #18
0
def test_multi_keys_hash_hash(monkeypatch, user, call_auth_endpoint):
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", ["key1", "key2"])

    response = call_auth_endpoint("username", "password")
    token = response.json()["token"]

    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", ["key2", "key1"])

    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_201_CREATED
    assert payload["user_id"] == user.id
    assert payload["username"] == user.get_username()
コード例 #19
0
    def test_auth__valid_credentials_with_JWT_GET_USER_SECRET_KEY_handler_set__returns_jwt_token(
            self, mock_settings):
        # Use default settings and override JWT_GET_USER_SECRET_KEY setting
        mock_settings = setup_default_mocked_api_settings(mock_settings)
        mock_settings.JWT_GET_USER_SECRET_KEY = jwt_get_user_secret_key

        response = call_auth_endpoint(self.client, "foobar", "foo")

        token = response.json()['token']
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        self.assertEqual(response.status_code, HTTP_200_OK)
        self.assertEqual(payload['user_id'], self.active_user.id)
        self.assertEqual(payload['username'], self.active_user.get_username())
コード例 #20
0
    def save(self, **kwargs):
        token = self.validated_data.get('token')

        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        iat = payload.get('iat', unix_epoch())
        expires_at_unix_time = iat + api_settings.JWT_EXPIRATION_DELTA.total_seconds()

        self.validated_data.update({
            'user': check_user(payload),
            'expires_at':
                make_aware(datetime.utcfromtimestamp(expires_at_unix_time)),
        })
        return super(BlacklistTokenSerializer, self).save(**kwargs)
コード例 #21
0
def test_valid_credentials_with_aud_and_iss_settings_return_jwt(
        monkeypatch, user, call_auth_endpoint):
    monkeypatch.setattr(api_settings, "JWT_AUDIENCE", "test-aud")
    monkeypatch.setattr(api_settings, "JWT_ISSUER", "test-iss")

    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_200_OK
    assert payload["aud"] == "test-aud"
    assert payload["iss"] == "test-iss"
    assert payload["user_id"] == user.id
    assert payload["username"] == user.get_username()
コード例 #22
0
def test_impersonation_sets_cookie(monkeypatch, user, super_user,
                                   create_authenticated_client):

    imp_cookie = "jwt-imp"
    monkeypatch.setattr(api_settings, "JWT_IMPERSONATION_COOKIE", imp_cookie)

    api_client = create_authenticated_client(super_user)

    data = {"user": user.id}
    url = reverse("impersonate")
    response = api_client.post(url, data, format="json")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    cookie_token = response.client.cookies.get(imp_cookie)
    cookie_payload = JSONWebTokenAuthentication.jwt_decode_token(
        cookie_token.value)

    assert response.status_code == status.HTTP_201_CREATED
    assert "token" in response.json()
    assert imp_cookie in response.client.cookies
    assert payload["user_id"] == user.id
    assert cookie_payload["user_id"] == user.id
コード例 #23
0
def test_superuser_can_impersonate(user, super_user,
                                   create_authenticated_client):

    api_client = create_authenticated_client(super_user)

    data = {"user": user.id}
    url = reverse("impersonate")
    response = api_client.post(url, data, format="json")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_201_CREATED
    assert "token" in response.json()
    assert payload["user_id"] == user.id
コード例 #24
0
def test_valid_credentials_with_JWT_GET_USER_SECRET_KEY_set_return_jwt(
        monkeypatch, user, call_auth_endpoint):
    def jwt_get_user_secret_key(user):
        return "{0}-{1}-{2}".format(user.pk, user.get_username(), "key")

    monkeypatch.setattr(api_settings, "JWT_GET_USER_SECRET_KEY",
                        jwt_get_user_secret_key)

    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    assert response.status_code == status.HTTP_200_OK
    assert payload["user_id"] == user.id
    assert payload["username"] == user.get_username()
コード例 #25
0
def test_valid_credentials_return_jwt_with_expected_claims(
        user, call_auth_endpoint):
    response = call_auth_endpoint("username", "password")

    token = response.json()["token"]
    payload = JSONWebTokenAuthentication.jwt_decode_token(token)

    expected_claims = {
        'jti',
        'username',
        'iat',
        'exp',
        'user_id',
        'orig_iat',
    }
    assert set(payload.keys()) == expected_claims
コード例 #26
0
def test_multi_keys_rsa_rsa(monkeypatch, user, call_auth_endpoint, rsa_keys):

    monkeypatch.setattr(api_settings, "JWT_ALGORITHM", "RS256")
    monkeypatch.setattr(api_settings, "JWT_PUBLIC_KEY",
                        list(rsa_keys["public"].values()))

    for skey in rsa_keys["secret"].values():
        monkeypatch.setattr(api_settings, "JWT_PRIVATE_KEY", skey)

        response = call_auth_endpoint("username", "password")
        token = response.json()["token"]

        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        assert response.status_code == status.HTTP_201_CREATED
        assert payload["user_id"] == user.id
        assert payload["username"] == user.get_username()
コード例 #27
0
    def test_auth__valid_credentials_with_aud_and_iss_settings__returns_jwt_token(
            self, mock_settings):
        # Use default settings and override JWT_AUDIENCE and JWT_ISSUER settings
        mock_settings = setup_default_mocked_api_settings(mock_settings)
        mock_settings.JWT_AUDIENCE = 'test-aud'
        mock_settings.JWT_ISSUER = 'test-iss'

        response = call_auth_endpoint(self.client, "foobar", "foo")

        token = response.json()['token']
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)

        self.assertEqual(response.status_code, HTTP_200_OK)
        self.assertEqual(payload['aud'], mock_settings.JWT_AUDIENCE)
        self.assertEqual(payload['iss'], mock_settings.JWT_ISSUER)
        self.assertEqual(payload['user_id'], self.active_user.id)
        self.assertEqual(payload['username'], self.active_user.get_username())
コード例 #28
0
def check_payload(token):
    from rest_framework_jwt.authentication import JSONWebTokenAuthentication

    if apps.is_installed('rest_framework_jwt.blacklist'):
        if BlacklistedToken.objects.filter(token=force_str(token)).exists():
            msg = _('Token is blacklisted.')
            raise serializers.ValidationError(msg)

    try:
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)
    except jwt.ExpiredSignature:
        msg = _('Token has expired.')
        raise serializers.ValidationError(msg)
    except jwt.DecodeError:
        msg = _('Error decoding token.')
        raise serializers.ValidationError(msg)

    return payload
def test_refreshed_token_is_blocked_by_original_id(user,
                                                   call_auth_refresh_endpoint,
                                                   monkeypatch, id_setting):
    monkeypatch.setattr(api_settings, "JWT_TOKEN_ID", id_setting)
    original_payload = JSONWebTokenAuthentication.jwt_create_payload(user)
    original_token = JSONWebTokenAuthentication.jwt_encode_payload(
        original_payload)

    refresh_response = call_auth_refresh_endpoint(original_token)
    refreshed_token = refresh_response.json()['token']
    payload = JSONWebTokenAuthentication.jwt_decode_token(refreshed_token)

    expiration = timezone.now() + timedelta(days=1)
    BlacklistedToken(
        token_id=original_payload['jti'],
        expires_at=expiration,
        user=user,
    ).save()

    assert BlacklistedToken.is_blocked(refreshed_token, payload) is True
コード例 #30
0
def check_payload(token):
    from rest_framework_jwt.authentication import JSONWebTokenAuthentication

    try:
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)
    except jwt.ExpiredSignature:
        msg = _('Token has expired.')
        raise serializers.ValidationError(msg)
    except jwt.DecodeError:
        msg = _('Error decoding token.')
        raise serializers.ValidationError(msg)
    except jwt.InvalidTokenError:
        msg = _('Invalid token.')
        raise serializers.ValidationError(msg)

    if apps.is_installed('rest_framework_jwt.blacklist'):
        from rest_framework_jwt.blacklist.models import BlacklistedToken
        if BlacklistedToken.is_blocked(token, payload):
            msg = _('Token is blacklisted.')
            raise serializers.ValidationError(msg)

    return payload