GitHub Actions commited on
Commit
76ca861
Β·
1 Parent(s): e4b4e15

πŸš€ Auto-deploy from GitHub

Browse files
app/api/v1/endpoints/auth.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Authentication endpoints for token management
3
+ """
4
+ from fastapi import APIRouter, HTTPException, Depends
5
+ from datetime import datetime, timedelta
6
+ from typing import Dict, Any
7
+ import jwt
8
+ import os
9
+ from ..schemas.auth_schemas import TokenRequest, TokenResponse
10
+ from ....core.config import settings
11
+
12
+ router = APIRouter()
13
+
14
+ @router.post("/auth/token", response_model=TokenResponse)
15
+ async def get_access_token(credentials: TokenRequest):
16
+ """
17
+ Exchange user credentials for a temporary access token
18
+ This endpoint allows users to authenticate and receive a JWT token
19
+ """
20
+ # Example: validate user credentials against your user database
21
+ # For now, this is just a placeholder implementation
22
+
23
+ if not validate_user_credentials(credentials.dict()):
24
+ raise HTTPException(status_code=401, detail="Invalid credentials")
25
+
26
+ # Generate a temporary JWT token
27
+ payload = {
28
+ "sub": credentials.username,
29
+ "exp": datetime.utcnow() + timedelta(hours=24),
30
+ "iat": datetime.utcnow(),
31
+ "type": "access_token"
32
+ }
33
+
34
+ secret_key = os.getenv("SECRET_KEY", "your-secret-key-change-this")
35
+ token = jwt.encode(payload, secret_key, algorithm="HS256")
36
+
37
+ return TokenResponse(
38
+ access_token=token,
39
+ token_type="bearer",
40
+ expires_in=86400 # 24 hours
41
+ )
42
+
43
+ @router.post("/auth/refresh")
44
+ async def refresh_access_token(refresh_token: str):
45
+ """
46
+ Refresh an expired access token
47
+ """
48
+ try:
49
+ secret_key = os.getenv("SECRET_KEY", "your-secret-key-change-this")
50
+ payload = jwt.decode(refresh_token, secret_key, algorithms=["HS256"])
51
+
52
+ if payload.get("type") != "refresh_token":
53
+ raise HTTPException(status_code=401, detail="Invalid token type")
54
+
55
+ # Generate new access token
56
+ new_payload = {
57
+ "sub": payload["sub"],
58
+ "exp": datetime.utcnow() + timedelta(hours=24),
59
+ "iat": datetime.utcnow(),
60
+ "type": "access_token"
61
+ }
62
+
63
+ new_token = jwt.encode(new_payload, secret_key, algorithm="HS256")
64
+
65
+ return TokenResponse(
66
+ access_token=new_token,
67
+ token_type="bearer",
68
+ expires_in=86400
69
+ )
70
+
71
+ except jwt.InvalidTokenError:
72
+ raise HTTPException(status_code=401, detail="Invalid refresh token")
73
+
74
+ def validate_user_credentials(credentials: Dict[str, Any]) -> bool:
75
+ """
76
+ Validate user credentials against your user database
77
+
78
+ TODO: Implement your actual user validation logic here
79
+ This could check against:
80
+ - Database users table
81
+ - LDAP/Active Directory
82
+ - OAuth provider
83
+ - etc.
84
+ """
85
+ # Placeholder implementation - replace with your actual auth logic
86
+ username = credentials.get("username")
87
+ password = credentials.get("password")
88
+
89
+ # Example: simple hardcoded validation (NOT for production!)
90
+ if username == "demo" and password == "demo123":
91
+ return True
92
+
93
+ # In a real implementation, you would:
94
+ # 1. Hash the password and compare with stored hash
95
+ # 2. Check against your user database
96
+ # 3. Validate any additional requirements
97
+
98
+ return False
app/api/v1/schemas/auth_schemas.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Authentication schemas for request/response models
3
+ """
4
+ from pydantic import BaseModel
5
+ from typing import Optional
6
+
7
+ class TokenRequest(BaseModel):
8
+ """Request model for token authentication"""
9
+ username: str
10
+ password: str
11
+
12
+ class TokenResponse(BaseModel):
13
+ """Response model for token endpoints"""
14
+ access_token: str
15
+ token_type: str = "bearer"
16
+ expires_in: int # seconds until expiration
17
+
18
+ class RefreshTokenRequest(BaseModel):
19
+ """Request model for token refresh"""
20
+ refresh_token: str
app/core/auth.py CHANGED
@@ -5,6 +5,8 @@ from fastapi import HTTPException, status, Depends
5
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
6
  from typing import Optional
7
  import os
 
 
8
  from dotenv import load_dotenv
9
 
10
  load_dotenv()
@@ -17,7 +19,7 @@ def get_hf_api_key() -> str:
17
 
18
  def verify_hf_token(credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)) -> bool:
19
  """
20
- Verify HuggingFace API token
21
  Returns True if no authentication is required (public space) or if token is valid
22
  """
23
  expected_token = get_hf_api_key()
@@ -34,15 +36,29 @@ def verify_hf_token(credentials: Optional[HTTPAuthorizationCredentials] = Depend
34
  headers={"WWW-Authenticate": "Bearer"},
35
  )
36
 
37
- # Verify the token matches
38
- if credentials.credentials != expected_token:
39
- raise HTTPException(
40
- status_code=status.HTTP_401_UNAUTHORIZED,
41
- detail="Invalid authentication token",
42
- headers={"WWW-Authenticate": "Bearer"},
43
- )
 
 
 
 
 
 
 
 
 
44
 
45
- return True
 
 
 
 
 
46
 
47
  def optional_auth(credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)) -> bool:
48
  """
 
5
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
6
  from typing import Optional
7
  import os
8
+ import jwt
9
+ from datetime import datetime
10
  from dotenv import load_dotenv
11
 
12
  load_dotenv()
 
19
 
20
  def verify_hf_token(credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)) -> bool:
21
  """
22
+ Verify HuggingFace API token or JWT token
23
  Returns True if no authentication is required (public space) or if token is valid
24
  """
25
  expected_token = get_hf_api_key()
 
36
  headers={"WWW-Authenticate": "Bearer"},
37
  )
38
 
39
+ token = credentials.credentials
40
+
41
+ # Try to verify as HuggingFace API key first
42
+ if token == expected_token:
43
+ return True
44
+
45
+ # Try to verify as JWT token (if you implement JWT auth)
46
+ try:
47
+ secret_key = os.getenv("SECRET_KEY", "your-secret-key")
48
+ payload = jwt.decode(token, secret_key, algorithms=["HS256"])
49
+ # Verify token hasn't expired
50
+ if payload.get("exp") and datetime.fromtimestamp(payload["exp"]) < datetime.utcnow():
51
+ raise jwt.ExpiredSignatureError("Token has expired")
52
+ return True
53
+ except jwt.InvalidTokenError:
54
+ pass
55
 
56
+ # If neither verification method worked, deny access
57
+ raise HTTPException(
58
+ status_code=status.HTTP_401_UNAUTHORIZED,
59
+ detail="Invalid authentication token",
60
+ headers={"WWW-Authenticate": "Bearer"},
61
+ )
62
 
63
  def optional_auth(credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)) -> bool:
64
  """
app/main.py CHANGED
@@ -1,7 +1,7 @@
1
  from fastapi import FastAPI
2
  from fastapi.staticfiles import StaticFiles
3
  from fastapi.middleware.cors import CORSMiddleware
4
- from .api.v1.endpoints import generate, download, health
5
  from .core.config import settings
6
  from .core.model_loader import get_generator # Import get_generator
7
  from contextlib import asynccontextmanager
@@ -95,6 +95,7 @@ app.add_middleware(
95
  )
96
 
97
  app.include_router(health.router, prefix=settings.API_PREFIX, tags=["Health"])
 
98
  app.include_router(generate.router, prefix=settings.API_PREFIX, tags=["Generate Card"])
99
  app.include_router(download.router, prefix=settings.API_PREFIX, tags=["Download Card"])
100
 
 
1
  from fastapi import FastAPI
2
  from fastapi.staticfiles import StaticFiles
3
  from fastapi.middleware.cors import CORSMiddleware
4
+ from .api.v1.endpoints import generate, download, health, auth
5
  from .core.config import settings
6
  from .core.model_loader import get_generator # Import get_generator
7
  from contextlib import asynccontextmanager
 
95
  )
96
 
97
  app.include_router(health.router, prefix=settings.API_PREFIX, tags=["Health"])
98
+ app.include_router(auth.router, prefix=settings.API_PREFIX, tags=["Authentication"])
99
  app.include_router(generate.router, prefix=settings.API_PREFIX, tags=["Generate Card"])
100
  app.include_router(download.router, prefix=settings.API_PREFIX, tags=["Download Card"])
101
 
static/images/generated/375677ce-67f8-4afc-aeae-7b993441b2a5.png DELETED
Binary file (36.9 kB)
 
static/images/generated/7b7c33a0-fdb1-44ff-8642-64b6adca011c.png DELETED
Binary file (31.2 kB)