'How to redirect to login in FastApi
I am looking to get a simple login sequence on fastapi: following This tutorial
from fastapi import FastAPI, Depends, HTTPException
from starlette.config import Config
from starlette.requests import Request
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import HTMLResponse, RedirectResponse
from authlib.integrations.starlette_client import OAuth, OAuthError
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="!secret")
config = Config(".env")
oauth = OAuth(config)
CONF_URL = "https://accounts.google.com/.well-known/openid-configuration"
oauth.register(
name="google",
server_metadata_url=CONF_URL,
client_kwargs={"scope": "openid email profile"},
)
@app.get("/")
async def home(request: Request):
user = request.session.get("user")
if user is not None:
email = user["email"]
html = (
f"<pre>Email: {email}</pre><br>"
'<a href="/docs">documentation</a><br>'
'<a href="/logout">logout</a>'
)
return HTMLResponse(html)
return HTMLResponse('<a href="/login">login</a>')
@app.get("/login", tags=["authentication"])
async def login(request: Request):
redirect_uri = request.url_for("auth")
return await oauth.google.authorize_redirect(request, redirect_uri)
@app.get("/auth")
async def auth(request: Request):
try:
token = await oauth.google.authorize_access_token(request)
except OAuthError as error:
return HTMLResponse(f"<h1>{error.error}</h1>")
user = token.get("userinfo")
if user:
request.session["user"] = dict(user)
return RedirectResponse(url="/")
@app.get("/logout", tags=["authentication"])
async def logout(request: Request):
request.session.pop("user", None)
return RedirectResponse(url="/")
# Try to get the logged in user
async def get_user(request: Request) -> Optional[dict]:
user = request.session.get("user")
if user is not None:
return user
else:
raise HTTPException(status_code=403, detail="Could not validate credentials.")
return None
# Endpoint to protect
@app.get("/other_endpoint/")
async def other_endpoint_function(
user: Optional[dict] = Depends(get_user), id: str
):
# Chek if other is authenticated
if user.is_authenticated:
function()
else:
# First redirect to the login page
RedirectResponse("login")
# Once logged in re-run the initial request
RedirectResponse(f"/other_endpoint/{id}")
I am looking to protect only the other_endpoint the homepage has a link to the login page.
- check that the user is authenticated before running the function
- If the user is authenticated, run function
- If the user is not authenticated
- redirect to the login page
- re-run the function after authentication
So far, I have tried multiple implementations with RedirectResponse, but i ends up bypassing the authentication
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
