How the emulator’s surface maps to real Entra ID (as documented at
learn.microsoft.com/entra), and —
the point of this table — whether real work happens or just the API shape.
The design bet is that the durable, testable surface is protocol + real
cryptography + directory state, and those are done for real: real RS256 JWTs
that third-party validators accept, every OAuth2 grant a real MSAL speaks, real
WebAuthn ceremonies, a real SQLite directory. What is deliberately left out is
the policy engine — Conditional Access, MFA, Identity Protection — which is
what would turn a dev-loop emulator into an IdP.
“Real via our own wire-protocol implementation.” A row is 🟢 Real not
only when real cryptography does the work, but also when the emulator itself
implements Entra’s wire protocol and the logic behind it — so a real,
unmodified client (MSAL in five languages, the Graph SDK, a SCIM connector)
gets byte- and behaviour-identical responses.
Real gate behind GRAPH_PERMISSIONS: delegated calls need the scope in scp, app-only calls the role in roles, Directory.* acts as the superset, denials are 403 Authorization_RequestDenied. Off by default — the emulator has always accepted any valid Graph-audience token, so enabling it is opt-in
🟢 Real
Separate servicePrincipal store
An app registration is its own SP; object id and appId are conflated
🟡 Emulated
Custom role definitions
Only the seeded built-ins exist
🔴 Not implemented
Administrative units, custom security attributes
—
🔴 Not implemented
Graph beta endpoint
v1.0 only
🔴 Not implemented
Sign-in / audit logs (Graph auditLogs, signIns)
— (the emulator’s own /admin/api/audit is a different, test-only thing)
Real ceremonies (real assertion verification, real CBOR/COSE); RP derived per-request from the Host, so passkeys work on any origin; drives amr:["fido"]
A PDP port: real engines attach — OpenFGA, SpiceDB, Keto, Permify, Casbin, OPA, Cedar, all exercised in CI. A ~50-line InMemoryPDP ships so the sample runs with nothing attached; it is explicitly not a real engine
Real clients prove the emulator works; golden references prove its wire
contracts haven’t drifted. Three canonical references — the real Entra OIDC
discovery document, the official Microsoft Graph OpenAPI, and the SCIM 2.0 RFCs
— are committed under e2e/golden/ and diffed against the live emulator on
every push. Several 🟢 rows above name those tests as their witness
(TestGoldenParityOIDCDiscovery, TestGoldenParityGraph,
TestGoldenParitySCIM). See
golden-reference parity for what each asserts
and the documented divergences it reports.
The stated non-goals — SAML/WS-Fed, B2C user flows, MFA/Conditional Access,
production hardening — are a deliberate line. Crossing it changes the project’s
character from “the identity provider your tests run against” to “an identity
provider”, which is a different product with a different duty of care.
What that buys: everything above the line can be real, because none of it
needs a policy engine, a risk model, or a tenant’s compliance posture. A token
this emulator signs is a real token; a passkey it verifies is really verified.