The problem.
Several Microsoft 365 tenants to watch: unlicensed or non-MFA accounts, admins without MFA, exhausted licence pools, disabled but still licensed accounts, App Registration secrets close to expiry… scattered across consoles, with nobody seeing the big picture.
What I built.
01
Detection
- Periodic Microsoft Graph collection on every tenant and anomaly detection (unlicensed, no MFA, missing from AD, exhausted licences, disabled but licensed, admins without MFA, expiring secrets).
02
Action
- Filterable consolidated view, anomaly acknowledgement, licence assignment and removal, licence downgrade, session revocation.
- Single or bulk disabling, routed by account origin (synced from AD or cloud-only), with a per-licence summary at the end of a batch.
03
Platform
- OIDC single sign-on (Keycloak), containerised deployment, every action logged.
The architecture.
Microsoft 365 tenantsGraph
Pollerperiodic collection
Laravel portalKeycloak SSO
Consolidated viewanomalies
Actionslicences · sessions · accounts
Security & guardrails.
- Every action logged with its author.
- Disabling adapted to account origin so AD sync is never broken.
The results.
- One view for the team instead of several consoles.
- 160+ commits as a team, nearly half of them mine.