Skip to content

Commit

Permalink
Handle UserAlreadyExists error in oauth callback route
Browse files Browse the repository at this point in the history
  • Loading branch information
frankie567 committed Jun 20, 2022
1 parent ce15284 commit f4338ca
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 11 deletions.
1 change: 1 addition & 0 deletions fastapi_users/router/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ErrorCodeReasonModel(BaseModel):
class ErrorCode(str, Enum):
REGISTER_INVALID_PASSWORD = "REGISTER_INVALID_PASSWORD"
REGISTER_USER_ALREADY_EXISTS = "REGISTER_USER_ALREADY_EXISTS"
OAUTH_USER_ALREADY_EXISTS = "OAUTH_USER_ALREADY_EXISTS"
LOGIN_BAD_CREDENTIALS = "LOGIN_BAD_CREDENTIALS"
LOGIN_USER_NOT_VERIFIED = "LOGIN_USER_NOT_VERIFIED"
RESET_PASSWORD_BAD_TOKEN = "RESET_PASSWORD_BAD_TOKEN"
Expand Down
27 changes: 17 additions & 10 deletions fastapi_users/router/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from fastapi_users import models, schemas
from fastapi_users.authentication import AuthenticationBackend, Authenticator, Strategy
from fastapi_users.exceptions import UserAlreadyExists
from fastapi_users.jwt import SecretType, decode_jwt, generate_jwt
from fastapi_users.manager import BaseUserManager, UserManagerDependency
from fastapi_users.router.common import ErrorCode, ErrorModel
Expand Down Expand Up @@ -115,16 +116,22 @@ async def callback(
except jwt.DecodeError:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)

user = await user_manager.oauth_callback(
oauth_client.name,
token["access_token"],
account_id,
account_email,
token.get("expires_at"),
token.get("refresh_token"),
request,
associate_by_email=associate_by_email,
)
try:
user = await user_manager.oauth_callback(
oauth_client.name,
token["access_token"],
account_id,
account_email,
token.get("expires_at"),
token.get("refresh_token"),
request,
associate_by_email=associate_by_email,
)
except UserAlreadyExists:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ErrorCode.OAUTH_USER_ALREADY_EXISTS,
)

if not user.is_active:
raise HTTPException(
Expand Down
31 changes: 30 additions & 1 deletion tests/test_router_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
from fastapi import FastAPI, status
from httpx_oauth.oauth2 import BaseOAuth2, OAuth2

from fastapi_users import exceptions
from fastapi_users.authentication import AuthenticationBackend, Authenticator
from fastapi_users.router.common import ErrorCode
from fastapi_users.router.oauth import (
generate_state_token,
get_oauth_associate_router,
Expand All @@ -16,7 +18,6 @@
User,
UserManagerMock,
UserModel,
UserOAuth,
UserOAuthModel,
)

Expand Down Expand Up @@ -159,6 +160,34 @@ async def test_invalid_state(

get_id_email_mock.assert_called_once_with("TOKEN")

async def test_already_exists_error(
self,
async_method_mocker: AsyncMethodMocker,
test_app_client: httpx.AsyncClient,
oauth_client: BaseOAuth2,
user_oauth: UserOAuthModel,
user_manager_oauth: UserManagerMock,
access_token: str,
):
state_jwt = generate_state_token({}, "SECRET")
async_method_mocker(oauth_client, "get_access_token", return_value=access_token)
async_method_mocker(
oauth_client, "get_id_email", return_value=("user_oauth1", user_oauth.email)
)
async_method_mocker(
user_manager_oauth, "oauth_callback"
).side_effect = exceptions.UserAlreadyExists

response = await test_app_client.get(
"/oauth/callback",
params={"code": "CODE", "state": state_jwt},
)

assert response.status_code == status.HTTP_400_BAD_REQUEST

data = cast(Dict[str, Any], response.json())
assert data["detail"] == ErrorCode.OAUTH_USER_ALREADY_EXISTS

async def test_active_user(
self,
async_method_mocker: AsyncMethodMocker,
Expand Down

0 comments on commit f4338ca

Please sign in to comment.