Aasher commited on
Commit
29340f0
·
1 Parent(s): 0e13f6d

feat(auth): add JWT authentication with python-jose dependency

Browse files

- Add new auth.py with JWT token verification functionality
- Include python-jose as dependency for JWT handling
- Implement OAuth2 password bearer scheme for token validation

Files changed (3) hide show
  1. api/dependencies/auth.py +39 -0
  2. pyproject.toml +1 -0
  3. uv.lock +28 -0
api/dependencies/auth.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ from pydantic import BaseModel, ValidationError
3
+
4
+ from fastapi import Depends, HTTPException, status
5
+ from fastapi.security import OAuth2PasswordBearer
6
+ from jose import JWTError, jwt
7
+
8
+ from core.config import get_settings
9
+
10
+ settings = get_settings()
11
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
12
+
13
+ class TokenPayload(BaseModel):
14
+ sub: uuid.UUID
15
+ aud: str
16
+
17
+ async def get_current_user(token: str = Depends(oauth2_scheme)) -> uuid.UUID:
18
+ """
19
+ Decodes and verifies the JWT token to get the current user.
20
+ Raises HTTPException if the token is invalid.
21
+ """
22
+ credentials_exception = HTTPException(
23
+ status_code=status.HTTP_401_UNAUTHORIZED,
24
+ detail="Could not validate credentials",
25
+ headers={"WWW-Authenticate": "Bearer"},
26
+ )
27
+ try:
28
+ payload = jwt.decode(
29
+ token,
30
+ settings.SUPABASE_JWT_SECRET,
31
+ algorithms=["HS256"],
32
+ audience="authenticated"
33
+ )
34
+ token_data = TokenPayload(**payload)
35
+
36
+ except (JWTError, ValidationError):
37
+ raise credentials_exception
38
+
39
+ return token_data.sub
pyproject.toml CHANGED
@@ -20,5 +20,6 @@ dependencies = [
20
  "pinecone>=7.3.0",
21
  "pydantic-settings>=2.10.1",
22
  "python-dotenv>=1.1.1",
 
23
  "sqlmodel>=0.0.24",
24
  ]
 
20
  "pinecone>=7.3.0",
21
  "pydantic-settings>=2.10.1",
22
  "python-dotenv>=1.1.1",
23
+ "python-jose>=3.5.0",
24
  "sqlmodel>=0.0.24",
25
  ]
uv.lock CHANGED
@@ -362,6 +362,18 @@ wheels = [
362
  { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 },
363
  ]
364
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  [[package]]
366
  name = "executing"
367
  version = "2.2.0"
@@ -1184,6 +1196,7 @@ dependencies = [
1184
  { name = "pinecone" },
1185
  { name = "pydantic-settings" },
1186
  { name = "python-dotenv" },
 
1187
  { name = "sqlmodel" },
1188
  ]
1189
 
@@ -1204,6 +1217,7 @@ requires-dist = [
1204
  { name = "pinecone", specifier = ">=7.3.0" },
1205
  { name = "pydantic-settings", specifier = ">=2.10.1" },
1206
  { name = "python-dotenv", specifier = ">=1.1.1" },
 
1207
  { name = "sqlmodel", specifier = ">=0.0.24" },
1208
  ]
1209
 
@@ -2108,6 +2122,20 @@ wheels = [
2108
  { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556 },
2109
  ]
2110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2111
  [[package]]
2112
  name = "pytz"
2113
  version = "2025.2"
 
362
  { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 },
363
  ]
364
 
365
+ [[package]]
366
+ name = "ecdsa"
367
+ version = "0.19.1"
368
+ source = { registry = "https://pypi.org/simple" }
369
+ dependencies = [
370
+ { name = "six" },
371
+ ]
372
+ sdist = { url = "https://files.pythonhosted.org/packages/c0/1f/924e3caae75f471eae4b26bd13b698f6af2c44279f67af317439c2f4c46a/ecdsa-0.19.1.tar.gz", hash = "sha256:478cba7b62555866fcb3bb3fe985e06decbdb68ef55713c4e5ab98c57d508e61", size = 201793 }
373
+ wheels = [
374
+ { url = "https://files.pythonhosted.org/packages/cb/a3/460c57f094a4a165c84a1341c373b0a4f5ec6ac244b998d5021aade89b77/ecdsa-0.19.1-py2.py3-none-any.whl", hash = "sha256:30638e27cf77b7e15c4c4cc1973720149e1033827cfd00661ca5c8cc0cdb24c3", size = 150607 },
375
+ ]
376
+
377
  [[package]]
378
  name = "executing"
379
  version = "2.2.0"
 
1196
  { name = "pinecone" },
1197
  { name = "pydantic-settings" },
1198
  { name = "python-dotenv" },
1199
+ { name = "python-jose" },
1200
  { name = "sqlmodel" },
1201
  ]
1202
 
 
1217
  { name = "pinecone", specifier = ">=7.3.0" },
1218
  { name = "pydantic-settings", specifier = ">=2.10.1" },
1219
  { name = "python-dotenv", specifier = ">=1.1.1" },
1220
+ { name = "python-jose", specifier = ">=3.5.0" },
1221
  { name = "sqlmodel", specifier = ">=0.0.24" },
1222
  ]
1223
 
 
2122
  { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556 },
2123
  ]
2124
 
2125
+ [[package]]
2126
+ name = "python-jose"
2127
+ version = "3.5.0"
2128
+ source = { registry = "https://pypi.org/simple" }
2129
+ dependencies = [
2130
+ { name = "ecdsa" },
2131
+ { name = "pyasn1" },
2132
+ { name = "rsa" },
2133
+ ]
2134
+ sdist = { url = "https://files.pythonhosted.org/packages/c6/77/3a1c9039db7124eb039772b935f2244fbb73fc8ee65b9acf2375da1c07bf/python_jose-3.5.0.tar.gz", hash = "sha256:fb4eaa44dbeb1c26dcc69e4bd7ec54a1cb8dd64d3b4d81ef08d90ff453f2b01b", size = 92726 }
2135
+ wheels = [
2136
+ { url = "https://files.pythonhosted.org/packages/d9/c3/0bd11992072e6a1c513b16500a5d07f91a24017c5909b02c72c62d7ad024/python_jose-3.5.0-py2.py3-none-any.whl", hash = "sha256:abd1202f23d34dfad2c3d28cb8617b90acf34132c7afd60abd0b0b7d3cb55771", size = 34624 },
2137
+ ]
2138
+
2139
  [[package]]
2140
  name = "pytz"
2141
  version = "2025.2"