diff --git a/api/routes/auth.py b/api/routes/auth.py index 6083b875..baf5bdde 100644 --- a/api/routes/auth.py +++ b/api/routes/auth.py @@ -5,7 +5,11 @@ from api.db import db_client from api.db.models import UserModel from api.enums import OrganizationConfigurationKey, PostHogEvent from api.schemas.auth import AuthResponse, LoginRequest, SignupRequest, UserResponse -from api.services.auth.depends import create_user_configuration_with_mps_key, get_user +from api.services.auth.depends import ( + create_user_configuration_with_mps_key, + get_user, + require_local_auth, +) from api.services.configuration.ai_model_configuration import ( convert_legacy_ai_model_configuration_to_v2, ) @@ -15,6 +19,7 @@ from api.utils.auth import create_jwt_token, hash_password, verify_password router = APIRouter( prefix="/auth", tags=["auth"], + dependencies=[Depends(require_local_auth)], ) diff --git a/api/services/auth/depends.py b/api/services/auth/depends.py index 4225b6f0..488d45a4 100644 --- a/api/services/auth/depends.py +++ b/api/services/auth/depends.py @@ -20,6 +20,19 @@ from api.services.posthog_client import ( ) from api.utils.auth import decode_jwt_token + +async def require_local_auth() -> None: + """Reject email/password auth requests outside OSS (local) deployments. + + The auth router stays mounted in every mode so the OpenAPI spec — and the + clients generated from it — don't vary with AUTH_PROVIDER; the gate has to + happen at request time. Without it, the SaaS deployment accepts + unauthenticated signups that mint oss_* users bypassing Stack Auth. + """ + if AUTH_PROVIDER != "local": + raise HTTPException(status_code=404, detail="Not found") + + POSTHOG_ORGANIZATION_GROUP_TYPE = "organization" POSTHOG_ORGANIZATION_USES_MPS_BILLING_V2_PROPERTY = "uses_mps_billing_v2"