Supabase is nice, but the functionality it provides for verifying tokens (auth.get_user
) for some inexplicable reasons makes a round trip to their end, and this trip in fact takes quite a while (up to 600ms).
JWT tokens should by their very nature be verifiable locally, provided we know the secret. Luckily Supabase does expose this JWT secret under project settings.
Here's how a FastAPI dependency to get user email and verify their authenticity using the token alone might look like:
import jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from katalystai.conf import SETTINGS
async def get_user_email(
res: Response,
cred: HTTPAuthorizationCredentials = Depends(HTTPBearer(auto_error=False)),
):
if cred is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Bearer authentication required",
headers={"WWW-Authenticate": 'Bearer realm="auth_required"'},
)
try:
jwt_result = jwt.decode(
cred.credentials,
SETTINGS.supabase_jwt_secret,
audience="authenticated",
algorithms=["HS256"],
)
return jwt_result["email"]
except jwt.exceptions.PyJWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": 'Bearer realm="auth_required"'},
)
We can then use this "middleware" like so:
from fastapi import Depends
from katalystai.auth import get_user_email
@router.post
async def create_thing(user_email: str = Depends(get_user_email)):
pass
Supabase python client overall is not that nice, it's kinda slow and unreliable. I also suggest switching to another ORM and communicating with Postgres directly instead of using their community python client. I had luck using tortoise
, which has excellent async support and clean Django-like API.
Top comments (0)