Connect Microsoft Entra ID
Connect Microsoft Entra ID as an identity provider for zone-level user authentication.
This is the Microsoft Entra ID walkthrough for Authenticate users with your identity provider. It connects Microsoft Entra ID to a custom Zone. You register an application in your tenant, create a Provider in Keycard that points at it, and select that Provider for the Zone’s sign-in.
You need Manager access to the custom Zone; organization Admins aren’t Managers of a custom Zone automatically (see Assign Zone Admin Access). In Entra ID you need at least the Application Developer role, plus Cloud Application Administrator to grant admin consent, assign users, or add a groups claim, and User Administrator to set a user’s email address.
Use one app registration per Zone, and keep it for the life of the Zone.
Keycard links each person to their User by the ID token’s issuer and sub, and
Entra ID issues a different sub for each app registration, so replacing the
registration can lock out returning users. Rotate its secret instead.
The Zone in this tutorial is named “Example”. Replace <zone-id> with your
Zone ID, which appears in the Zone’s domain (<zone-id>.keycard.cloud), and
<tenant-id> with your Directory (tenant) ID.
Create an app registration in Microsoft Entra ID
Section titled “Create an app registration in Microsoft Entra ID”-
Sign in to the Microsoft Entra admin center. If you have access to more than one tenant, use the Settings icon in the top menu to switch to the tenant whose users will sign in to the Zone. Browse to Entra ID > App registrations and select New registration.
-
Enter “Example”, the name of your Zone, as the Name. Users can see it. Under Supported account types, select Single tenant only (in older versions, Accounts in this organizational directory only), then select Register. Keycard matches the Issuer URL against the discovery document’s
issuerexactly, and thecommonandorganizationsendpoints that multitenant apps use publish a placeholder issuer that never matches. -
On the Overview page, copy the Application (client) ID and the Directory (tenant) ID.
-
Under Manage, select Authentication. On the Redirect URI configuration tab, select Add Redirect URI, then the Web platform tile (in older versions, Platform configurations > Add a platform). Enter your Zone’s Redirect URL as the Redirect URI and select Configure. Leave implicit grant and hybrid flows off, because Keycard uses the authorization code flow with PKCE.
-
(Optional) Add a sign-out redirect URI. Keycard signs a user out of Entra ID too only when single logout is enabled on the Provider, a Keycard API setting (
protocols.openid.single_logout_enabled) that Console doesn’t offer. If you enable it, addhttps://<zone-id>.keycard.cloud/openid/connect/redirect/logout(or the same path on your custom domain) as a second Web redirect URI, because Entra ID returns users after sign-out only to a registered redirect URI. -
Under Manage, select Certificates & secrets, then Client secrets > New client secret. Add a description, choose an expiration (Entra ID allows up to 24 months and recommends less than 12), and select Add. Copy the Value column now, not the Secret ID; Entra ID never shows it again. The Provider accepts only a client secret, not a certificate or a federated credential, so if your tenant restricts client secrets, get an exception for this app registration first.
-
Make sure every user who will sign in has an email address in Entra ID. Keycard creates each User from the ID token’s
emailclaim, and Entra ID leaves that claim out for accounts with no email address, so those users can’t sign in. Guests invited by email already have one. For a member account, open Entra ID > Users, select the user, select Edit properties, enter the address under Contact info, and select Save. For users synced from Windows Server Active Directory, set it there. -
Grant admin consent if your tenant requires it. When users can’t consent to applications themselves, or the app requires assignment (next step), they see an Entra ID prompt asking for admin approval at first sign-in. Select API permissions > Add a permission > Microsoft Graph > Delegated permissions, select
openid,profile, andemail, and select Add permissions. Then select Grant admin consent for your tenant and confirm with Yes. -
(Optional) Limit who can sign in. Otherwise any user in your tenant, including invited guests, can sign in to the Zone. Open Entra ID > Enterprise apps > All applications, select the app, set Assignment required? to Yes on the Properties page, and save. Under Users and groups > Add user/group, assign the users or groups who should reach the Zone. Assigning groups requires Microsoft Entra ID P1 or P2, assignment doesn’t extend to members of nested groups, and Global Administrators can still sign in.
Keep the app’s Overview page open for the next phase.
Create a Provider in Keycard
Section titled “Create a Provider in Keycard”-
In Keycard Console, go to Zones, open the ⋯ menu on your Zone’s card, and select Switch to zone. Keycard creates a Provider in the Zone you’re working in, and opening a Zone’s Settings from its card doesn’t switch you into it. A Provider created in another Zone never appears in this Zone’s Identity Provider dropdown. If Switch to zone is missing and you aren’t already working in that Zone, you don’t have access to it yet. Creating a Provider takes Manager access; see Assign Zone Admin Access.
-
Select Providers in the navigation menu, then click Add Provider.
-
In the Name field, enter “Microsoft Entra ID”. You select the Provider by this name in the next phase.
-
In the Issuer URL field, enter
https://login.microsoftonline.com/<tenant-id>/v2.0, using the tenant ID rather than a domain name and no trailing slash. To check it, openhttps://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration; itsissuermust match exactly. This tutorial covers the Microsoft Entra global service; national clouds use a different sign-in host. -
In the Client ID field, enter the Application (client) ID. In the Client Secret field, enter the secret Value.
-
Leave Advanced options at their defaults, including Identifier and Additional Scopes. Keycard always requests
openid,profile, andemail, which is all Entra ID needs, and Entra ID sends groups from token configuration rather than a requested scope, so don’t addgroupshere the way an Okta groups setup does.(Optional) By default, the
subin tokens Keycard issues for a User is the User’s Keycard ID. To use the Entra object ID instead, which is the same across every application in your tenant, set User Identifier Claim tooid. Keycard reads it only when it creates a User at sign-in, so set it before anyone signs in. A User that directory sync provisions keeps its Keycard ID. -
Click Create Provider. Console opens the new Provider’s Configuration tab.
You can also create this Provider and select it for the Zone with the
Keycard Terraform provider,
using keycard_provider (with oauth2.issuer set to the Issuer URL above) and
keycard_zone_user_identity_config. Register the Zone’s oauth2.redirect_uri,
from the keycard_zone resource or data source, as the redirect URI in Entra
ID. Terraform can’t set User Identifier Claim.
Use Microsoft Entra ID for sign in
Section titled “Use Microsoft Entra ID for sign in”-
While you’re working in the Zone, select Settings under Zone in the navigation menu. The Zone configuration page opens.
-
Select the Settings tab.
-
In the Zone sign in configuration section, open the Identity Provider dropdown and select Microsoft Entra ID. Your organization Zone doesn’t show this section; you set its sign-in through Single Sign-On instead.
-
Click Save Changes.
Keycard now sends every sign-in to this Zone straight to Microsoft Entra ID and creates each User the first time that person signs in. To confirm, sign in to an Application in the Zone with an Entra ID account, then check that the User appears under People in the Zone.
Claims Keycard reads from Microsoft Entra ID
Section titled “Claims Keycard reads from Microsoft Entra ID”Keycard reads the ID token Entra ID returns at sign-in and doesn’t call its
userinfo endpoint, so anything policy needs has to be in the ID token. Only
email and groups reach policy as claims. A claim you set as User
Identifier Claim reaches policy only indirectly, as the identifier
(principal.identifier) of each User created at sign-in. Entra app roles in
the roles claim don’t reach policy.
| Claim | How Keycard uses it |
|---|---|
iss and sub |
Link the Entra ID account to its Keycard User |
email |
Required to create the User, and available to policy as context.subject_claims.email |
groups |
Captured at sign-in, and available to policy as context.subject_claims.groups |
Use the Entra ID groups claim to bring your directory’s groups into policy.
Keycard captures it at sign-in, so a new claim or a membership change reaches
policy only in sessions that start after the user signs in again, and tokens
Keycard issues don’t carry it. An agent that already holds a refresh token
keeps the earlier groups; see
What Keycard receives from your identity provider.
Keycard Groups are an alternative that policy reads every
time it evaluates, so a membership change applies to the next credential
request; see
Group-based Policies.
Send group membership to Keycard
Section titled “Send group membership to Keycard”-
In the Microsoft Entra admin center, open the app registration and select Token configuration under Manage.
-
Select Add groups claim.
-
Select Security groups, or Groups assigned to the application to send only the groups you’ve assigned to the app under Enterprise apps.
-
Leave each token type’s group format at its default, and don’t change the claim type to a role. Keycard reads only a claim named
groups. -
Select Save.
Match Entra ID groups in policy
Section titled “Match Entra ID groups in policy”Entra ID identifies each group by its object ID, a GUID, so rules compare against that ID. Find it as Object ID on the group’s Overview page under Entra ID > Groups.
@id("permit-entra-group")permit ( principal is Keycard::User, action, resource) when { context has subject_claims && context.subject_claims has groups && context.subject_claims.groups.contains("<group-object-id>")};Entra ID can send display names instead, but only for cloud groups assigned to
the application, and sAMAccountName values only for groups synced from Active
Directory; either changes the strings your rules must match. Two more limits:
- For a user in more than 200 groups, counting nested membership, Entra ID
leaves
groupsout of the ID token and sends a pointer to Microsoft Graph. Keycard reads groups only from the claim, so group-based rules don’t match that user. Groups assigned to the application keeps the list short. - Groups assigned to the application includes direct members only.
To check a rule without a live sign-in, see Test an identity provider groups claim. For the full pattern, see Same agent, different user.
Troubleshooting
Section titled “Troubleshooting”Sign-in fails with access_denied: no email address
Entra ID sent no email claim for this user. Keycard stops the sign-in with
access_denied and the description “Identity provider did not supply an email
address.” It returns the error to the Application when it can, so what the user
sees depends on the Application. Add an email address to the user’s account
(step 7 of the first phase), then have the user sign in again.
Sign-in fails before the Entra ID sign-in page appears
The Issuer URL doesn’t match the issuer in Entra ID’s discovery document.
Keycard doesn’t check it when you save the Provider, so a mismatch shows up at
sign-in, sometimes as an Invalid URL error. Copy the issuer from
https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration
into Issuer URL on the Provider’s Configuration tab. The usual causes are
a trailing slash, a domain name in place of the tenant ID, and the common or
organizations endpoint.
A rule on Entra ID groups never matches
- The app registration has a groups claim under Token configuration, and its claim type isn’t changed to a role.
- The rule compares group object IDs, unless Entra ID sends names.
- The user is in 200 groups or fewer, counting nested groups, or the claim is limited to Groups assigned to the application.
- The user has signed in again since the claim or their membership changed. An agent that connected before the change keeps the earlier groups for up to 90 days, because its refresh token keeps using the groups from sign-in. Disabling the person stops it; revoking a grant doesn’t.
Sign-in stops working when the client secret expires
An expired secret breaks sign-in for every user of the Zone. An app registration can hold more than one secret, so add the new one first: create it under Certificates & secrets, then on the Provider’s Configuration tab select Update next to Client Secret, paste the new Value, and click Save changes. Then delete the old secret in Entra ID.
Sign-in fails with access_denied: federation subject conflict
Keycard found a User with this email address already linked to a different
Entra ID sub. It stops the sign-in with access_denied and the description
“We could not sign you in. This sign-in conflicts with an existing account.
Contact your administrator.” Because each app registration gets its own
sub, replacing the app registration can cause this for every returning user. If the original
registration still exists, point the Provider’s Client ID and Client Secret
back at it and rotate that registration’s secret.