-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: OAuth and JWT based authentication
a reference implementation of password based OAuth login and JWT sessions working this commit has the get_current_user not working properly. note that this does not use pyjose but pyjwt instead REFS #52
- Loading branch information
Showing
4 changed files
with
155 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,18 @@ | |
""" | ||
from datetime import datetime | ||
from uuid import UUID | ||
from fastapi import APIRouter, Request, Depends, HTTPException | ||
|
||
from fastapi import APIRouter, Request, Depends,\ | ||
HTTPException, status | ||
from fastapi.security import OAuth2PasswordRequestForm | ||
from sqlalchemy.ext.asyncio import AsyncSession | ||
|
||
|
||
from ...db import get_async_session | ||
from ...models import User | ||
from ...schema import UserRequest,\ | ||
PasswordLoginRequest, AuthResponse | ||
from ...schema import UserRequest, UserResponse, Token | ||
from ...utils.auth import create_access_token | ||
from ..utils import get_current_user | ||
|
||
from .create import router as router_account_create | ||
from .otp import router as router_otp | ||
|
@@ -25,33 +29,41 @@ | |
router.include_router(router_account_create) | ||
router.include_router(router_otp, prefix="/otp") | ||
|
||
@router.post("/login", | ||
summary=""" Provides an endpoint for login via email and password | ||
""", | ||
response_model=AuthResponse, | ||
@router.post( | ||
"/token", | ||
summary="Provides an endpoint for login via email and password", | ||
response_model=Token, | ||
) | ||
async def login_user(request: PasswordLoginRequest, | ||
session: AsyncSession = Depends(get_async_session)): | ||
async def login_for_auth_token( | ||
form_data: OAuth2PasswordRequestForm = Depends(), | ||
session: AsyncSession = Depends(get_async_session) | ||
): | ||
""" Attempt to authenticate a user and issue JWT token | ||
""" | ||
user = await User.get_by_email(session, request.username) | ||
|
||
if user is None: | ||
raise HTTPException(status_code=401, detail="Failed to authenticate user") | ||
|
||
access_token = Authorize.create_access_token(subject=user.email,fresh=True) | ||
refresh_token = Authorize.create_refresh_token(subject=user.email) | ||
|
||
return AuthResponse(access_token=access_token, | ||
refresh_token=refresh_token, | ||
token_type="Bearer", | ||
expires_in=100) | ||
|
||
user = await User.get_by_email(session, form_data.username) | ||
|
||
if user is None or not user.check_password(form_data.password): | ||
raise HTTPException( | ||
status_code=status.HTTP_401_UNAUTHORIZED, | ||
detail="Incorrect username or password", | ||
headers={"WWW-Authenticate": "Bearer"}, | ||
) | ||
|
||
access_token = create_access_token( | ||
subject=user.email, | ||
fresh=True | ||
) | ||
|
||
return Token( | ||
access_token=access_token, | ||
token_type="bearer" | ||
) | ||
|
||
@router.post("/refresh", | ||
@router.post( | ||
"/refresh", | ||
summary=""" Provides an endpoint for refreshing the JWT token""", | ||
response_model=AuthResponse, | ||
response_model=Token, | ||
) | ||
async def refresh_jwt_token(request: Request, | ||
session: AsyncSession = Depends(get_async_session)): | ||
|
@@ -60,7 +72,8 @@ async def refresh_jwt_token(request: Request, | |
return {} | ||
|
||
|
||
@router.post("/logout", | ||
@router.post( | ||
"/logout", | ||
summary=""" Provides an endpoint for logging out the user""", | ||
) | ||
async def logout_user(session: AsyncSession = Depends(get_async_session)): | ||
|
@@ -69,25 +82,17 @@ async def logout_user(session: AsyncSession = Depends(get_async_session)): | |
""" | ||
return {} | ||
|
||
@router.get("/me", response_model=UserRequest) | ||
async def get_me(request: Request, | ||
session: AsyncSession = Depends(get_async_session) | ||
@router.get( | ||
"/me", | ||
response_model=UserResponse, | ||
) | ||
async def get_me( | ||
current_user: User = Depends(get_current_user) | ||
): | ||
"""Get the currently logged in user or myself | ||
This endpoint will return the currently logged in user or raise | ||
and exception if the user is not logged in. | ||
""" | ||
model = UserRequest( | ||
id = UUID('{12345678-1234-5678-1234-567812345678}'), | ||
first_name="Dev", | ||
last_name="Mukherjee", | ||
email="[email protected]", | ||
mobile_phone="042-1234567", | ||
verified=True, | ||
created_at=datetime.now(), | ||
updated_at=datetime.now() | ||
) | ||
|
||
return model | ||
return current_user | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters