To use Microsoft Entra ID as a SAML identity provider in Keycloak, create a non-gallery Enterprise Application in the Microsoft Entra admin center, set up SAML single sign-on with your realm’s Entity ID and the broker’s ACS URL, download the Federation Metadata XML, import it into Keycloak as a SAML v2.0 identity provider, and then add attribute mappers for email, first name and last name. Once a user is assigned to the application, they can sign in to your realm with their Microsoft 365 account.
This guide walks through that loop screen by screen, as the Entra admin center and the Keycloak 26.x admin console lay it out in November 2026. It is written for Keycloak admins who know their way around the admin console but do not live in Entra every day, and it ends with a section of fixes for the SAML errors you are most likely to meet, each with the message you will see and the one setting that fixes it.
SAML or OIDC: which one should you use with Entra ID?
Both protocols work, and Keycloak brokers both. If you have no requirement that says SAML, OpenID Connect (OIDC) is usually the simpler choice, because there is no certificate to roll over on your side and the claims are plain JSON. We cover that path in setting up Microsoft Entra ID SSO with Keycloak over OIDC. Choose SAML, and this guide, when your security team mandates SAML for enterprise federation, when the tenant already runs its other apps over SAML, or when you need the user’s attributes as SAML assertions rather than token claims.
What you need before you start
- A Keycloak 26.x realm and an admin account for it. Every URL below uses the current Quarkus distribution, so none of them includes the old
/auth/prefix. - A Microsoft Entra tenant and one of the roles Microsoft lists for this setup: Cloud Application Administrator, Application Administrator, or owner of the service principal.
- Three values you choose up front: your Keycloak base URL, the realm name and the alias you will give the identity provider in Keycloak. This guide uses
https://keycloak.example.com,my-realmandentra-id.
The alias matters early because it is part of the URL Entra sends users back to, so pick it now and keep it.
Step 1: Work out the two Keycloak values Entra needs
Entra needs two values from Keycloak: the Entity ID that identifies your realm as a SAML service provider, and the Assertion Consumer Service (ACS) URL, which is the address Entra posts the signed login response to. Keycloak’s documentation gives the default Service Provider Entity ID as the realm’s base URL, and the ACS URL is the broker endpoint for your alias, the same path as the SP descriptor Keycloak documents without the final /descriptor:
| Value | For this guide |
|---|---|
| Entity ID (Entra calls it Identifier) | https://keycloak.example.com/realms/my-realm |
| ACS URL (Entra calls it Reply URL) | https://keycloak.example.com/realms/my-realm/broker/entra-id/endpoint |
You will confirm both against Keycloak’s own screens in Step 5, so a typo here is cheap to catch.
Step 2: Create a non-gallery Enterprise Application in Entra ID
- Sign in to the Microsoft Entra admin center.
- Browse to Entra ID › Enterprise apps › All applications, which is the path Microsoft’s SSO quickstart uses today. Older guides say Identity › Applications › Enterprise applications, which is the previous layout of the same menu.
- Select New application, then Create your own application.
- Name it (for example “Keycloak my-realm”), choose Integrate any other application you don’t find in the gallery (Non-gallery) and select Create.
Entra creates the application and its service principal and opens the app’s overview page.
Step 3: Set up SAML single sign-on in Entra ID
In the app’s left menu, select Single sign-on and then SAML. The Set up Single Sign-On with SAML page shows numbered cards: Basic SAML Configuration, Attributes & Claims, SAML Certificates, the setup values for the app, and a test card.
Basic SAML Configuration
Select Edit on the Basic SAML Configuration card and fill it in:
| Field | Value |
|---|---|
| Identifier (Entity ID) | https://keycloak.example.com/realms/my-realm |
| Reply URL (Assertion Consumer Service URL) | https://keycloak.example.com/realms/my-realm/broker/entra-id/endpoint |
| Sign on URL | leave blank |
| Relay State | leave blank |
| Logout Url | https://keycloak.example.com/realms/my-realm/broker/entra-id/endpoint |
Save the card. Microsoft’s SAML protocol reference says the Issuer in each request “must exactly match one of the ServicePrincipalNames” of the app, which is why the Identifier has to be character for character the same as the Entity ID Keycloak sends, trailing slash included.
The Logout Url points at the same broker endpoint as the Reply URL because that endpoint is where Keycloak, acting as the service provider, handles logout requests from the identity provider. Earlier versions of this guide used the realm’s /protocol/saml endpoint, which is the endpoint Keycloak documents for its own SAML clients, so we no longer recommend it here.
Attributes & Claims
Select Edit on Attributes & Claims. A new non-gallery app already sends the claims Keycloak needs, under these names:
| Claim | Source attribute | SAML attribute name |
|---|---|---|
| Unique User Identifier (Name ID) | user.userprincipalname |
the SAML Subject |
user.mail |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress |
|
| Given name | user.givenname |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname |
| Surname | user.surname |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname |
If you want Keycloak usernames to be email addresses, open the Unique User Identifier claim, set its source attribute to user.mail and its Name identifier format to Email address. A user principal name looks like an email address but is not always one that receives mail, especially in tenants with several domains. You will match this format on the Keycloak side in Step 5, and the fixes section explains what happens when the two sides disagree.
Assign users and groups
Assignment lives in the app’s left menu under Users and groups, outside the SAML cards, so it is easy to skip. Select Add user/group, pick the users or groups that should sign in to the realm, and select Assign. Without it, the first test login stops at error AADSTS50105, covered below.
Step 4: Get the federation metadata from Entra ID
On the SAML Certificates card you have two ways to hand Entra’s settings to Keycloak:
- The app’s federation metadata URL, which Microsoft describes as the per-tenant, per-application metadata URL. This is the better choice when Keycloak can reach
login.microsoftonline.com, because Keycloak can download new certificates from it later. - The Federation Metadata XML file, through its Download link, for Keycloak hosts that cannot make outbound calls to Microsoft.
Either one carries Entra’s Entity ID, its single sign-on and logout URLs and the certificate it signs responses with, so you do not copy those values by hand.
Somewhere to run this that stays patched
Everything above works the same on Skycloak, because it is real upstream Keycloak rather than a fork. What changes is who handles the upgrades, backups and security patches afterwards.
Step 5: Add Entra ID as a SAML v2.0 identity provider in Keycloak
- Open the admin console at
https://keycloak.example.com/admin/and selectmy-realm. - Select Identity providers and choose SAML v2.0.
- Set Alias to
entra-idand Display name toMicrosoft Entra ID. - Check that the Redirect URI shown on the form is
https://keycloak.example.com/realms/my-realm/broker/entra-id/endpoint, the Reply URL you entered in Entra, and that Service provider entity ID is the realm URL you entered as the Identifier. - To import the metadata, leave Use entity descriptor on and paste the federation metadata URL, or turn it off and import the XML file you downloaded.
- Select Add.
Keycloak fills in the single sign-on service URL, the single logout service URL and the validating certificate from the metadata. Then review these settings on the provider’s page:
| Setting | Value | Why |
|---|---|---|
| NameID policy format | Keycloak’s documented default is persistent, and for persistent Entra issues a pairwise identifier instead of the email | |
| Principal type | Subject NameID | Keycloak identifies the user by the SAML Subject |
| HTTP-POST binding response | On | |
| HTTP-POST binding for AuthnRequest | On | |
| Want AuthnRequests signed | On | Keycloak signs the SAMLRequest it sends with the realm key |
| Validate Signatures | On | Keycloak checks Entra’s signature on every response |
| Use metadata descriptor URL | On, with the metadata URL | Keycloak then downloads Entra’s signing certificates from that URL instead of relying on the pasted copy |
| Trust Email | On | Keycloak marks the email as verified on first login, which suits a tenant that manages its own addresses |
| First login flow | first broker login | Creates the Keycloak user, or links an existing one |
| Sync mode | Import, or Force to refresh profile fields on every login |
Save the page. The Endpoints item on the provider page links to the SAML 2.0 Service Provider Metadata for this alias, at /realms/my-realm/broker/entra-id/endpoint/descriptor, which is a quick way to see exactly what Keycloak expects.
If you run Keycloak on Skycloak, our identity providers guide lists Azure AD among the SAML providers and covers the rest of the page.
The user picks Microsoft Entra ID on the Keycloak login page (1), Keycloak sends a signed AuthnRequest whose Issuer is the realm URL (2), Entra checks the Issuer against the app’s Identifier and the user’s assignment (3), posts a signed SAMLResponse to the broker endpoint (4), and Keycloak checks the signature, runs the mappers and creates or links the user (5).
Step 6: Add attribute mappers for email, first name and last name
Without mappers, Keycloak creates the user from the Subject alone and the profile stays empty. On the provider page, open the Mappers tab and select Add mapper three times, each with the mapper type Attribute Importer and sync mode override Inherit:
| Name | Attribute Name | User Attribute Name |
|---|---|---|
email |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress |
email |
firstName |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname |
firstName |
lastName |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname |
lastName |
The Attribute Name must match the Name of the attribute in the assertion exactly, full URI included. If you need to map other Entra claims, such as groups or an employee ID, the approach is the same as in our guide to attribute mapping during identity brokering, with SAML attribute names in place of OIDC claim names.
Step 7: Test the login end to end
Open the account console at https://keycloak.example.com/realms/my-realm/account/ in a private window and pick Microsoft Entra ID on the login page. To skip Keycloak’s login page and go straight to Entra, add kc_idp_hint=entra-id to an authorization request:
https://keycloak.example.com/realms/my-realm/protocol/openid-connect/auth?client_id=account-console&response_type=code&scope=openid&redirect_uri=https://keycloak.example.com/realms/my-realm/account/&kc_idp_hint=entra-id
Sign in as an assigned user. On the first login, the first broker login flow creates the Keycloak user, or asks to link it if an account with the same email already exists, which we explain in the “account already exists” error during brokering. Afterwards, open Users in the admin console and check that the new user has an email, a first and last name, and an entra-id entry under Identity provider links.
If you broker several Entra tenants into one realm, one per customer, you can route each user to the right tenant by email domain instead of showing a button per tenant, as described in home realm discovery with Keycloak Organizations.
Fixes for common errors
Errors that start with AADSTS come from Entra and show on Microsoft’s sign-in page, so Keycloak’s log has nothing for them. Errors on Keycloak’s own error page come with a line in the Keycloak server log, and the messages below are the ones we read in Keycloak’s SAMLEndpoint source at the 26.8.1 tag. Their wording can differ in other versions, so go by the meaning if yours does not match exactly. When you need to see what Entra actually sent, copy the SAMLResponse form field from the POST to the broker endpoint in your browser’s network tab and decode it.
AADSTS50105: the user is not assigned to the application
Microsoft’s error reference describes this code as a signed-in user who isn’t assigned to a role for the app, and so does its troubleshooting article for AADSTS50105. Keycloak never sees the request. The fix is in Users and groups on the Enterprise Application: assign the user, or a group they belong to.
AADSTS700016: the application was not found in the directory
The error reference says the application could not be found in the directory or tenant and names a misconfigured identifier as one cause. For SAML, it means the Issuer in Keycloak’s AuthnRequest, the Service provider entity ID, matches no app’s Identifier in the tenant. The fix is to make the two identical, usually by copying the realm URL from Keycloak into the Identifier field. Check also that the single sign-on URL in Keycloak points at the tenant where you created the app, which it does when it came from that app’s metadata.
AADSTS50011: the Reply URL does not match
Keycloak puts its ACS URL in the AuthnRequest, and Entra rejects it when it is not one of the app’s Reply URLs: the reference lists this code as InvalidReplyTo, and Microsoft has a troubleshooting article for the mismatch. The usual causes are a different alias, http against https behind a proxy, or a trailing slash. Copy the Redirect URI from the Keycloak provider page into Reply URL in Basic SAML Configuration. If the URL in the request has the wrong scheme or host, fix the hostname and proxy settings of Keycloak itself rather than adding the wrong URL to Entra.
“Invalid requester” after Entra sends you back
This Keycloak page means the response arrived but did not match what the provider expects. The log line tells you which part:
no principal in assertion; expected: ...(wordedmissing or blank principal in assertionon Keycloak’s main branch) means Keycloak looked for the user’s identity where Principal type says and found nothing. Set Principal type to Subject NameID, or, if you identify users by an attribute, make sure Entra sends that attribute under exactly the name in Principal attribute.Response Issuer validation failed: expected ..., actual ...means the Identity provider entity ID in Keycloak is not the Issuer Entra sends, often because the metadata came from another tenant or app. Re-import the metadata of this app.
A related symptom, without an error, is users created with opaque IDs as usernames. That is the NameID format: Keycloak asked for persistent, its default, and Entra answered with a pairwise identifier as the SAML protocol reference says it does. Set NameID policy format to Email in Keycloak, and keep the Unique User Identifier in Entra on an email-address attribute.
“Invalid signature in response from identity provider” after a certificate rollover
Keycloak logs validation failed and shows this page when Entra signs with a certificate Keycloak does not have. It tends to happen without warning on the day someone makes a new certificate active in Entra. Entra’s auto-generated signing certificate is valid for three years, and Microsoft sends notification emails 60, 30 and 7 days before it expires, to the admin who added the app unless you add up to five addresses on the SAML Signing Certificate page.
Turn on Use metadata descriptor URL, with the app’s metadata URL in Metadata descriptor URL, to prevent it. Keycloak’s documentation says that with it on, the certificates that validate signatures are downloaded from that URL. If your host cannot reach Microsoft, create the new certificate in Entra while it is still inactive, add it to Validating X509 certificates next to the old one (the field takes several, separated by commas), and only then select Make certificate active in Entra.
Single logout does not end the Keycloak session
When a user signs out of Microsoft 365, Entra sends a LogoutRequest to the app’s Logout Url, and the broker endpoint’s logout code in the 26.8.1 source looks up the brokered session by the SessionIndex in it, using the value it stored at login. If the Logout Url is the realm’s /protocol/saml endpoint, the request goes to the endpoint Keycloak documents for its own SAML clients rather than to that broker code. Set the Logout Url to the broker endpoint, as in Step 3.
If your realm is also a SAML identity provider for downstream applications, note that, as we cover in the Keycloak 26.8.1 SAML logout fix, Keycloak 26.8.1 rejects a LogoutRequest whose SessionIndex belongs to a different client and records the reason session_index_not_owned_by_issuer, in this check in the SamlService source. A downstream app that logs out other apps’ sessions will start seeing bad request responses after that upgrade.
Clock differences between Keycloak and Entra
SAML assertions carry a validity window, and Keycloak rejects one that falls outside it. If logins fail right after Entra redirects back and the server’s clock is off, fix time synchronization on the Keycloak hosts first. The provider’s Allowed clock skew setting tolerates a small difference, but it hides the real problem if the clock keeps drifting.
Frequently asked questions
Can one Entra application serve several Keycloak realms?
Not cleanly. Each realm is its own SAML service provider with its own Entity ID, and the Issuer has to match the app’s Identifier, so the usual setup is one Enterprise Application per realm. That also keeps user assignment separate per realm.
Can I import the metadata by URL instead of a file?
Yes. Paste the app’s federation metadata URL with Use entity descriptor on when you create the provider, and turn on Use metadata descriptor URL afterwards so Keycloak keeps Entra’s certificates current. Fall back to the XML file only when Keycloak cannot reach Microsoft.
Why does Keycloak ask an existing user to link their account?
The first broker login flow found a Keycloak account with the same email or username and, by default, asks the user to confirm the link rather than linking silently. Keycloak’s first login documentation cautions against linking an existing account automatically, because you cannot always trust the information an external identity provider sends, so change the flow only when you trust the tenant’s email addresses.
Does Entra require signed AuthnRequests?
Only if you configure it to. Microsoft’s SAML protocol reference says Entra can enforce signed requests, and otherwise relies on responding only to registered ACS URLs. Signing them from Keycloak costs nothing and is harmless when Entra does not check.
Next steps
You now have Entra ID brokered into your realm over SAML: users are assigned in Entra, Keycloak validates every response against Entra’s current certificate, and the mappers fill in email and name on first login. Keep the Identifier, Reply URL and Logout Url identical on both sides, and leave Use metadata descriptor URL on so the next certificate rollover passes without anyone noticing.
When a login fails and the log line is not enough, paste the SAMLResponse into the Skycloak SAML decoder to check the NameID, the Issuer and the attribute names Entra sent. For the service provider side of Keycloak in more depth, read Keycloak as a SAML service provider. If you would rather spend your time on the integration than on running Keycloak, look at managed Keycloak hosting on Skycloak.


