From the code snippet you provided, you seem to be using the (third-party) FastAPI-Login
package. Their documentation suggests using a custom Exception
on the LoginManager
instance, which can be used to redirect the user to the login
page, if they are not logged in.
Working example:
The authentication below is based on cookies, but you could pass the token in the Authorization
header as well. Navigate to /protected
route when you are not logged in for the redirection to take effect.
from fastapi import FastAPI, Depends, Request, Response, status
from starlette.responses import RedirectResponse, HTMLResponse, JSONResponse
from fastapi.security import OAuth2PasswordRequestForm
from fastapi_login.exceptions import InvalidCredentialsException
from fastapi_login import LoginManager
class NotAuthenticatedException(Exception):
pass
app = FastAPI()
SECRET = "super-secret-key"
manager = LoginManager(SECRET, '/login', use_cookie=True, custom_exception=NotAuthenticatedException)
DB = {
'users': {
'[email protected]': {
'name': 'John Doe',
'password': 'hunter2'
}
}
}
def query_user(user_id: str):
return DB['users'].get(user_id)
@manager.user_loader()
def load_user(user_id: str):
user = DB['users'].get(user_id)
return user
@app.exception_handler(NotAuthenticatedException)
def auth_exception_handler(request: Request, exc: NotAuthenticatedException):
"""
Redirect the user to the login page if not logged in
"""
return RedirectResponse(url='/login')
@app.get("/login", response_class=HTMLResponse)
def login_form():
return """
<!DOCTYPE html>
<html>
<body>
<form method="POST" action="/login">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" value="[email protected]"><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" value="hunter2"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
"""
@app.post('/login')
def login(data: OAuth2PasswordRequestForm = Depends()):
email = data.username
password = data.password
user = query_user(email)
if not user:
# you can return any response or error of your choice
raise InvalidCredentialsException
elif password != user['password']:
raise InvalidCredentialsException
token = manager.create_access_token(data={'sub': email})
response = RedirectResponse(url="/protected",status_code=status.HTTP_302_FOUND)
manager.set_cookie(response, token)
return response
@app.get('/protected')
def protected_route(user=Depends(manager)):
return {'user': user}
status
come from? What does login manager? I’d login manager raises, the endpoint function is never called. – Cycloparaffin