Skip to main content

TenantTool Web

TenantTool Documentation

A centralized management and auditing platform for Microsoft 365 tenants — built for managed service providers who operate fleets of customer tenants.

Tech stack: Blazor Server · .NET 8 · MudBlazor 9 · PostgreSQL · Microsoft Graph · PKCE OAuth2 · Docker + Caddy · ClosedXML


Table of Contents


Architecture

TenantTool is a Blazor Server application running against a PostgreSQL database. All Microsoft 365 operations use delegated PKCE OAuth2 flows — there is no application-only credential for per-tenant reads. Each registered tenant has its own Azure app registration.

Component Details
Rendering Blazor Server interactive
Database EF Core 8 + Npgsql (PostgreSQL)
Authentication ASP.NET Core Identity for app login
Per-tenant auth PKCE delegated OAuth2
Token cache 55 min TTL, 6 token types per tenant
Infrastructure Docker + Caddy reverse proxy
Excel ClosedXML for import/export
CI/CD GitHub Actions → production

Multi-Client Hierarchy

The data model is scoped: Clients group related Tenants. Application users are assigned to a Client and can only see tenants belonging to that Client. Administrator-tier users (no ClientId set) see everything.

Entity Description Notes
Client An MSP customer organization Holds logo and breakglass name pool preference
Tenant An Azure / M365 tenant Belongs to a Client; one per client can be flagged IsGold
ApplicationUser A TenantTool login account ClientId = null = full admin; set = scoped to one client

Roles & Access

Three application roles control what each user can see and do.

Role Name Access
Admin TenantTool.Admin Full access — all pages including Clients, Users, Tenant registration, Standard Config, Gold Config, Identity Config, and all reports. Can provision tenants, manage app users, and update standard templates.
L1 TenantTool.L1 Restricted write access — can use Gold Config and Identity Config, run all reports, and perform Tenant Checks. Cannot manage clients, users, or tenant registrations.
Report TenantTool.Report Read-only — all reports and Tenant Check only. No write operations.
Public (anonymous) The Quick Check page is accessible without login using ad-hoc credentials.

Warning: The default seed account is admin / admin. Change the password immediately on first deploy.


Dashboard

Home — /

Shows three KPI tiles: total tenants, Gold tenants, and active app users. Lists all tenants visible to the current user. Click any tenant to open its hub page with links to Tenant Check and all reports.

Access: All roles

Quick Check — /quick-check

Runs a full Tenant Check with ad-hoc credentials — Tenant ID, App Client ID, and client secret entered directly. No tenant registration required. Uses a client-credential (secret) flow instead of PKCE.

Access: No login required

Info & Permissions Reference — /info

Lists the OAuth redirect URI to register in each tenant's app registration, and all required API permissions grouped by API surface (Graph, Exchange Online, Defender ATP, ARM, Azure Storage).

Access: All roles


Tenant Management

Tenants — /tenants

Register, rename, and delete Azure tenant entries. Two creation modes:

  • Manual — paste in the Tenant ID, App Client ID, and client secret from an app registration you created in the Azure Portal.
  • Automatic provisioning — authenticates as Global Admin via the Microsoft device code flow, then fully creates the TenantToolWeb app registration: all required permissions, admin consent, service principal with "assignment required", and a 24-month client secret. No Azure Portal work needed.

Access: Admin only

Clients — /clients

Create, rename, and delete MSP client organizations. Visible to administrator-tier accounts only (users with a ClientId set cannot access this page).

Access: Admin only

Users — /users

Create, edit, and delete TenantTool login accounts. Assign a role and optionally bind each user to a Client for data scoping.

Access: Admin only


Tenant Check

Full Tenant Analysis — /tenant-info/{id}

Authenticates via PKCE, then fetches all tenant data from Microsoft Graph in parallel across eight analysis tabs.

Access: All roles

Tab What it checks
Summary Health status overview per platform, tenant country, technical contact, creation date, verified domains
Admin Directory roles, Global Admins, breakglass accounts, MFA coverage for privileged users
Identity All users, deleted users, risky users, MFA/SSPR registrations, sign-in log analysis, license overview
Intune Managed devices, configuration profiles, compliance policies with assignment and success/error/conflict counts
Exchange EOP policies (Anti-Malware, Anti-Spam, Anti-Phishing, Safe Links, Safe Attachments, Quarantine), Secure Score, mailbox sizes
Files SharePoint tenant settings, OneDrive quota overview, sharing and external-access policies
Defender Open alerts, active incidents, endpoint status, exposure level from Microsoft Defender ATP
Teams Teams calling settings, channel overview, membership summary
Gold Check Compares this tenant against the Gold baseline — per Intune profile, compliance policy, and CA policy: Match / Differ / Missing / Extra

A standalone HTML report can be exported containing all results with embedded styles and the client's logo. The file is fully self-contained and can be emailed or archived without dependencies.


Specialized Reports

Each report authenticates via PKCE and is accessible from the tenant hub. All reports include an export to a standalone HTML file.

Report Route Details
SharePoint Rights /tenant-sharepoint/{id} Select sites, then fetch Owners / Members / Visitors groups and expand Azure AD security group members
SharePoint Storage /tenant-sp-storage/{id} Per-site and per-OneDrive storage used vs. allocated. Export HTML + JSON
Azure Blob Storage /tenant-blob-storage/{id} Uses ARM + Azure Storage tokens to list accounts, containers, and blob tree with file sizes. Export HTML + JSON
Exchange Mailboxes /tenant-exchange/{id} Shared mailboxes with full-access and read-only delegate permissions via Exchange Online token
Teams /tenant-teams/{id} All Teams, their channels, owners, and members
Conditional Access /tenant-conditional-access/{id} All CA policies with state, conditions summary, and grant controls
Privileged Access /tenant-privileged/{id} All Entra ID directory roles and their current holders
PIM Status /tenant-entra/{id} PIM-eligible vs. permanent role assignments; identifies over-privileged accounts
Maintenance /tenant-maintenance/{id} Stale users, inactive devices, and other maintenance-relevant findings

Gold Config

Gold Reference Baseline — /gold-config

Designate one tenant per client as the Gold tenant — the approved configuration baseline. TenantTool syncs that tenant's Intune configuration profiles, compliance policies, and Conditional Access policies into the local database.

Once synced, compare any other tenant against the Gold baseline. Each item shows one of four states:

State Meaning
Match Configuration is identical to Gold
⚠️ Differ Item exists but configuration differs
Missing Item exists in Gold but not in this tenant
ℹ️ Extra Item exists in this tenant but not in Gold

Comparison is by display name. Use the Gold Check tab in Tenant Check to quickly spot configuration drift across managed tenants.

Access: Admin + L1


Standard Config

Provisioning Templates — /standard-config

Defines the templates used when provisioning new or existing tenants. Five tabs, all supporting JSON export and import.

Access: Admin only

Tab What it defines Import formats
Admin Users Admin and breakglass accounts — UPN prefix, first/last name, department, company, job title, security group rights, usage location JSON, Excel
Admin Groups RBAC-bearing groups with role assignments JSON, Excel
Standard Groups Security / M365 groups with type (Assigned or Dynamic), category, and membership rules JSON, Excel
CA Policies Conditional Access policy templates stored as JSON. Full typed form editor. Import directly from a live tenant JSON, from Tenant
EOP Policies Exchange Online Protection templates — Anti-Malware, Anti-Spam Inbound/Outbound, Anti-Phishing, Safe Links, Safe Attachments, Quarantine — with per-field typed editors JSON

Importing CA Policies from a Live Tenant

The CA Policies tab includes an Import from Tenant button. Select a source tenant, authenticate via PKCE (scope: Policy.Read.All), and TenantTool fetches all CA policies from Graph API. Pick which ones to bring in as standard templates.

Server-only fields (id, createdDateTime, modifiedDateTime, templateId) are stripped automatically. Existing templates with the same name are updated; new ones are added.


Identity Config

Tenant Identity Provisioning — /tenant-config/identity

Applies standard templates to a specific tenant via Graph API. Four sub-tabs.

Access: Admin + L1


Group Provisioning

Select standard groups (admin and/or standard groups) and provision them in a chosen tenant. Groups are created with the configured type, membership rule, and category. Groups that already exist are skipped.

Admin User Provisioning

Create admin and breakglass accounts from standard templates. A temporary password is generated per account. Manager assignments are set automatically when a manager UPN is specified in the template.

Member User Provisioning

Import a member user Excel file and create accounts in bulk.

Required columns: First Name, Last Name, UserPrincipalName, Company Name, Usage Location

Optional columns: Job Title, Department, Manager (UPN)

Group memberships and manager relationships are set after account creation. Results are shown per-user with per-assignment status.

CA Policy Deployment

Select standard CA policies and deploy them to a target tenant.

Workflow:

  1. Check for duplicates — any policy with the same display name on the target tenant is skipped and flagged "Already exists".
  2. Resolve references — group names, user UPNs, and named location names are looked up in the target tenant and replaced with their object IDs. Unresolvable references block deployment for that policy.
  3. Create policy — the resolved JSON is posted to /identity/conditionalAccess/policies on the target tenant. New policies are always created as disabled.

Note: CA policies are always created as disabled. Review and enable them manually in the tenant's Azure portal to prevent accidental lockout.

In-session customization

Before deploying, policies can be customized without modifying the stored standard templates:

  • Edit — open a per-policy JSON editor. Changes are stored in memory for the current session only.
  • Reset — discard in-session edits and revert to the standard template.
  • Export JSON — download the current working set (including any in-session edits) as a JSON file.
  • Import JSON — load a previously exported or manually crafted JSON file. Policies matching existing standard names override their JSON for the session; unrecognized names are added as temporary session-only policies.

My Org

Organisation Settings — /my-org

Client Logo — Upload a PNG or SVG (max 2 MB). The logo is stored as Base64 and embedded in all exported HTML reports for that client.

Breakglass Name Pool — Choose a themed name pool for breakglass account naming suggestions:

  • Saint Seiya
  • Greek & Roman Gods
  • Norse Mythology
  • Arthurian Legends

Each pool contains 50 names. Use "Pick Random" to suggest a name and copy it to clipboard.

Access: Admin only


Authentication Flow

Each report and provisioning operation uses a PKCE delegated OAuth2 flow. The token cache is checked first; if no valid token exists, the user is redirected to Microsoft's authorization endpoint for that specific tenant.

1. TenantTool generates a PKCE code verifier + SHA-256 challenge
   and redirects to:
   login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize

2. After Microsoft sign-in and consent, the browser is redirected
   to /oauth-callback with an authorization code.

3. The callback fires six parallel token exchanges:
   - Microsoft Graph
   - Exchange Online
   - Microsoft Defender ATP
   - SharePoint REST
   - Azure Resource Manager
   - Azure Storage

4. All tokens are stored in TokenCacheService keyed by (userId, tenantDbId)
   with a 55-minute TTL. The user is returned to the originating page.

After 55 minutes, the next operation will trigger re-authentication. Each browser session maintains its own token set per tenant.


Required API Permissions

The following delegated permissions must be granted with admin consent on each tenant's app registration. The Automatic Provisioning flow creates all of these automatically.

Microsoft Graph — Delegated

User.Read                                   Organization.Read.All
User.Read.All                               User.ReadWrite.All
Group.Read.All                              Group.ReadWrite.All
Directory.Read.All                          Sites.Read.All
Sites.ReadWrite.All                         DeviceManagementManagedDevices.Read.All
DeviceManagementConfiguration.Read.All      DeviceManagementApps.Read.All
RoleManagement.Read.Directory               Policy.Read.All
Policy.ReadWrite.ConditionalAccess          IdentityRiskyUser.Read.All
Reports.Read.All                            AuditLog.Read.All
UserAuthenticationMethod.Read.All           SecurityEvents.Read.All
SecurityIncident.Read.All                   SharePointTenantSettings.Read.All
TeamMember.Read.All                         Channel.ReadBasic.All
ChannelMember.Read.All                      TeamSettings.Read.All
TeamsActivity.Read

Office 365 Exchange Online — Delegated

Exchange.Manage

Windows Defender ATP — Delegated

Alert.Read
Machine.Read

Azure Service Management — Delegated

user_impersonation

Azure Storage — Delegated

user_impersonation

Data Model

Key entities persisted in PostgreSQL via Entity Framework Core.

Entity Key Fields Purpose
Client Name, LogoBase64, BreakglassNamePool MSP customer organization; holds logo and name pool preference
Tenant AzureTenantId, AppClientId, ClientSecret, IsGold Azure / M365 tenant registration; one per client can be Gold
ApplicationUser ClientId (nullable), Role TenantTool login; null ClientId = administrator
StandardUser Type, UpnPrefix, FirstName, LastName, SecurityGroupsRights Admin / breakglass user provisioning template
StandardAdminGroup DisplayName, Description, RbacRole RBAC group provisioning template
StandardGroup DisplayName, GroupType, GroupCategory, MembershipRule Standard group provisioning template
StandardCaPolicy Name, Comment, ConfigJson CA policy template (full Graph API JSON payload)
StandardEopPolicy PolicyType, Name, Comment, ConfigJson EOP policy template by type
GoldSync TenantId, LastSyncedAt Tracks last Gold sync timestamp per tenant
GoldConfigEntry ExternalId, Name, Category, Platform, SettingsJson Intune configuration profile snapshot from Gold tenant
GoldComplianceEntry ExternalId, Name, Category, Platform Intune compliance policy snapshot from Gold tenant
GoldCaEntry ExternalId, DisplayName, State, IncludeGroupsJson CA policy snapshot from Gold tenant

TenantTool · Blazor Server .NET 8