Validates Entra JWTs directly via JWKS verification. Extracts device_id for compliance gating, MFA status, roles, and constructs DID from Entra tenant + oid. Adds device_id field to AuthResult dataclass. Signed-off-by: Tyler King <tking@guildhouse.dev>
40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
"""Identity Driver Interface — GSAP §2.2. Zero framework imports."""
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass, field
|
|
from typing import Optional
|
|
|
|
@dataclass
|
|
class ElevationRequired:
|
|
role: str
|
|
activation_url: str
|
|
instructions: str
|
|
mechanism: str = "custom"
|
|
|
|
@dataclass
|
|
class AuthResult:
|
|
STATUS_AUTHORIZED = "authorized"
|
|
STATUS_PENDING_ELEVATION = "pending_elevation"
|
|
STATUS_DENIED = "denied"
|
|
|
|
status: str
|
|
principal_did: str = ""
|
|
display_name: str = ""
|
|
stable_id: str = ""
|
|
token_jti: str = ""
|
|
elevation_active: list = field(default_factory=list)
|
|
mfa_satisfied: bool = False
|
|
elevation_required: Optional[ElevationRequired] = None
|
|
denial_reason: str = ""
|
|
device_id: Optional[str] = None
|
|
|
|
@property
|
|
def is_authorized(self): return self.status == self.STATUS_AUTHORIZED
|
|
@property
|
|
def needs_elevation(self): return self.status == self.STATUS_PENDING_ELEVATION
|
|
|
|
class IdentityDriver(ABC):
|
|
def __init__(self, config: dict): self.config = config
|
|
@abstractmethod
|
|
async def authenticate(self) -> AuthResult: ...
|
|
@abstractmethod
|
|
async def revoke(self, session_id: str) -> None: ...
|