Persist OIDC config in a single-row oidc_settings table; non-empty DB fields override the OIDC_* env vars (env = bootstrap default). The Authlib client is rebuilt when config changes. - GET/PUT /auth/oidc/settings — admin only, via JWT OR API key. The API-key path is the recovery channel when OIDC-only mode is on and OIDC is misconfigured (avoids total lockout). - client_secret is write-only: never returned (has_client_secret bool), preserved when the field is left blank on update. - /auth/config, login/link/callback now use the effective (DB|env) config so enabling OIDC needs no redeploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
23 lines
936 B
Python
23 lines
936 B
Python
from sqlalchemy import Column, Integer, String, Boolean, DateTime
|
|
from sqlalchemy.sql import func
|
|
from app.core.config import Base
|
|
|
|
|
|
class OidcSettings(Base):
|
|
"""Single-row (id=1) runtime OIDC configuration.
|
|
|
|
When a row exists its non-empty fields override the OIDC_* env vars,
|
|
so the provider can be configured from the admin UI without a redeploy.
|
|
"""
|
|
__tablename__ = "oidc_settings"
|
|
|
|
id = Column(Integer, primary_key=True, default=1)
|
|
enabled = Column(Boolean, default=False, nullable=False)
|
|
issuer = Column(String(255), nullable=True)
|
|
client_id = Column(String(255), nullable=True)
|
|
client_secret = Column(String(512), nullable=True)
|
|
redirect_uri = Column(String(512), nullable=True)
|
|
scopes = Column(String(255), nullable=True)
|
|
post_login_redirect = Column(String(512), nullable=True)
|
|
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|