Skip to main content

Microsoft

This section will guide you through the configuration of the Microsoft authentication and organization providers.

These providers will use:

  1. An App Registration in Microsoft Entra ID to authenticate users.
  2. Permissions on the Microsoft Graph API for the above App Registration to fetch the users and groups information.

Setting up the App Registration

First of all, we need an App Registration to be created in the Azure Portal. Depending on how locked down your company is, you may need a directory administrator to do some or all of these instructions.

Go to Azure Portal > App registrations and find your existing App Registration, or create a new one.

On your App Registration's overview page, add a new Web platform configuration, with the configuration:

  • Redirect URI: https://your-witboost.com/api/auth/microsoft/handler/frame. The hostname, your-witboost.com should be changed to match the one of your Witboost instance; the rest of the URL stays the same.
  • Front-channel logout Url: blank
  • Implicit grant and hybrid flows: all unchecked

On the API Permissions tab, click on Add Permission, then add the following Application (not Delegated) permissions (they will be needed for for Microsoft Graph):

  • GroupMember.Read.All
  • User.Read.All

These permissions need to be granted directly to the application and not delegated because they are used for retrieval of users and groups; this happens in the background on a schedule, with no user interaction and as such cannot be of the delegated kind.

Then, in the API Permissions tab, click on Add Permission, then add the following Delegated permission for the Microsoft Graph API.

  • email
  • offline_access
  • openid
  • profile
  • User.Read

These are used when logging in a user to fetch the details needed to verify he is indeed allowed to login; as such, given that a user is involved, they are of the delegated kind.

Your company may require you to grant admin consent for these permissions. Even if your company doesn't require admin consent, you may wish to do so as it means users don't need to individually consent the first time they access Witboost. To grant admin consent, a directory admin will need to come to this page and click on the "Grant admin consent for YourCompany" button.

Authentication Provider

To configure the Microsoft authentication provider, you need to provide the following configuration:

auth:
providers:
microsoft:
default:
clientId: <clientId>
clientSecret: <clientSecret>
tenantId: <tenantId>
signIn:
resolvers:
- resolver: emailMatchingUserEntityAnnotation

where the clientId, clientSecret, and tenantId are the App Registration ones.

note

You can have multiple Microsoft authentication providers setup, each with a different providerId, to support e.g. multiple separate tenants. You can do this by adding multiple configuration blocks under the microsoft key. In this case, just one, with default as the providerId has been specified.

Organization Provider

The Microsoft Graph API will be used to fetch the users and groups information.

By default the provider requires the following Application permissions (not Delegated) for Microsoft Graph (we already defined them in the section above):

  • GroupMember.Read.All
  • User.Read.All

To configure the Microsoft organization provider, you need to provide the following configuration:

catalog:
providers:
microsoftGraphOrg:
default:
target: https://graph.microsoft.com/v1.0
authority: https://login.microsoftonline.com
# If you don't know you tenantId, you can use Microsoft Graph Explorer
# to query it
tenantId: <tenantId>
# Client Id and Secret can be created under Certificates & secrets in
# the App registration in the Microsoft Azure Portal.
clientId: <clientId>
clientSecret: <clientSecret>
userGroupMember:
filter: "displayName eq 'witboost'"
group:
filter: "displayName eq 'witboost'"
schedule:
frequency: { hours: 5 }
timeout: { minutes: 30 }

where the clientId, clientSecret, and tenantId are the App Registration ones.

In the example above, the userGroupMember and group filters are used to fetch the users and groups, belonging only to groups with certain properties (here you can use ).

The schedule configuration is used to define the frequency and timeout of the fetching process. The frequency represents the time between two fetches, while the timeout represents the maximum time the fetching process can take.

note

You can have multiple Microsoft organization providers setup, each with a different providerId, to support e.g. multiple separate tenants. You can do this by adding multiple configuration blocks under the microsoftGraphOrg key. In this case, just one, with default as the providerId has been specified.

Filtering

With the above configuration, the plugin will import all users in the "witboost" group as well as that group from your directory. This can be customized through filters and search queries. Keep in mind that if you omit filters and search queries for the user or group properties, the plugin will automatically import all available users or groups, which is unlikely to be a correct setup.

The recommended approach is to use groups with a common prefix for all the needed users (eg, WITBOOST_ADMINS, WITBOOST_GOVERNANCE, WITBOOST_USERS, WITBOOST_DP_OWNERS, WITBOOST_DP_DEVELOPERS_<DOMAIN>) and use a filter with the startsWith operator (eg, startsWith(displayName, 'WITBOOST_')). The full filter syntax reference is available here.

note

Filter clauses have a maximum complexity limit (around 15 operators). Try to keep operators to a minimum (see above suggestion on prefixes). If all else fails, you can have multiple providerIds each with its own filter fetching a subset of the total set of groups needed.

The search configuration key can be used along with filterto narrow down after the results, but is typically not needed. The full reference is available here.

Mappings

The default configuration above maps the objects from the Microsoft Graph API into Witboost users/groups by using common attributes as follows:

Microsoft Graph User FieldWitboost UserEntity FieldRequired
user.idmetadata.annotations['graph.microsoft.com/user-id']✅ Yes
user.mailmetadata.name (normalized)✅ Yes
user.mailmetadata.annotations['microsoft.com/email']✅ Yes
user.mailspec.profile.email✅ Yes
user.displayNamespec.profile.displayName✅ Yes

Entities that do not provide all the required fields are skipped, and will not be imported into Witboost. You can check the logs of the backend to see the detailed reason why a specific entity was skipped.

There are however some scenarios in which this approach may not be flexible enough. For example, service principals may not have a valid email address, or you may want to source the display name from different attributes, or you want to add additional fields to the Witboost entity. In these scenarios you can configure Witboost to use fields-based mapping for the entities. With this example configuration:

catalog:
providers:
microsoftGraphOrg:
default:
target: https://graph.microsoft.com/v1.0
authority: https://login.microsoftonline.com
# If you don't know you tenantId, you can use Microsoft Graph Explorer
# to query it
tenantId: <tenantId>
# Client Id and Secret can be created under Certificates & secrets in
# the App registration in the Microsoft Azure Portal.
clientId: <clientId>
clientSecret: <clientSecret>
userGroupMember:
filter: "displayName eq 'witboost'"
group:
filter: "displayName eq 'witboost'"
schedule:
frequency: { hours: 5 }
timeout: { minutes: 30 }
entityTransformer: mapping # This sets the mapping system to use; "default" switched to the standard behaviour described above. The "default" is the fallback also if this is set to null or undefined.
userFieldMappings:
spec.profile.displayName:
- 'preferredName'
- 'displayName'
spec.profile.email:
- 'mail'
- 'userPrincipalName'
groupFieldMappings:
metadata.description:
- 'description'
spec.profile.displayName:
- 'displayName'
- 'mailNickname'
spec.profile.email:
- 'mail'
orgFieldMappings:
spec.profile.displayName:
- 'displayName'

Witboost will use the provided mappings to populate the entities using the following logic:

  • User entities are managed by userFieldMappings, groups by groupFieldMappings, organizations by orgFieldMappings
  • For each of these, you specify the target Witboost entity field (eg, spec.profile.displayName) and provide a list of fields in the Microsoft Graph entity (eg, preferredName and displayName)
  • Witboost will populate the Witboost entity field with the value of the first non-null field
  • If none of the fields provide a valid value, the field is left as null, or the entity is skipped if the field is required (see below)

The identifiers of the entities are always normalized according to the algorithm described here. For users, the entity id is the normalized version of the spec.profile.email. We use the email as the main identifier because this is what a lot of other systems do, and since we want to be able to correctly map the user to the corresponding identity in all other systems it is the best option for that. The User Principal Name or UPN which would be the most standards-adherent way is sometimes ignored or misinterpreted by external systems. For groups, the entity id is the normalized version of the spec.profile.displayName.

The required Witboost entity fields for the various types are:

  • spec.profile.displayName
  • spec.profile.email

These fields must be specified by the field mapping configuration, as they are needed to create the entity.

Additionally, some Witboost entity fields cannot be configured this way, as they are managed exclusively by Witboost; they are:

  • apiVersion
  • kind
  • metadata.name
  • metadata.annotations.backstage.io/managed-by-location
  • metadata.annotations.backstage.io/managed-by-origin-location
  • metadata.annotations.microsoft.com/email
  • metadata.annotations.graph.microsoft.com/user-id
  • spec.memberOf

These fields cannot be specified by the field mapping configuration, as they are critical to the inner workings of Witboost.