fix(workspace): validate Keycloak JWT for production auth
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a483b47369
commit
a846b3e7f1
@ -22,14 +22,22 @@ class Settings(BaseSettings):
|
|||||||
auth_required: bool = True
|
auth_required: bool = True
|
||||||
entitlement_stub: bool = True
|
entitlement_stub: bool = True
|
||||||
keycloak_enabled: bool = True
|
keycloak_enabled: bool = True
|
||||||
keycloak_server_url: str = "http://localhost:8080"
|
keycloak_server_url: str = Field(default="http://localhost:8080", validation_alias="KEYCLOAK_SERVER_URL")
|
||||||
keycloak_public_url: str = ""
|
keycloak_public_url: str = Field(default="", validation_alias="KEYCLOAK_PUBLIC_URL")
|
||||||
keycloak_realm: str = "superapp"
|
keycloak_realm: str = Field(default="superapp", validation_alias="KEYCLOAK_REALM")
|
||||||
jwt_algorithm: str = "RS256"
|
jwt_algorithm: str = "RS256"
|
||||||
jwt_audience: str = "account"
|
jwt_audience: str = "account"
|
||||||
jwt_verify_signature: bool = True
|
jwt_verify_signature: bool = True
|
||||||
cors_origins: str = "http://localhost:3000,http://127.0.0.1:3000"
|
cors_origins: str = "http://localhost:3000,http://127.0.0.1:3000"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keycloak_public_base(self) -> str:
|
||||||
|
return (self.keycloak_public_url or self.keycloak_server_url).rstrip("/")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keycloak_public_realm_url(self) -> str:
|
||||||
|
return f"{self.keycloak_public_base}/realms/{self.keycloak_realm}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cors_origin_list(self):
|
def cors_origin_list(self):
|
||||||
return [x.strip() for x in self.cors_origins.split(",") if x.strip()]
|
return [x.strip() for x in self.cors_origins.split(",") if x.strip()]
|
||||||
|
|||||||
@ -1,16 +1,34 @@
|
|||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||||
|
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
|
from shared.auth import JWTSettings, JWTValidator
|
||||||
from shared.exceptions import UnauthorizedError
|
from shared.exceptions import UnauthorizedError
|
||||||
from shared.security import CurrentUser
|
from shared.security import CurrentUser
|
||||||
|
|
||||||
bearer = HTTPBearer(auto_error=False)
|
bearer = HTTPBearer(auto_error=False)
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache
|
||||||
|
def get_jwt_validator() -> JWTValidator:
|
||||||
|
return JWTValidator(
|
||||||
|
JWTSettings(
|
||||||
|
keycloak_enabled=settings.keycloak_enabled,
|
||||||
|
keycloak_server_url=settings.keycloak_server_url,
|
||||||
|
keycloak_realm=settings.keycloak_realm,
|
||||||
|
jwt_algorithm=settings.jwt_algorithm,
|
||||||
|
jwt_audience=settings.jwt_audience,
|
||||||
|
jwt_verify_signature=settings.jwt_verify_signature,
|
||||||
|
jwt_issuer=settings.keycloak_public_realm_url,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer)):
|
async def get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer)):
|
||||||
if not settings.auth_required:
|
if not settings.auth_required:
|
||||||
return CurrentUser(user_id="test-user", username="test", roles=["tenant_admin"])
|
return CurrentUser(user_id="test-user", username="test", roles=["tenant_admin"])
|
||||||
if not credentials:
|
if credentials is None or not credentials.credentials:
|
||||||
raise UnauthorizedError("Authentication required")
|
raise UnauthorizedError("توکن احراز هویت ارائه نشده است")
|
||||||
return CurrentUser(user_id="token-user", username="token", roles=[])
|
return await get_jwt_validator().validate(credentials.credentials)
|
||||||
|
|||||||
@ -460,6 +460,10 @@ services:
|
|||||||
WORKSPACE_DATABASE_URL_SYNC: ${WORKSPACE_DATABASE_URL_SYNC:-postgresql+psycopg://superapp:superapp_password@postgres:5432/workspace_db}
|
WORKSPACE_DATABASE_URL_SYNC: ${WORKSPACE_DATABASE_URL_SYNC:-postgresql+psycopg://superapp:superapp_password@postgres:5432/workspace_db}
|
||||||
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
|
CORE_SERVICE_URL: ${CORE_SERVICE_URL:-http://core-service:8000}
|
||||||
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
|
AUTH_REQUIRED: ${AUTH_REQUIRED:-true}
|
||||||
|
KEYCLOAK_SERVER_URL: ${KEYCLOAK_SERVER_URL:-http://keycloak:8080}
|
||||||
|
KEYCLOAK_PUBLIC_URL: ${KEYCLOAK_PUBLIC_URL:-http://localhost:8080}
|
||||||
|
KEYCLOAK_REALM: ${KEYCLOAK_REALM:-superapp}
|
||||||
|
JWT_VERIFY_SIGNATURE: ${JWT_VERIFY_SIGNATURE:-true}
|
||||||
ports:
|
ports:
|
||||||
- "8013:8013"
|
- "8013:8013"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user