Skip to content

Commit

Permalink
refactor: Improve 2FA login flow and activate 2FA when logging in wit…
Browse files Browse the repository at this point in the history
…hout 2FA
  • Loading branch information
TanookiVerde committed Aug 31, 2024
1 parent 5de1bc9 commit 42ff25b
Showing 1 changed file with 21 additions and 29 deletions.
50 changes: 21 additions & 29 deletions app/routers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ async def login_without_2fa(
}


@router.post("/2fa/is-2fa-active/")
async def is_2fa_active(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> bool:
user = await authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)

return user.is_2fa_activated


@router.post("/2fa/login/")
async def login_with_2fa(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
Expand All @@ -58,15 +73,6 @@ async def login_with_2fa(
headers={"WWW-Authenticate": "Bearer"},
)

# Caso 1: Usuário não registrou 2FA e está tentando logar
if user.is_2fa_required and not user.is_2fa_activated:
raise HTTPException(
status_code=status.HTTP_412_PRECONDITION_FAILED,
detail="2FA not activated. Use the /2fa/enable/ endpoint",
headers={"WWW-Authenticate": "Bearer"},
)

# Caso 2: Usuário registrou 2FA e está tentando logar
secret_key = await TwoFactorAuth.get_or_create_secret_key(user.id)
two_factor_auth = TwoFactorAuth(user.id, secret_key)

Expand All @@ -77,11 +83,16 @@ async def login_with_2fa(
detail="Incorrect OTP",
headers={"WWW-Authenticate": "Bearer"},
)
if not user.is_2fa_activated:
user.is_2fa_activated = True
await user.save()

return {
"access_token": generate_user_token(user),
"token_type": "bearer",
}


@router.post("/2fa/enable/")
async def enable_2fa(
current_user: Annotated[User, Depends(get_current_frontend_user)],
Expand All @@ -94,7 +105,7 @@ async def enable_2fa(
}


@router.get("/2fa/activate/generate-qrcode/")
@router.get("/2fa/generate-qrcode/")
async def generate_qrcode(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
):
Expand All @@ -114,22 +125,3 @@ async def generate_qrcode(
raise HTTPException(status_code=404, detail="User not found")

return StreamingResponse(io.BytesIO(qr_code), media_type="image/png")


@router.post('/2fa/activate/verify-code/')
async def verify_code(
totp_code: str,
current_user: Annotated[User, Depends(get_current_frontend_user)],
):
secret_key = await TwoFactorAuth.get_or_create_secret_key(current_user.id)
two_factor_auth = TwoFactorAuth(current_user.id, secret_key)

is_valid_totp = two_factor_auth.verify_totp_code(totp_code)

if is_valid_totp:
current_user.is_2fa_activated = True
await current_user.save()

return {
'success': is_valid_totp
}

0 comments on commit 42ff25b

Please sign in to comment.