How to implement Single Sign-On with SAML 2.0 and OpenID Connect between business applications and Microsoft Entra ID or Google Workspace

LoginMaster

To implement Single Sign-On between business applications and Microsoft Entra ID or Google Workspace you do not integrate every application with every identity provider: you put an identity broker in the middle. Applications speak a single protocol — OpenID Connect — to the broker; the broker speaks SAML 2.0 or OIDC to Entra ID and Google Workspace. A new application then needs one configuration (redirect URI and project key) instead of N SAML configurations, and adding a new identity provider does not touch the code of applications already in production.

OIDC or SAML 2.0: which one, and where

The question "SAML or OIDC?" has different answers depending on which side of the integration you are on. Between your applications and the broker, OIDC is almost always preferable: it is JSON, it works with SPAs and mobile apps, it handles token refresh and it does not require parsing and validating signed XML. Between the broker and the corporate identity provider the IdP decides: Entra ID and Google Workspace support both, but many established enterprise setups (and on-premise ADFS) only expose SAML 2.0.

CriterionOpenID ConnectSAML 2.0
FormatJSON / JWTSigned XML
Typical transportHTTPS redirect + POST to /tokenHTTP-Redirect (AuthnRequest) + HTTP-POST (Response)
SPAs and mobile appsNative (Authorization Code + PKCE)Not suitable: needs a backend to process the assertion
Session renewalRefresh tokens and prompt=noneRe-authentication at the IdP
User attributesClaims in the ID token and /userinfoAttribute Statement in the assertion
Global logoutRP-Initiated Logout / Front-ChannelSingle Logout (SLO), often partially implemented
Clock sensitivityLow (tolerance on iat/exp claims)High: NotBefore / NotOnOrAfter typically ±5 minutes
Choose it whenNew apps, APIs, mobile, broker integrationLegacy enterprise IdP, ADFS, SaaS apps that only expose SAML

For the theoretical comparison between the protocols, the extended treatment is in OAuth 2.0, OIDC and SAML: differences and use cases. Here we move on to configuration.

Step 1 — Register the application as a project

Every application that delegates login is a project: web app, mobile app and admin panel are three distinct projects, each with its own cryptographic key and its own policies. That is what lets you enforce mandatory 2FA on the admin panel while keeping it optional on the public app, without duplicating the user base.

  1. 1Create the project in the tenant and note the project key (pk_live_…): it is the public identifier used in authentication calls.
  2. 2Register the exact redirect URIs, one per environment. The comparison is character by character: https://app.example.com/callback and https://app.example.com/callback/ are two different URIs.
  3. 3Set the project session lifetime and 2FA policy (disabled, optional, mandatory).
  4. 4Generate a separate API key (ak_live_…) if the backend will also do provisioning: the project key is for login, the API key for administrative operations.
App integration — TypeScript
npm install @loginmaster/sdk
app/auth.ts
import { LoginMaster } from "@loginmaster/sdk";

const lm = new LoginMaster({
  projectKey: process.env.LOGINMASTER_PROJECT_KEY,
  tenant: "https://tenant.example.com",
});

// In the OIDC callback: verify the dual-signature token (tenant + cloud)
const session = await lm.verifyToken(token);
if (session.valid) {
  const userId = session.subject; // e.g. sub_9f2a7c
}

The same applies on .NET with the ASP.NET Core middleware; both full quickstarts are on Integration. If you use neither TypeScript nor .NET, the same operations are available over REST: POST /v1/auth/token and POST /v1/auth/verify.

Step 2 — Federate Microsoft Entra ID via OpenID Connect

This is the path to prefer with Entra ID when there are no historical constraints. In the Entra ID portal: App registrations → New registration.

  1. 1Supported account types: choose "Accounts in this organizational directory only" for a closed corporate SSO, or multitenant if you must accept several customer directories.
  2. 2Redirect URI (Web type): the broker callback endpoint, not the one of the final application.
  3. 3Certificates & secrets: generate a client secret (or better, register a certificate) and store it in the broker tenant.
  4. 4API permissions: openid, profile, email. Add User.Read only if you need to read the Graph profile; SSO alone does not require it.
  5. 5Token configuration: add the groups claim if you want to map Entra groups onto application roles.
Entra ID tenant discovery document
https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration

From that document the broker automatically derives the authorization endpoint, the token endpoint and the jwks_uri, so Microsoft's signing key rotation requires no manual work. The relevant ID token claims are:

ClaimContentRecommended use
oidImmutable object ID of the user in the directoryIdentity correlation key: use this, not the email
tidTenant ID of the Entra directoryCheck the user comes from the expected directory (multitenant)
preferred_usernameUPN or sign-in emailDisplay; it can change over time
emailEmail addressNotifications; do not use it as a stable identifier
groups / rolesAssigned groups or app rolesMapping onto project roles

Step 3 — Federate Microsoft Entra ID via SAML 2.0

You need this when the organisation has already standardised on SAML or when the IdP is on-premise ADFS. In the portal: Enterprise applications → New application → Create your own application → Integrate any other application, then Single sign-on → SAML.

Entra ID fieldWhat to enterName in the SAML standard
Identifier (Entity ID)The unique Service Provider identifier, e.g. https://tenant.example.com/saml/metadataSP EntityID
Reply URLThe endpoint receiving the signed assertion, e.g. https://tenant.example.com/saml/acsAssertion Consumer Service (ACS) URL
Sign on URLEntry point for the SP-initiated flowSP-initiated SSO URL
Logout URLSingle Logout endpoint, if you implement itSLO endpoint
User Identifier (Name ID)user.objectid, not user.mailNameID (persistent format)

Then download the Federation Metadata XML and upload it to the broker: it contains the IdP EntityID, the SSO endpoints and the signing certificate, and importing it avoids transcribing the certificate by hand.

Entra ID IdP metadata
https://login.microsoftonline.com/{tenantId}/federationmetadata/2007-06/federationmetadata.xml

The same rule as the oid claim applies to the NameID: set user.objectid with persistent format. The Entra ID default is often the email address, and it is the number-one cause of duplicate accounts after a corporate reorganisation.

Signing certificate rotation

Entra ID SAML certificates default to a three-year validity, and expiry breaks login for every user at the same instant. Two concrete countermeasures: configure expiry notifications to a monitored mailbox, and import the IdP metadata by URL rather than as a file, so the broker re-reads the certificate without a manual task scheduled three years in advance.

Step 4 — Federate Google Workspace via OpenID Connect

Google exposes a public discovery document and a single issuer for all domains, so configuration is shorter than Entra ID's — but with one extra security requirement.

Google discovery document
https://accounts.google.com/.well-known/openid-configuration
  1. 1In Google Cloud Console create a project and, under APIs & Services → Credentials, an OAuth 2.0 Client ID of type Web application.
  2. 2Authorized redirect URIs: the broker callback endpoint (exact, https, no trailing slash unless you use one).
  3. 3Configure the OAuth consent screen as Internal if you want to restrict it to the Workspace domain only.
  4. 4Requested scopes: openid, email, profile.
  5. 5Validate the hd (hosted domain) claim on every login on the broker side: without that check, any personal Gmail account going through the same consent screen is technically a valid login.

Step 5 — Federate Google Workspace via SAML 2.0

In the Admin console: Apps → Web and mobile apps → Add app → Add custom SAML app. Google shows its own metadata (SSO URL, Entity ID, certificate) to upload to the broker; then you fill in the Service Provider ACS URL and Entity ID.

  1. 1Copy or download Google's IdP metadata and import it into the broker.
  2. 2Service provider details: broker ACS URL and Entity ID; Name ID format PERSISTENT and Name ID = Basic Information > Primary email (or a custom immutable attribute, if you manage one).
  3. 3Attribute mapping: map at least primary email, first name, last name; add groups if you need them for roles.
  4. 4User access: assign the app to the organisational units or groups that must have access. Skip this and login fails with app_not_configured_for_user.
  5. 5Allow for propagation: Admin console changes can take several minutes to become effective for all users.

Step 6 — Map claims and groups onto application roles

The real value of federated SSO is not saving a password: it is that authorisation stops living in a local table nobody updates. A user who moves department changes group in the directory, and the application role follows at the next login with no IT ticket.

SourceExampleProject role
Entra ID group (groups claim)GRP-FINANCE-APPROVERSapprover
Entra ID app role (roles claim)Admin.Billingbilling-admin
Google Workspace groupadministration@example.comadmin
Workspace custom attributedepartment = Supportsupport-agent
Verified email domain (hd claim)example.commember (baseline role)

Two rules that prevent incidents: always assign a minimal baseline role to anyone who authenticates but matches no rule (instead of inheriting the last known role), and recompute roles at every login rather than only at account creation. The second point is what makes privilege revocation effective, not just access revocation.

If there are many groups to propagate, note that Entra ID "overages" the token beyond a certain group count and returns a Graph reference instead of the list: in that case, map explicit app roles rather than raw groups.

Step 7 — Session, revocation and deprovisioning

SSO is half the problem; the other half is what happens when access must stop. With federation, disabling the account in the corporate directory stops new sessions being issued on federated services: you do not have to remember to disable the user on every platform. The residual window is the lifetime of tokens already issued, which is why it should be sized deliberately.

ScenarioEffectConfiguration lever
Account disabled in the IdPNo new federated sessionsImmediate at the next login
Access token already issuedStays valid until expiryProject token lifetime (e.g. 3600 s)
Immediate revocation requiredSession closed on the application sidesubject.deactivated webhook + app-side invalidation
Role changePermissions updated at the next loginRole recomputation on every authentication
Lost deviceActive sessions closedUser session management page

For immediate revocation the lever is the webhook: the broker notifies the application of the event and the application invalidates its own session, with no polling.

Deprovisioning webhook (HMAC-SHA256 signed payload)
POST /hooks/loginmaster HTTP/1.1
X-LoginMaster-Signature: sha256=9f86d081884c...
Content-Type: application/json

{
  "id": "evt_7c1e2f",
  "type": "subject.deactivated",
  "createdAt": "2026-09-10T09:24:00Z",
  "tenant": "https://tenant.example.com",
  "data": { "subjectId": "sub_9f2a7c", "project": "prj_12ab" }
}

The full lifecycle (creation, role change, suspension, deletion) is covered in User provisioning and lifecycle via REST API and SDK.

Testing: nine checks before release

  1. 1SP-initiated login: from the application, with the user not yet authenticated at the IdP.
  2. 2IdP-initiated login: from the Microsoft or Google portal (SAML only; it does not exist in OIDC, and asking for it signals a mis-stated requirement).
  3. 3Valid user not assigned to the application: it must fail with an understandable message, not a blank page.
  4. 4User from an external domain: must be rejected (hd or tid claim verification).
  5. 5Expired session: silent renewal and, where impossible, a clean return to the login screen.
  6. 6Logout: check whether the IdP session stays open; with partial SLO the user 'leaves' and re-enters with one click, and that must be documented.
  7. 7Account disabled in the IdP: new login refused within the expected time.
  8. 8Clock skew: move a client clock by 10 minutes and check the error message (SAML will fail on the NotBefore / NotOnOrAfter conditions).
  9. 9Signing certificate rotation: simulate it in a test environment, do not discover it in production.

Typical errors and how to read them

SymptomMost likely causeFix
AADSTS50011Redirect URI does not match the registered oneAlign character by character, trailing slash included
AADSTS700016Application not found in the directoryWrong client ID, or app registered in another tenant
AADSTS50105User not assigned to the applicationAssign the user or group to the Enterprise application
app_not_configured_for_user (Google)SAML app not assigned to the organisational unitAssign the app to the OU or group in Admin console
Signature validation failedIdP certificate expired or stale on the SPRe-import the IdP metadata, preferably by URL
Assertion rejected on time conditionsClock skew between IdP and SPSync via NTP; typical tolerance ±5 minutes
Duplicate users after a reorganisationIdentity correlated on email instead of an immutable IDCorrelate on oid / sub / persistent NameID
invalid_client on the token endpointExpired client secretRotate the secret and schedule the next expiry

Managed broker, self-hosting or direct integration

All three routes are viable, but their cost and risk profiles differ sharply. The honest comparison is about the work left after the first successful login.

AspectDirect per-app integrationSelf-hosted broker (e.g. Keycloak)Managed broker (LoginMaster)
Configurations to maintainN apps × M identity providers1 per IdP, but you own the infrastructure1 per IdP, managed infrastructure
SAML certificate rotationManual on every applicationCentralised, to be staffedCentralised, via metadata URL
IdP patches and CVEsOn every application teamOn your team (major upgrades included)On the vendor
Customer/tenant isolationTo be designedSeparate realms, logical isolationCryptographic isolation: tokens signed per tenant and project
Admin credential resetDepends on the appPossible for the realm adminTechnically impossible: the user only
Cost as users growHidden in team timeInfrastructure + staffingPer tenant and project, unlimited users
Data jurisdictionVariesWherever you install itEU, personal data only in the tenant

What sets LoginMaster apart in the bottom rows is not commercial but architectural: the token returned to the application carries two independent signatures, one from the tenant and one from the cloud, and a token issued for tenant A fails validation in the context of tenant B even when the two share the deployment. Architecture details are on Security, while the SSO page collects the available federation features. Teams coming from a Keycloak installation will find the full path in Migrating from self-hosted Keycloak to a managed IAM.

Where this guide comes from

LoginMaster is the IAM platform of CDBKR S.r.l., an Italian company that builds and operates authentication infrastructure for software houses, MSPs and European enterprise organisations. The procedures described here are the ones the team applies in federation projects towards Entra ID and Google Workspace, including the case where both directories coexist in the same organisation. A real adoption example is documented in the case studies; to assess your own scenario, start from the contact page.

Frequently asked questions

It depends on which side of the integration you are on. Between your applications and the identity broker use OpenID Connect: it is JSON, it supports SPAs and mobile apps with Authorization Code + PKCE and it handles token renewal. Between the broker and Entra ID choose OIDC if you have no historical constraints; use SAML 2.0 if the organisation has already standardised on SAML or if the identity provider is on-premise ADFS. Not every application needs to speak the identity provider's protocol: that is exactly the job of the broker.

Yes, and it is a frequent scenario after acquisitions or in companies whose departments run different suites. The broker registers both identity providers and either presents the choice to the user or routes automatically based on the domain of the email address entered (home realm discovery). Applications do not see the difference: they always receive an OIDC token with the same claim shape, whichever IdP authenticated the user.

The technical configuration of an OIDC federation to Entra ID or Google Workspace is a matter of a few hours: app registration on the IdP side, redirect URI, scopes and claim mapping. The SAML 2.0 route adds the metadata exchange and NameID verification. Real project time is almost always dominated by testing — unassigned users, external domains, revocation, certificate rotation — not by the initial configuration.

Access to federated services stops with no manual work: the corporate directory no longer authenticates the user, so the broker issues no new sessions. Tokens already issued stay valid until their configured expiry (typically one hour), so for immediate revocation you use the subject.deactivated webhook, which notifies the application to invalidate its own session. That is the difference between revoking access and revoking the session in progress: both need to be designed.

Because email changes: marriages, surname changes, domain mergers, reorganisations. If application identity hangs off the email, at the next login the user looks like a new person and loses history, roles and data. Always correlate on an immutable identifier: the oid claim in Entra ID, the sub claim in Google, the persistent-format NameID in SAML. Email stays a useful attribute, but an updatable one.

In federated SSO passwords never pass through the broker: the user authenticates at Entra ID or Google and the broker only receives an assertion or an ID token. For local users — non-federated ones, typical of mixed scenarios with partners and end customers — the answer depends on the vendor. In LoginMaster credentials are protected with Argon2 and a split salt between tenant and cloud, and no function exists that returns or resets a user's password: not even the tenant administrator can do it.

The broker can act as a SAML Identity Provider towards those applications while remaining a Service Provider towards Entra ID or Google Workspace. In practice the legacy application sees a classic SAML IdP (Entity ID, ACS URL, signing certificate) while upstream authentication happens against the corporate directory. That way you neither touch the application code nor duplicate credentials, which is the main reason migrating those applications gets postponed for years.

It adds to it. If the corporate identity provider already enforces MFA, the broker can accept it and not ask for a second one, reading the authentication information carried in the token. If instead you need a specific second factor on sensitive applications — an admin panel, an area with financial data — the policy is set at project level, independently of what the IdP does. The detail of TOTP and conditional access policies is in the dedicated LoginMaster guide.

Want to see LoginMaster in action?

Request a personalized demo and discover how to manage identities and access securely and compliantly.