diff --git a/.gitignore b/.gitignore index b4418da..8e6f860 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ env/ # Environment variables .env +# Cryptographic keys +*.pem + # IDE .vscode/ .idea/ diff --git a/services/auth/app/config.py b/services/auth/app/config.py index 641f1c1..d92e6e8 100644 --- a/services/auth/app/config.py +++ b/services/auth/app/config.py @@ -4,6 +4,7 @@ Contains secrets that ONLY the Auth Service needs (e.g., JWT private key). These are NOT in shared/config.py to prevent other services from accessing them. """ +from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict @@ -20,6 +21,13 @@ class AuthSettings(BaseSettings): # openssl rsa -in private.pem -pubout -out public.pem JWT_PUBLIC_KEY: str = "" + @field_validator("JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", mode="before") + @classmethod + def _expand_pem_newlines(cls, v: str) -> str: + if isinstance(v, str) and r"\n" in v: + return v.replace(r"\n", "\n") + return v + model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8") diff --git a/shared/config.py b/shared/config.py index 50df4a7..5cf0b18 100644 --- a/shared/config.py +++ b/shared/config.py @@ -6,6 +6,7 @@ of the vars, but keeping one Settings class avoids fragmentation. from typing import Literal +from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict @@ -18,6 +19,14 @@ class Settings(BaseSettings): # JWTs locally (optional — Traefik ForwardAuth handles this in prod). # The private key lives ONLY in the Auth Service config. JWT_PUBLIC_KEY: str = "" + + @field_validator("JWT_PUBLIC_KEY", mode="before") + @classmethod + def _expand_pem_newlines(cls, v: str) -> str: + if isinstance(v, str) and r"\n" in v: + return v.replace(r"\n", "\n") + return v + JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 30 JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 30 @@ -67,7 +76,9 @@ class Settings(BaseSettings): # ── Environment ────────────────────────────────────────────────── ENV: Literal["dev", "prod"] = "dev" - model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8") + model_config = SettingsConfigDict( + env_file=".env", env_file_encoding="utf-8", extra="ignore" + ) settings = Settings()