mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
feat(oidc): Azure Entra ID support — configurable email claim & verification + Remember Me persistent login (#1126)
feat(oidc): add Azure Entra ID support with configurable email claim resolution Adds two new OIDC provider fields: email_claim and require_email_verified.
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func
|
||||
from sqlalchemy import Boolean, CheckConstraint, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from backend.app.core.database import Base
|
||||
@@ -21,6 +21,15 @@ class OIDCProvider(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "oidc_providers"
|
||||
__table_args__ = (
|
||||
# DB-level enforcement of SEC-1/SEC-6: auto_link is only safe when
|
||||
# require_email_verified=True AND email_claim='email'. Enforced on new
|
||||
# installations; existing tables get this via the PostgreSQL-only migration.
|
||||
CheckConstraint(
|
||||
"auto_link_existing_accounts = FALSE OR (require_email_verified = TRUE AND email_claim = 'email')",
|
||||
name="ck_auto_link_requires_verified_email_claim",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
# Human-readable name shown on the login button (e.g. "PocketID", "Google")
|
||||
@@ -50,6 +59,20 @@ class OIDCProvider(Base):
|
||||
# operators must explicitly opt-in to prevent an attacker-controlled IdP from
|
||||
# silently hijacking local accounts via email matching (M-2 fix).
|
||||
auto_link_existing_accounts: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
# JWT claim name used as the email identity (default "email").
|
||||
# Set to "preferred_username" or "upn" for Azure Entra ID, which does not send
|
||||
# email_verified — using a custom claim skips the email_verified check entirely
|
||||
# and is the recommended Azure configuration.
|
||||
# Has no interaction with require_email_verified when set to a non-"email" value:
|
||||
# custom claims never perform an email_verified check regardless of that setting.
|
||||
email_claim: Mapped[str] = mapped_column(String(64), default="email")
|
||||
# When True (default), the "email" claim is only trusted when email_verified=True.
|
||||
# Set to False to accept the email even when email_verified is absent — required
|
||||
# for providers like Azure Entra ID that never send email_verified and where a
|
||||
# custom claim (email_claim != "email") is not preferred.
|
||||
# Has no effect when email_claim is not "email": the custom-claim path never
|
||||
# performs an email_verified check regardless of this setting.
|
||||
require_email_verified: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
# Optional icon URL (SVG/PNG) shown on the login button
|
||||
icon_url: Mapped[str | None] = mapped_column(Text, nullable=True, default=None)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
|
||||
|
||||
Reference in New Issue
Block a user