diff --git a/gns3server/api/routes/controller/dependencies/authentication.py b/gns3server/api/routes/controller/dependencies/authentication.py index c1647c4b..c1e05b71 100644 --- a/gns3server/api/routes/controller/dependencies/authentication.py +++ b/gns3server/api/routes/controller/dependencies/authentication.py @@ -26,13 +26,26 @@ from gns3server.db.repositories.rbac import RbacRepository from gns3server.services import auth_service from .database import get_repository -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/v3/users/login") +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/v3/users/login", auto_error=False) async def get_user_from_token( - token: str = Depends(oauth2_scheme), user_repo: UsersRepository = Depends(get_repository(UsersRepository)) + bearer_token: str = Depends(oauth2_scheme), + user_repo: UsersRepository = Depends(get_repository(UsersRepository)), + token: Optional[str] = None, ) -> schemas.User: + if bearer_token: + # bearer token is used first, then any token passed as a URL parameter + token = bearer_token + + if token is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + username = auth_service.get_username_from_token(token) user = await user_repo.get_user_by_username(username) if user is None: diff --git a/tests/api/routes/controller/test_users.py b/tests/api/routes/controller/test_users.py index 56bf0b17..042c2b32 100644 --- a/tests/api/routes/controller/test_users.py +++ b/tests/api/routes/controller/test_users.py @@ -291,6 +291,26 @@ class TestUserLogin: assert response.status_code == status_code assert "access_token" not in response.json() + async def test_user_can_use_token_as_url_param( + self, + app: FastAPI, + unauthorized_client: AsyncClient, + test_user: User, + config: Config + ) -> None: + + credentials = { + "username": test_user.username, + "password": "user1_password", + } + + response = await unauthorized_client.post(app.url_path_for("authenticate"), json=credentials) + assert response.status_code == status.HTTP_200_OK + token = response.json().get("access_token") + + response = await unauthorized_client.get(app.url_path_for("get_projects"), params={"token": token}) + assert response.status_code == status.HTTP_200_OK + class TestUserMe: