mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2025-11-03 13:42:16 +08:00
Return 403 instead of 401 when a user is known (#705)
* return 403 instead of 401 if user is known * return 403 for unverified users * updated docs
This commit is contained in:
@ -11,7 +11,7 @@ Return a dependency callable to retrieve currently authenticated user, passing t
|
||||
|
||||
* `optional`: If `True`, `None` is returned if there is no authenticated user or if it doesn't pass the other requirements. Otherwise, throw `401 Unauthorized`. Defaults to `False`.
|
||||
* `active`: If `True`, throw `401 Unauthorized` if the authenticated user is inactive. Defaults to `False`.
|
||||
* `verified`: If `True`, throw `401 Unauthorized` if the authenticated user is not verified. Defaults to `False`.
|
||||
* `verified`: If `True`, throw `403 Forbidden` if the authenticated user is not verified. Defaults to `False`.
|
||||
* `superuser`: If `True`, throw `403 Forbidden` if the authenticated user is not a superuser. Defaults to `False`.
|
||||
|
||||
### Examples
|
||||
@ -88,7 +88,7 @@ def protected_route(user: User = Depends(fastapi_users.get_current_active_user))
|
||||
|
||||
### `get_current_verified_user`
|
||||
|
||||
Get the current active and verified user. Will throw a `401 Unauthorized` if missing or wrong credentials or if the user is not active and verified.
|
||||
Get the current active and verified user. Will throw a `401 Unauthorized` if missing or wrong credentials or if the user is not active. Will throw a `403 Forbidden` if the user is unverified.
|
||||
|
||||
```py
|
||||
@app.get("/protected-route")
|
||||
|
||||
@ -183,12 +183,13 @@ class Authenticator:
|
||||
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
if user:
|
||||
status_code = status.HTTP_403_FORBIDDEN
|
||||
if active and not user.is_active:
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
user = None
|
||||
elif verified and not user.is_verified:
|
||||
user = None
|
||||
elif superuser and not user.is_superuser:
|
||||
status_code = status.HTTP_403_FORBIDDEN
|
||||
user = None
|
||||
|
||||
if not user and not optional:
|
||||
|
||||
@ -191,7 +191,7 @@ class TestGetCurrentVerifiedUser:
|
||||
"/current-verified-user",
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
@ -253,7 +253,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
"/current-verified-superuser",
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_user(
|
||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||
@ -271,7 +271,7 @@ class TestGetCurrentVerifiedSuperuser:
|
||||
"/current-verified-superuser",
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_valid_token_verified_superuser(
|
||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserDB
|
||||
|
||||
@ -183,7 +183,7 @@ class TestLogout:
|
||||
path, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ class TestMe:
|
||||
"/me", headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
data = cast(Dict[str, Any], response.json())
|
||||
@ -159,7 +159,7 @@ class TestUpdateMe:
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
@ -181,7 +181,7 @@ class TestUpdateMe:
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
@ -204,7 +204,7 @@ class TestUpdateMe:
|
||||
"/me", json={}, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -232,7 +232,7 @@ class TestUpdateMe:
|
||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -260,7 +260,7 @@ class TestUpdateMe:
|
||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -288,7 +288,7 @@ class TestUpdateMe:
|
||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -316,7 +316,7 @@ class TestUpdateMe:
|
||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -349,7 +349,7 @@ class TestUpdateMe:
|
||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
assert after_update.called is False
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
@ -535,8 +535,6 @@ class TestGetUser:
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
else:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_verified_user(
|
||||
@ -562,7 +560,7 @@ class TestGetUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
@ -589,7 +587,7 @@ class TestGetUser:
|
||||
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -633,8 +631,6 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
else:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_verified_user(
|
||||
@ -661,7 +657,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
@ -689,7 +685,7 @@ class TestUpdateUser:
|
||||
f"/{user.id}", json={}, headers={"Authorization": f"Bearer {superuser.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -727,7 +723,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -808,7 +804,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -847,7 +843,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -886,7 +882,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
@ -930,7 +926,7 @@ class TestUpdateUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert mock_user_db.update.called is True
|
||||
@ -982,8 +978,6 @@ class TestDeleteUser:
|
||||
headers={"Authorization": f"Bearer {user.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
else:
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
async def test_verified_user(
|
||||
@ -1009,7 +1003,7 @@ class TestDeleteUser:
|
||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
@ -1040,7 +1034,7 @@ class TestDeleteUser:
|
||||
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
||||
)
|
||||
if requires_verification:
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||
else:
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
assert response.content == b""
|
||||
|
||||
Reference in New Issue
Block a user