Everything is configured through Entra ID security groups — no MDM, no configuration profiles, no per-user setup required.
Enterprise Contacts is a multi-tenant iOS app registered in Azure. When a user logs in with their Microsoft work account, the app reads a special configuration group in your Entra ID tenant to discover the group prefix you have defined. It then looks for all security groups with that prefix and presents them as contact databases.
Setup is three steps:
Grant admin consent so users in your organisation can log in with their work account.
One security group that tells the app which prefix to use when looking for contact databases.
One security group per contact database you want to make available. Members of a group can access that database.
Enterprise Contacts is a multi-tenant app registration. You need to add it to your tenant as an Enterprise Application and grant admin consent once.
Go to Entra ID → Enterprise Applications → New application.
Search for "Enterprise Contacts" in the App Gallery, or add it manually using its Application (client) ID:
Go to Enterprise Applications → Enterprise Contacts → Permissions → Grant admin consent for [your tenant]. This allows users to sign in without individual consent prompts.
By default all users in your tenant can log in. If you want to restrict access, enable User assignment required under Properties and add only the relevant users or groups.
| Permission | Why it is needed | Admin consent |
|---|---|---|
User.Read |
Reads the signed-in user's own profile (/me) — display name, job title, department, and profile photo — shown on the My Profile screen. Also used to resolve the user's ID for membership checks. |
No |
Contacts.Read |
Reads contacts from the signed-in user's own Exchange contact folders (/me/contactFolders/…). Required for database type 2 (My Contacts). |
No |
Contacts.Read.Shared |
Reads contacts from another user's shared Exchange contact folder (/users/{id}/contactFolders/…). Required for database type 0 (Exchange mailbox), for example a shared reception mailbox. |
No |
Group.Read.All |
Lists and reads Entra ID security groups to discover the configuration group (App_EnterpriseContacts_Config) and all contact database groups matching your chosen prefix. Without this the app cannot find any databases. |
Yes |
GroupMember.Read.All |
Reads the transitive members of each database group to fetch contact details and verify that the signed-in user is authorised to access a given database. Without this no contacts can be synced. | Yes |
Create a single security group named exactly App_EnterpriseContacts_Config. The app looks for this group in your tenant to read your chosen group prefix.
App_EnterpriseContacts_Config — case-sensitive.
Set the group Description to the following JSON, replacing Your_Prefix_Here_ with your chosen prefix:
Example — if your organisation is Contoso and you want to use the prefix EC_Contoso_:
Each contact database visible in the app is backed by one Entra ID security group. The group name must start with your chosen prefix. The group description defines how the database behaves.
The description must be a JSON object. The app also accepts the older pipe-delimited format for groups created before this change — both formats work side by side.
| Field | Type | Values | Description |
|---|---|---|---|
name |
string | Any string | Display name shown in the app. Required. |
description |
string | Any string | Short subtitle shown when adding the database manually. Can be empty. |
autoLoad |
boolean | true or false |
true = added automatically for all members on first launch. false = only available via the + button. |
deleteable |
boolean | true or false |
true = user can remove the database. false = delete button is disabled. |
type |
integer | 0, 1, or 2 |
0 = Exchange mailbox, 1 = Entra ID group, 2 = My Contacts folder. Required. |
primaryId |
string | See reference below | Main identifier. UPN for mailbox/myContacts. Object ID (GUID) for Entra ID group. Required. |
secondaryId |
string | Folder ID | Required for type 0 (mailbox) only. The Exchange folder ID of the contacts folder to sync. Omit for other types. |
Add-MailboxFolderPermission).
EC_Contoso_CompanyContacts). Add members here to control who can see this database in the app. This group carries the configuration in its description field.primaryId.These are two different groups. A user in the access group sees the database. The contacts they see are the members of the contact group. A user can be in one, both, or neither — they are completely independent.
Group 1 — Access group (you create this)
Create this group with your prefix. Add the users or teams who should see this database as members. Put the config JSON in the description.
Group 2 — Contact group (existing or new)
This can be any Entra ID group whose members you want to appear as contacts — an existing distribution list, security group, or a brand new group you create specifically for this purpose. You do not configure it in any special way; just copy its Object ID into primaryId in the access group's description.
| Type | primaryId | secondaryId |
|---|---|---|
0 — Mailbox |
User UPN, e.g. john@contoso.com |
Exchange folder ID (required) |
1 — Entra ID group |
Object ID (GUID) of the contact source group — the group whose members become contacts. This is not the access group (the prefixed group) — it is a separate existing group. | Not used — omit |
2 — My Contacts |
User UPN, e.g. jane@contoso.com |
Not used — omit |
GET /users/{upn}/contactFolders to list all contact folders and their IDs for a given mailbox.
Groups created before the JSON format was introduced continue to work without any changes. The app automatically detects the format and parses accordingly. There is no need to migrate existing groups.
Enterprise Contacts is a public OAuth client — there is no client secret embedded in the app, by design. The trade-off is that the client ID is technically discoverable. The steps below close off the most practical abuse vectors and are recommended for all production deployments.
In Entra ID → App registrations → Enterprise Contacts → Authentication, confirm that the only platform configured is Mobile and desktop applications and the only redirect URI is:
Remove any Web platform entries. Without a web redirect URI the authorisation flow can only complete by handing the auth code to a custom URL scheme that iOS routes exclusively to the Enterprise Contacts app. A script or browser tab initiating the same flow has no way to receive the code.
In Entra ID → Enterprise Applications → Enterprise Contacts → Properties, set User assignment required to Yes. Then go to Users and groups and add only the users or groups who should have access to the app.
Anyone outside those assignments cannot complete authentication — even if they attempt to use the client ID directly.
If your organisation has Microsoft Intune or Microsoft 365 E3/E5 licensing, create a Conditional Access policy targeting the Enterprise Contacts application that requires an App Protection Policy. This is the strongest available control — it rejects any token acquired outside of an Intune-managed app, regardless of client ID.
If your tenant does not have Intune licensing, steps 1 and 2 together provide a solid baseline and match the security posture of most commercial enterprise mobile apps.