Skip to content

Onboarding Your First Organization

BJD1997 edited this page Oct 16, 2026 · 5 revisions

Onboarding Your First Organization

TL;DR: platform admin creates the org and (ideally) sets its Entra tenant ID → the org's first user signs in and becomes its org_admin → the org connects a mailbox and completes two Microsoft-side consent steps → domains get verified → checks start running.

This is the actual current flow, kept in sync with the app rather than a design-time plan — steps here are what the UI does, from the app's multi-tenant model: an "operator" who can create/manage organizations, and the organizations themselves.

1. Platform admin: create the organization

In the admin console (/admin), enter the organization's name and its Entra tenant ID (the GUID for its Microsoft 365 / Azure AD tenant — found in its Entra admin center under "Tenant properties"). Providing the tenant ID up front activates the organization immediately.

If you don't have the tenant ID yet, you can still create the organization with just a name (status stays pending_setup) and add the tenant ID later from the same screen — nothing else is blocked on it except that organization's users being able to sign in.

That's the only manual step on the platform-admin side. Everything from here is self-service from the organization's own dashboard.

2. Organization: sign in

The organization's users go to the dashboard and sign in with "Sign in with Microsoft." Microsoft handles SSO consent automatically inline at first sign-in — there's no separate consent link to hand out for this part, unless the organization's tenant is configured to block user consent entirely, in which case an admin-consent link for the SSO app is available from the mailbox setup screen (see below) and its Global Admin needs to click it once.

The first user to sign in for a newly-activated organization automatically becomes that organization's org_admin, and anyone else in the tenant can sign in too. Before handing out the dashboard address, set Assignment required on the sign-in app in the organization's tenant and assign the intended admin first; see Securing Your Install.

3. Organization (org_admin): connect the mailbox

On first visit to the dashboard, a banner prompts for the shared mailbox address that receives DMARC/TLS-RPT reports (e.g. dmarc-reports@yourdomain.com). Entering it and clicking "Save & start syncing" is enough to kick off the first sync attempt — consent is self-attested at this point, so the banner will initially show green even before the underlying Graph permissions are actually in place.

This step alone is not sufficient for reports to actually flow in. Two more things need to happen on the organization's side, both surfaced as links right there in the banner (click "Entra links" once the banner is up, or — if the first sync fails — the same links appear automatically under the sync-error message):

  1. Mail access consent (required): the organization's Global Admin clicks the mail-access admin-consent link and approves it. This grants the app's Mail Access application (app-only, Mail.Read) permission in its tenant.

  2. Limit the app to the reports mailbox (required, done outside this app, in Exchange Online PowerShell). This is the step that actually matters for security: the consent in step 1 grants app-only Mail.Read, which on its own can read every mailbox in the tenant, not just the reports mailbox. Pick one of the two ways below.

    Option A: RBAC for Applications (Microsoft's current way; it replaces Application Access Policies):

    Connect-ExchangeOnline
    # The IDs from Entra → Enterprise applications → the mail access app
    # (not App registrations, which shows different IDs).
    New-ServicePrincipal -AppId <mail-access-app-id> -ObjectId <enterprise-app-object-id> -DisplayName "YetAnotherDmarcTool mail access"
    New-ManagementScope -Name "YetAnotherDmarcTool reports mailbox" `
      -RecipientRestrictionFilter "PrimarySmtpAddress -eq 'dmarc-reports@yourdomain.com'"
    New-ManagementRoleAssignment -App <enterprise-app-object-id> -Role "Application Mail.Read" `
      -CustomResourceScope "YetAnotherDmarcTool reports mailbox"

    Then remove the tenant-wide Mail.Read grant from step 1. This is not optional: Exchange adds the two grants together, so as long as the Entra grant exists the scope above limits nothing (Microsoft's FAQ on this).

    Connect-MgGraph -Scopes "Application.ReadWrite.All","AppRoleAssignment.ReadWrite.All"
    $sp = Get-MgServicePrincipal -Filter "appId eq '<mail-access-app-id>'"
    # Mail.Read (application) on Microsoft Graph has app role ID 810c84a8-4a9e-49e6-bf7d-12d183f40d01
    Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id |
      Where-Object AppRoleId -eq "810c84a8-4a9e-49e6-bf7d-12d183f40d01" |
      ForEach-Object { Remove-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id -AppRoleAssignmentId $_.Id }

    Check it: Test-ServicePrincipalAuthorization -Identity <mail-access-app-id> -Resource dmarc-reports@yourdomain.com should show InScope: True, and the same command against any other mailbox InScope: False. That test doesn't see Entra grants, so also check that Entra → Enterprise applications → the app → Permissions no longer lists Mail.Read. Changes can take 30 minutes to 2 hours to apply. Don't approve the consent link from step 1 again afterwards: that brings the tenant-wide grant back.

    Option B: Application Access Policy (older, still works; it limits the Entra grant itself, so nothing needs removing):

    New-DistributionGroup -Name "DMARC Dashboard Mailbox Access" -Members dmarc-reports@yourdomain.com
    New-ApplicationAccessPolicy -AppId <mail-access-app-id> `
      -PolicyScopeGroupId "DMARC Dashboard Mailbox Access" -AccessRight RestrictAccess `
      -Description "Restrict DMARC Dashboard's Graph token to the DMARC reports mailbox only"
    Test-ApplicationAccessPolicy -AppId <mail-access-app-id> -Identity dmarc-reports@yourdomain.com

    Test-ApplicationAccessPolicy should report access granted for the reports mailbox and denied for any other.

    The same applies to the operator's hosted reporting mailbox: limit the mail access app to that one mailbox in the operator's own tenant.

If the organization sets the mailbox address before completing these two steps (a common ordering, since it's the more discoverable action), the first sync will fail. That's expected — the dashboard shows the same consent-guidance links directly next to the sync error, with no dead end. More on diagnosing a stuck sync: Report Ingestion Troubleshooting.

4. Confirm the sync actually worked

Once both consent steps are done, click "Resync now" (or wait for the next scheduled poll, every 10 minutes). The mailbox banner should turn green with a recent "last synced" timestamp. As platform admin, /admin/job-runs shows every mailbox-poll attempt across all organizations — a success row for this org's mailbox_poll job confirms it end-to-end, and doubles as confirmation that the Application Access Policy is scoped correctly (a mis-scoped policy fails here, not silently).

5. Organization (org_admin): add domains

Add each domain/subdomain to monitor. Before any best-practice checks run against it, the domain must prove DNS control:

  1. Click "How to verify" on the newly-added domain to get a TXT record name (_yadt-verify.<domain>) and a token value.
  2. Publish that TXT record in the domain's real DNS.
  3. Click "Check now" — once the record resolves, the domain flips to verified and checks start running.

A subdomain of an already-verified apex domain inherits verification automatically and doesn't need its own token. See DNS Verification Issues if a check keeps failing.

6. Organization (org_admin): add DKIM selectors

DKIM selectors aren't discoverable via DNS alone, so they have to be added manually (whatever selector the mail provider uses — check its provider's DKIM setup docs, e.g. selector1/selector2 for Microsoft 365, google for Google Workspace). Without at least one selector added, the DKIM check just reports "no selectors registered" rather than a real result.

7. Review findings, fix DNS

Once verified (and with selectors added), SPF/DKIM/DMARC/DMARCbis/MX/ MTA-STS/DANE/TLS-RPT checks run automatically on a schedule (see How DNS Checks Are Scheduled), or on-demand via "Recheck." This app is read-only and advisory toward the organization's DNS — it never writes records on their behalf. Every finding is a recommendation; the organization updates its own authoritative DNS (at its registrar or DNS host) to act on it.


Platform-admin login, separately

None of the above requires the platform admin to log in more than once (to create the org). For reference, platform-admin auth itself works two ways:

  • Local email + password (the break-glass account, bootstrapped at deploy time) — has a "Change password" option in the admin console.
  • Via your own operator organization's Entra login, if that organization is flagged as the operator org — sign in normally as an org_admin of that org and you land in the same admin console.

← Configuration Reference · Core Concepts →

Clone this wiki locally