octicon-rss(16/)
You've already forked fastapi-users
mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2025-11-10 02:05:41 +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:
octicon-git-branch(16/)
octicon-tag(16/)
committed by
GitHub
gitea-unlock(16/)
parent
7527902e9d
commit
e59fb2c9b9
octicon-diff(16/tw-mr-1) 5 changed files with 28 additions and 33 deletions
@@ -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`.
|
* `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`.
|
* `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`.
|
* `superuser`: If `True`, throw `403 Forbidden` if the authenticated user is not a superuser. Defaults to `False`.
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@@ -88,7 +88,7 @@ def protected_route(user: User = Depends(fastapi_users.get_current_active_user))
|
|||||||
|
|
||||||
### `get_current_verified_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
|
```py
|
||||||
@app.get("/protected-route")
|
@app.get("/protected-route")
|
||||||
|
|||||||
@@ -183,12 +183,13 @@ class Authenticator:
|
|||||||
|
|
||||||
status_code = status.HTTP_401_UNAUTHORIZED
|
status_code = status.HTTP_401_UNAUTHORIZED
|
||||||
if user:
|
if user:
|
||||||
|
status_code = status.HTTP_403_FORBIDDEN
|
||||||
if active and not user.is_active:
|
if active and not user.is_active:
|
||||||
|
status_code = status.HTTP_401_UNAUTHORIZED
|
||||||
user = None
|
user = None
|
||||||
elif verified and not user.is_verified:
|
elif verified and not user.is_verified:
|
||||||
user = None
|
user = None
|
||||||
elif superuser and not user.is_superuser:
|
elif superuser and not user.is_superuser:
|
||||||
status_code = status.HTTP_403_FORBIDDEN
|
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
if not user and not optional:
|
if not user and not optional:
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ class TestGetCurrentVerifiedUser:
|
|||||||
"/current-verified-user",
|
"/current-verified-user",
|
||||||
headers={"Authorization": f"Bearer {user.id}"},
|
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(
|
async def test_valid_token_verified_user(
|
||||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||||
@@ -253,7 +253,7 @@ class TestGetCurrentVerifiedSuperuser:
|
|||||||
"/current-verified-superuser",
|
"/current-verified-superuser",
|
||||||
headers={"Authorization": f"Bearer {user.id}"},
|
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(
|
async def test_valid_token_verified_user(
|
||||||
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
self, test_app_client: httpx.AsyncClient, verified_user: UserDB
|
||||||
@@ -271,7 +271,7 @@ class TestGetCurrentVerifiedSuperuser:
|
|||||||
"/current-verified-superuser",
|
"/current-verified-superuser",
|
||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
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(
|
async def test_valid_token_verified_superuser(
|
||||||
self, test_app_client: httpx.AsyncClient, verified_superuser: UserDB
|
self, test_app_client: httpx.AsyncClient, verified_superuser: UserDB
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class TestLogout:
|
|||||||
path, headers={"Authorization": f"Bearer {user.id}"}
|
path, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class TestMe:
|
|||||||
"/me", headers={"Authorization": f"Bearer {user.id}"}
|
"/me", headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
data = cast(Dict[str, Any], response.json())
|
data = cast(Dict[str, Any], response.json())
|
||||||
@@ -159,7 +159,7 @@ class TestUpdateMe:
|
|||||||
headers={"Authorization": f"Bearer {user.id}"},
|
headers={"Authorization": f"Bearer {user.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||||
@@ -181,7 +181,7 @@ class TestUpdateMe:
|
|||||||
headers={"Authorization": f"Bearer {user.id}"},
|
headers={"Authorization": f"Bearer {user.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||||
@@ -204,7 +204,7 @@ class TestUpdateMe:
|
|||||||
"/me", json={}, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json={}, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -232,7 +232,7 @@ class TestUpdateMe:
|
|||||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -260,7 +260,7 @@ class TestUpdateMe:
|
|||||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -288,7 +288,7 @@ class TestUpdateMe:
|
|||||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -316,7 +316,7 @@ class TestUpdateMe:
|
|||||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -349,7 +349,7 @@ class TestUpdateMe:
|
|||||||
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
"/me", json=json, headers={"Authorization": f"Bearer {user.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
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
|
assert after_update.called is False
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
@@ -535,8 +535,6 @@ class TestGetUser:
|
|||||||
headers={"Authorization": f"Bearer {user.id}"},
|
headers={"Authorization": f"Bearer {user.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
|
||||||
else:
|
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
|
|
||||||
async def test_verified_user(
|
async def test_verified_user(
|
||||||
@@ -562,7 +560,7 @@ class TestGetUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||||
|
|
||||||
@@ -589,7 +587,7 @@ class TestGetUser:
|
|||||||
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -633,8 +631,6 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {user.id}"},
|
headers={"Authorization": f"Bearer {user.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
|
||||||
else:
|
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
|
|
||||||
async def test_verified_user(
|
async def test_verified_user(
|
||||||
@@ -661,7 +657,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
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}"}
|
f"/{user.id}", json={}, headers={"Authorization": f"Bearer {superuser.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -727,7 +723,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -808,7 +804,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -847,7 +843,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -886,7 +882,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
|
||||||
@@ -930,7 +926,7 @@ class TestUpdateUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
assert mock_user_db.update.called is True
|
assert mock_user_db.update.called is True
|
||||||
@@ -982,8 +978,6 @@ class TestDeleteUser:
|
|||||||
headers={"Authorization": f"Bearer {user.id}"},
|
headers={"Authorization": f"Bearer {user.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
|
||||||
else:
|
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
|
|
||||||
async def test_verified_user(
|
async def test_verified_user(
|
||||||
@@ -1009,7 +1003,7 @@ class TestDeleteUser:
|
|||||||
headers={"Authorization": f"Bearer {superuser.id}"},
|
headers={"Authorization": f"Bearer {superuser.id}"},
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||||
|
|
||||||
@@ -1040,7 +1034,7 @@ class TestDeleteUser:
|
|||||||
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
f"/{user.id}", headers={"Authorization": f"Bearer {superuser.id}"}
|
||||||
)
|
)
|
||||||
if requires_verification:
|
if requires_verification:
|
||||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
assert response.status_code == status.HTTP_403_FORBIDDEN
|
||||||
else:
|
else:
|
||||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||||
assert response.content == b""
|
assert response.content == b""
|
||||||
|
|||||||
Reference in New Issue
Block a user