Using System for Cross-Domain Identity Management to automatically provision users and groups from Azure Active Directory to applications

Overview

Azure Active Directory (Azure AD) can automatically provision users and groups to any application or identity store that is fronted by a web service with the interface defined in the System for Cross-Domain Identity Management (SCIM) 2.0 protocol specification. Azure Active Directory can send requests to create, modify, or delete assigned users and groups to the web service. The web service can then translate those requests into operations on the target identity store.

Important

Microsoft recommends that you manage Azure AD using the Azure AD admin center in the Azure portal instead of using the Azure classic portal referenced in this article.

Figure 1: Provisioning from Azure Active Directory to an identity store via a web service

This capability can be used in conjunction with the “bring your own app” capability in Azure AD to enable single sign-on and automatic user provisioning for applications that provide or are fronted by a SCIM web service.

There are two use cases for using SCIM in Azure Active Directory:

  • Provisioning users and groups to applications that support SCIM Applications that support SCIM 2.0 and use OAuth bearer tokens for authentication works with Azure AD without configuration.
  • Build your own provisioning solution for applications that support other API-based provisioning For non-SCIM applications, you can create a SCIM endpoint to translate between the Azure AD SCIM endpoint and any API the application supports for user provisioning. To help you develop a SCIM endpoint, we provide Common Language Infrastructure (CLI) libraries along with code samples that show you how to do provide a SCIM endpoint and translate SCIM messages.

Provisioning users and groups to applications that support SCIM

Azure AD can be configured to automatically provision assigned users and groups to applications that implement a System for Cross-domain Identity Management 2 (SCIM) web service and accept OAuth bearer tokens for authentication. Within the SCIM 2.0 specification, applications must meet these requirements:

  • Supports creating users and/or groups, as per section 3.3 of the SCIM protocol.
  • Supports modifying users and/or groups with patch requests as per section 3.5.2 of the SCIM protocol.
  • Supports retrieving a known resource as per section 3.4.1 of the SCIM protocol.
  • Supports querying users and/or groups, as per section 3.4.2 of the SCIM protocol. By default, users are queried by externalId and groups are queried by displayName.
  • Supports querying user by ID and by manager as per section 3.4.2 of the SCIM protocol.
  • Supports querying groups by ID and by member as per section 3.4.2 of the SCIM protocol.
  • Accepts OAuth bearer tokens for authorization as per section 2.1 of the SCIM protocol.

Check with your application provider, or your application provider's documentation for statements of compatibility with these requirements.

Getting started

Applications that support the SCIM profile described in this article can be connected to Azure Active Directory using the "non-gallery application" feature in the Azure AD application gallery. Once connected, Azure AD runs a synchronization process every 20 minutes where it queries the application's SCIM endpoint for assigned users and groups, and creates or modifies them according to the assignment details.

To connect an application that supports SCIM:

  1. Sign in to the Azure portal.
  2. Browse to Azure Active Directory > Enterprise Applications, and select **New application > All > Non-gallery application.
  3. Enter a name for your application, and click Add icon to create an app object.

    Figure 2: Azure AD application gallery

  4. In the resulting screen, select the Provisioning tab in the left column.

  5. In the Provisioning Mode menu, select Automatic.

    Figure 3: Configuring provisioning in the Azure portal

  6. In the Tenant URL field, enter the URL of the application's SCIM endpoint. Example: https://api.contoso.com/scim/v2/

  7. If the SCIM endpoint requires an OAuth bearer token from an issuer other than Azure AD, then copy the required OAuth bearer token into the optional Secret Token field. If this field is left blank, then Azure AD included an OAuth bearer token issued from Azure AD with each request. Apps that use Azure AD as an identity provider can validate this Azure AD -issued token.
  8. Click the Test Connection button to have Azure Active Directory attempt to connect to the SCIM endpoint. If the attempts fail, error information is displayed.
  9. If the attempts to connect to the application succeed, then click Save to save the admin credentials.
  10. In the Mappings section, there are two selectable sets of attribute mappings: one for user objects and one for group objects. Select each one to review the attributes that are synchronized from Azure Active Directory to your app. The attributes selected as Matching properties are used to match the users and groups in your app for update operations. Select the Save button to commit any changes.

    Note

    You can optionally disable syncing of group objects by disabling the "groups" mapping.

  11. Under Settings, the Scope field defines which users and or groups are synchronized. Selecting "Sync only assigned users and groups" (recommended) will only sync users and groups assigned in the Users and groups tab.

  12. Once your configuration is complete, change the Provisioning Status to On.
  13. Click Save to start the Azure AD provisioning service.
  14. If syncing only assigned users and groups (recommended), be sure to select the Users and groups tab and assign the users and/or groups you wish to sync.

Once the initial synchronization has started, you can use the Audit logs tab to monitor progress, which shows all actions performed by the provisioning service on your app. For more information on how to read the Azure AD provisioning logs, see Reporting on automatic user account provisioning.

Note

The initial sync takes longer to perform than subsequent syncs, which occur approximately every 20 minutes as long as the service is running.

Building your own provisioning solution for any application

By creating a SCIM web service that interfaces with Azure Active Directory, you can enable single sign-on and automatic user provisioning for virtually any application that provides a REST or SOAP user provisioning API.

Here’s how it works:

  1. Azure AD provides a common language infrastructure library named Microsoft.SystemForCrossDomainIdentityManagement. System integrators and developers can use this library to create and deploy a SCIM-based web service endpoint capable of connecting Azure AD to any application’s identity store.
  2. Mappings are implemented in the web service to map the standardized user schema to the user schema and protocol required by the application.
  3. The endpoint URL is registered in Azure AD as part of a custom application in the application gallery.
  4. Users and groups are assigned to this application in Azure AD. Upon assignment, they are put into a queue to be synchronized to the target application. The synchronization process handling the queue runs every 20 minutes.

Code Samples

To make this process easier, a set of code samples are provided that create a SCIM web service endpoint and demonstrate automatic provisioning. One sample is of a provider that maintains a file with rows of comma-separated values representing users and groups. The other is of a provider that operates on the Amazon Web Services Identity and Access Management service.

Prerequisites

Getting Started

The easiest way to implement a SCIM endpoint that can accept provisioning requests from Azure AD is to build and deploy the code sample that outputs the provisioned users to a comma-separated value (CSV) file.

To create a sample SCIM endpoint:

  1. Download the code sample package at https://github.com/Azure/AzureAD-BYOA-Provisioning-Samples/tree/master
  2. Unzip the package and place it on your Windows machine at a location such as C:\AzureAD-BYOA-Provisioning-Samples.
  3. In this folder, launch the FileProvisioningAgent solution in Visual Studio.
  4. Select Tools > Library Package Manager > Package Manager Console, and execute the following commands for the FileProvisioningAgent project to resolve the solution references: Install-Package Microsoft.SystemForCrossDomainIdentityManagement Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory Install-Package Microsoft.Owin.Diagnostics Install-Package Microsoft.Owin.Host.SystemWeb
  5. Build the FileProvisioningAgent project.
  6. Launch the Command Prompt application in Windows (as an Administrator), and use the cd command to change the directory to your \AzureAD-BYOA-Provisioning-Samples\ProvisioningAgent\bin\Debug folder.
  7. Run the following command, replacing with the IP address or domain name of the Windows machine: FileAgnt.exe http://<ip-address>:9000 TargetFile.csv
  8. In Windows under Windows Settings > Network & Internet Settings, select the Windows Firewall > Advanced Settings, and create an Inbound Rule that allows inbound access to port 9000.
  9. If the Windows machine is behind a router, the router needs to be configured to perform Network Access Translation between its port 9000 that is exposed to the internet, and port 9000 on the Windows machine. This is required for Azure AD to be able to access this endpoint in the cloud.

To register the sample SCIM endpoint in Azure AD:

  1. Sign in to the Azure portal.
  2. Browse to Azure Active Directory > Enterprise Applications, and select **New application > All > Non-gallery application.
  3. Enter a name for your application, and click Add icon to create an app object. The application object created is intended to represent the target app you would be provisioning to and implementing single sign-on for, and not just the SCIM endpoint.
  4. In the resulting screen, select the Provisioning tab in the left column.
  5. In the Provisioning Mode menu, select Automatic.

    Figure 4: Configuring provisioning in the Azure portal

  6. In the Tenant URL field, enter the internet-exposed URL and port of your SCIM endpoint. This would be something like http://testmachine.contoso.com:9000 or http://:9000/, where is the internet exposed IP address.

  7. If the SCIM endpoint requires an OAuth bearer token from an issuer other than Azure AD, then copy the required OAuth bearer token into the optional Secret Token field. If this field is left blank, then Azure AD will include an OAuth bearer token issued from Azure AD with each request. Apps that use Azure AD as an identity provider can validate this Azure AD -issued token.
  8. Click the Test Connection button to have Azure Active Directory attempt to connect to the SCIM endpoint. If the attempts fail, error information is displayed.
  9. If the attempts to connect to the application succeed, then click Save to save the admin credentials.
  10. In the Mappings section, there are two selectable sets of attribute mappings: one for user objects and one for group objects. Select each one to review the attributes that are synchronized from Azure Active Directory to your app. The attributes selected as Matching properties are used to match the users and groups in your app for update operations. Select the Save button to commit any changes.
  11. Under Settings, the Scope field defines which users and or groups are synchronized. Selecting "Sync only assigned users and groups" (recommended) will only sync users and groups assigned in the Users and groups tab.
  12. Once your configuration is complete, change the Provisioning Status to On.
  13. Click Save to start the Azure AD provisioning service.
  14. If syncing only assigned users and groups (recommended), be sure to select the Users and groups tab and assign the users and/or groups you wish to sync.

Once the initial synchronization has started, you can use the Audit logs tab to monitor progress, which shows all actions performed by the provisioning service on your app. For more information on how to read the Azure AD provisioning logs, see Reporting on automatic user account provisioning.

The final step in verifying the sample is to open the TargetFile.csv file in the \AzureAD-BYOA-Provisioning-Samples\ProvisioningAgent\bin\Debug folder on your Windows machine. Once the provisioning process is run, this file shows the details of all assigned and provisioned users and groups.

Development libraries

To develop your own web service that conforms to the SCIM specification, first familiarize yourself with the following libraries provided by Microsoft to help accelerate the development process:

  1. Common Language Infrastructure (CLI) libraries are offered for use with languages based on that infrastructure, such as C#. One of those libraries, Microsoft.SystemForCrossDomainIdentityManagement.Service, declares an interface, Microsoft.SystemForCrossDomainIdentityManagement.IProvider, shown in the following illustration: A developer using the libraries would implement that interface with a class that may be referred to, generically, as a provider. The libraries enable the developer to deploy a web service that conforms to the SCIM specification. The web service can be either hosted within Internet Information Services, or any executable Common Language Infrastructure assembly. Request is translated into calls to the provider’s methods, which would be programmed by the developer to operate on some identity store.

  2. Express route handlers are available for parsing node.js request objects representing calls (as defined by the SCIM specification), made to a node.js web service.

Building a Custom SCIM Endpoint

Using the CLI libraries, developers using those libraries can host their services within any executable Common Language Infrastructure assembly, or within Internet Information Services. Here is sample code for hosting a service within an executable assembly, at the address http://localhost:9000:

private static void Main(string[] arguments)
{
// Microsoft.SystemForCrossDomainIdentityManagement.IMonitor, 
// Microsoft.SystemForCrossDomainIdentityManagement.IProvider and 
// Microsoft.SystemForCrossDomainIdentityManagement.Service are all defined in 
// Microsoft.SystemForCrossDomainIdentityManagement.Service.dll.  

Microsoft.SystemForCrossDomainIdentityManagement.IMonitor monitor = 
  new DevelopersMonitor();
Microsoft.SystemForCrossDomainIdentityManagement.IProvider provider = 
  new DevelopersProvider(arguments[1]);
Microsoft.SystemForCrossDomainIdentityManagement.Service webService = null;
try
{
    webService = new WebService(monitor, provider);
    webService.Start("http://localhost:9000");

    Console.ReadKey(true);
}
finally
{
    if (webService != null)
    {
        webService.Dispose();
        webService = null;
    }
}
}

public class WebService : Microsoft.SystemForCrossDomainIdentityManagement.Service
{
private Microsoft.SystemForCrossDomainIdentityManagement.IMonitor monitor;
private Microsoft.SystemForCrossDomainIdentityManagement.IProvider provider;

public WebService(
  Microsoft.SystemForCrossDomainIdentityManagement.IMonitor monitoringBehavior, 
  Microsoft.SystemForCrossDomainIdentityManagement.IProvider providerBehavior)
{
    this.monitor = monitoringBehavior;
    this.provider = providerBehavior;
}

public override IMonitor MonitoringBehavior
{
    get
    {
        return this.monitor;
    }

    set
    {
        this.monitor = value;
    }
}

public override IProvider ProviderBehavior
{
    get
    {
        return this.provider;
    }

    set
    {
        this.provider = value;
    }
}
}

This service must have an HTTP address and server authentication certificate of which the root certification authority is one of the following:

  • CNNIC
  • Comodo
  • CyberTrust
  • DigiCert
  • GeoTrust
  • GlobalSign
  • Go Daddy
  • Verisign
  • WoSign

A server authentication certificate can be bound to a port on a Windows host using the network shell utility:

netsh http add sslcert ipport=0.0.0.0:443 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}  

Here, the value provided for the certhash argument is the thumbprint of the certificate, while the value provided for the appid argument is an arbitrary globally unique identifier.

To host the service within Internet Information Services, a developer would build a CLA code library assembly with a class named Startup in the default namespace of the assembly. Here is a sample of such a class:

public class Startup
{
// Microsoft.SystemForCrossDomainIdentityManagement.IWebApplicationStarter, 
// Microsoft.SystemForCrossDomainIdentityManagement.IMonitor and  
// Microsoft.SystemForCrossDomainIdentityManagement.Service are all defined in 
// Microsoft.SystemForCrossDomainIdentityManagement.Service.dll.  

Microsoft.SystemForCrossDomainIdentityManagement.IWebApplicationStarter starter;

public Startup()
{
    Microsoft.SystemForCrossDomainIdentityManagement.IMonitor monitor = 
      new DevelopersMonitor();
    Microsoft.SystemForCrossDomainIdentityManagement.IProvider provider = 
      new DevelopersProvider();
    this.starter = 
      new Microsoft.SystemForCrossDomainIdentityManagement.WebApplicationStarter(
        provider, 
        monitor);
}

public void Configuration(
  Owin.IAppBuilder builder) // Defined in in Owin.dll.  
{
    this.starter.ConfigureApplication(builder);
}
}

Handling endpoint authentication

Requests from Azure Active Directory include an OAuth 2.0 bearer token. Any service receiving the request should authenticate the issuer as being Azure Active Directory on behalf of the expected Azure Active Directory tenant, for access to the Azure Active Directory Graph web service. In the token, the issuer is identified by an iss claim, like, "iss":"https://sts.windows.net/cbb1a5ac-f33b-45fa-9bf5-f37db0fed422/". In this example, the base address of the claim value, https://sts.windows.net, identifies Azure Active Directory as the issuer, while the relative address segment, cbb1a5ac-f33b-45fa-9bf5-f37db0fed422, is a unique identifier of the Azure Active Directory tenant on behalf of which the token was issued. If the token was issued for accessing the Azure Active Directory Graph web service, then the identifier of that service, 00000002-0000-0000-c000-000000000000, should be in the value of the token’s aud claim.

Developers using the CLA libraries provided by Microsoft for building a SCIM service can authenticate requests from Azure Active Directory using the Microsoft.Owin.Security.ActiveDirectory package by following these steps:

  1. In a provider, implement the Microsoft.SystemForCrossDomainIdentityManagement.IProvider.StartupBehavior property by having it return a method to be called whenever the service is started:

     public override Action\<Owin.IAppBuilder, System.Web.Http.HttpConfiguration.HttpConfiguration\> StartupBehavior
     {
       get
       {
         return this.OnServiceStartup;
       }
     }
    
     private void OnServiceStartup(
       Owin.IAppBuilder applicationBuilder,  // Defined in Owin.dll.  
       System.Web.Http.HttpConfiguration configuration)  // Defined in System.Web.Http.dll.  
     {
     }
    
  2. Add the following code to that method to have any request to any of the service’s endpoints authenticated as bearing a token issued by Azure Active Directory on behalf of a specified tenant, for access to the Azure AD Graph web service:

     private void OnServiceStartup(
       Owin.IAppBuilder applicationBuilder IAppBuilder applicationBuilder, 
       System.Web.Http.HttpConfiguration HttpConfiguration configuration)
     {
       // IFilter is defined in System.Web.Http.dll.  
       System.Web.Http.Filters.IFilter authorizationFilter = 
         new System.Web.Http.AuthorizeAttribute(); // Defined in System.Web.Http.dll.configuration.Filters.Add(authorizationFilter);
    
       // SystemIdentityModel.Tokens.TokenValidationParameters is defined in    
       // System.IdentityModel.Token.Jwt.dll.
       SystemIdentityModel.Tokens.TokenValidationParameters tokenValidationParameters =     
         new TokenValidationParameters()
         {
           ValidAudience = "00000002-0000-0000-c000-000000000000"
         };
    
       // WindowsAzureActiveDirectoryBearerAuthenticationOptions is defined in 
       // Microsoft.Owin.Security.ActiveDirectory.dll
       Microsoft.Owin.Security.ActiveDirectory.
       WindowsAzureActiveDirectoryBearerAuthenticationOptions authenticationOptions =
         new WindowsAzureActiveDirectoryBearerAuthenticationOptions()    {
         TokenValidationParameters = tokenValidationParameters,
         Tenant = "03F9FCBC-EA7B-46C2-8466-F81917F3C15E" // Substitute the appropriate tenant’s 
                                                       // identifier for this one.  
       };
    
       applicationBuilder.UseWindowsAzureActiveDirectoryBearerAuthentication(authenticationOptions);
     }
    

User and group schema

Azure Active Directory can provision two types of resources to SCIM web services. Those types of resources are users and groups.

User resources are identified by the schema identifier, urn:ietf:params:scim:schemas:extension:enterprise:2.0:User, which is included in this protocol specification: http://tools.ietf.org/html/draft-ietf-scim-core-schema. The default mapping of the attributes of users in Azure Active Directory to the attributes of urn:ietf:params:scim:schemas:extension:enterprise:2.0:User resources is provided in table 1, below.

Group resources are identified by the schema identifier, http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/Group. Table 2, below, shows the default mapping of the attributes of groups in Azure Active Directory to the attributes of http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/Group resources.

Table 1: Default user attribute mapping

Azure Active Directory user urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
IsSoftDeleted active
displayName displayName
Facsimile-TelephoneNumber phoneNumbers[type eq "fax"].value
givenName name.givenName
jobTitle title
mail emails[type eq "work"].value
mailNickname externalId
manager manager
mobile phoneNumbers[type eq "mobile"].value
objectId id
postalCode addresses[type eq "work"].postalCode
proxy-Addresses emails[type eq "other"].Value
physical-Delivery-OfficeName addresses[type eq "other"].Formatted
streetAddress addresses[type eq "work"].streetAddress
surname name.familyName
telephone-Number phoneNumbers[type eq "work"].value
user-PrincipalName userName

Table 2: Default group attribute mapping

Azure Active Directory group http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/Group
displayName externalId
mail emails[type eq "work"].value
mailNickname displayName
members members
objectId id
proxyAddresses emails[type eq "other"].Value

User provisioning and de-provisioning

The following illustration shows the messages that Azure Active Directory sends to a SCIM service to manage the lifecycle of a user in another identity store. The diagram also shows how a SCIM service implemented using the CLI libraries provided by Microsoft for building such services translate those requests into calls to the methods of a provider.

Figure 5: User provisioning and de-provisioning sequence

  1. Azure Active Directory queries the service for a user with an externalId attribute value matching the mailNickname attribute value of a user in Azure AD. The query is expressed as a Hypertext Transfer Protocol (HTTP) request such as this example, wherein jyoung is a sample of a mailNickname of a user in Azure Active Directory:

     GET https://.../scim/Users?filter=externalId eq jyoung HTTP/1.1
     Authorization: Bearer ...
    

    If the service was built using the Common Language Infrastructure libraries provided by Microsoft for implementing SCIM services, then the request is translated into a call to the Query method of the service’s provider. Here is the signature of that method:

     // System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
     // Microsoft.SystemForCrossDomainIdentityManagement.Resource is defined in 
     // Microsoft.SystemForCrossDomainIdentityManagement.Schemas.  
     // Microsoft.SystemForCrossDomainIdentityManagement.IQueryParameters is defined in 
     // Microsoft.SystemForCrossDomainIdentityManagement.Protocol.  
    
     System.Threading.Tasks.Task<Microsoft.SystemForCrossDomainIdentityManagement.Resource[]> Query(
       Microsoft.SystemForCrossDomainIdentityManagement.IQueryParameters parameters, 
       string correlationIdentifier);
    

    Here is the definition of the Microsoft.SystemForCrossDomainIdentityManagement.IQueryParameters interface:

     public interface IQueryParameters: 
       Microsoft.SystemForCrossDomainIdentityManagement.IRetrievalParameters
     {
         System.Collections.Generic.IReadOnlyCollection <Microsoft.SystemForCrossDomainIdentityManagement.IFilter> AlternateFilters 
         { get; }
     }
    
     public interface Microsoft.SystemForCrossDomainIdentityManagement.IRetrievalParameters
     {
       system.Collections.Generic.IReadOnlyCollection<string> ExcludedAttributePaths 
       { get; }
       System.Collections.Generic.IReadOnlyCollection<string> RequestedAttributePaths 
       { get; }
       string SchemaIdentifier 
       { get; }
     }
    
     public interface Microsoft.SystemForCrossDomainIdentityManagement.IFilter
     {
         Microsoft.SystemForCrossDomainIdentityManagement.IFilter AdditionalFilter 
           { get; set; }
         string AttributePath 
           { get; } 
         Microsoft.SystemForCrossDomainIdentityManagement.ComparisonOperator FilterOperator 
           { get; }
         string ComparisonValue 
           { get; }
     }
    
     public enum Microsoft.SystemForCrossDomainIdentityManagement.ComparisonOperator
     {
         Equals
     }
    

    In the following sample of a query for a user with a given value for the externalId attribute, values of the arguments passed to the Query method are:

    • parameters.AlternateFilters.Count: 1
    • parameters.AlternateFilters.ElementAt(0).AttributePath: "externalId"
    • parameters.AlternateFilters.ElementAt(0).ComparisonOperator: ComparisonOperator.Equals
    • parameters.AlternateFilter.ElementAt(0).ComparisonValue: "jyoung"
    • correlationIdentifier: System.Net.Http.HttpRequestMessage.GetOwinEnvironment["owin.RequestId"]
  2. If the response to a query to the web service for a user with an externalId attribute value that matches the mailNickname attribute value of a user does not return any users, then Azure Active Directory requests that the service provision a user corresponding to the one in Azure Active Directory. Here is an example of such a request:

     POST https://.../scim/Users HTTP/1.1
     Authorization: Bearer ...
     Content-type: application/json
     {
       "schemas":
       [
         "urn:ietf:params:scim:schemas:core:2.0:User",
         "urn:ietf:params:scim:schemas:extension:enterprise:2.0User"],
       "externalId":"jyoung",
       "userName":"jyoung",
       "active":true,
       "addresses":null,
       "displayName":"Joy Young",
       "emails": [
         {
           "type":"work",
           "value":"jyoung@Contoso.com",
           "primary":true}],
       "meta": {
         "resourceType":"User"},
        "name":{
         "familyName":"Young",
         "givenName":"Joy"},
       "phoneNumbers":null,
       "preferredLanguage":null,
       "title":null,
       "department":null,
       "manager":null}
    

    The Common Language Infrastructure libraries provided by Microsoft for implementing SCIM services would translate that request into a call to the Create method of the service’s provider. The Create method has this signature:

     // System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
     // Microsoft.SystemForCrossDomainIdentityManagement.Resource is defined in 
     // Microsoft.SystemForCrossDomainIdentityManagement.Schemas.  
    
     System.Threading.Tasks.Task<Microsoft.SystemForCrossDomainIdentityManagement.Resource> Create(
       Microsoft.SystemForCrossDomainIdentityManagement.Resource resource, 
       string correlationIdentifier);
    

    In a request to provision a user, the value of the resource argument is an instance of the Microsoft.SystemForCrossDomainIdentityManagement. Core2EnterpriseUser class, defined in the Microsoft.SystemForCrossDomainIdentityManagement.Schemas library. If the request to provision the user succeeds, then the implementation of the method is expected to return an instance of the Microsoft.SystemForCrossDomainIdentityManagement. Core2EnterpriseUser class, with the value of the Identifier property set to the unique identifier of the newly provisioned user.

  3. To update a user known to exist in an identity store fronted by an SCIM, Azure Active Directory proceeds by requesting the current state of that user from the service with a request such as:

     GET ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
     Authorization: Bearer ...
    

    In a service built using the Common Language Infrastructure libraries provided by Microsoft for implementing SCIM services, the request is translated into a call to the Retrieve method of the service’s provider. Here is the signature of the Retrieve method:

     // System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
     // Microsoft.SystemForCrossDomainIdentityManagement.Resource and 
     // Microsoft.SystemForCrossDomainIdentityManagement.IResourceRetrievalParameters 
     // are defined in Microsoft.SystemForCrossDomainIdentityManagement.Schemas.  
     System.Threading.Tasks.Task<Microsoft.SystemForCrossDomainIdentityManagement.Resource> 
        Retrieve(
          Microsoft.SystemForCrossDomainIdentityManagement.IResourceRetrievalParameters 
            parameters, 
            string correlationIdentifier);
    
     public interface 
       Microsoft.SystemForCrossDomainIdentityManagement.IResourceRetrievalParameters:   
         IRetrievalParameters
         {
           Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier 
             ResourceIdentifier 
               { get; }
     }
     public interface Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier
     {
         string Identifier 
           { get; set; }
         string Microsoft.SystemForCrossDomainIdentityManagement.SchemaIdentifier 
           { get; set; }
     }
    

    In the example of a request to retrieve the current state of a user, the values of the properties of the object provided as the value of the parameters argument are as follows:

    • Identifier: "54D382A4-2050-4C03-94D1-E769F1D15682"
    • SchemaIdentifier: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
  4. If a reference attribute is to be updated, then Azure Active Directory queries the service to determine whether or not the current value of the reference attribute in the identity store fronted by the service already matches the value of that attribute in Azure Active Directory. For users, the only attribute of which the current value is queried in this way is the manager attribute. Here is an example of a request to determine whether the manager attribute of a particular user object currently has a certain value:

     GET ~/scim/Users?filter=id eq 54D382A4-2050-4C03-94D1-E769F1D15682 and manager eq 2819c223-7f76-453a-919d-413861904646&attributes=id HTTP/1.1
     Authorization: Bearer ...
    

    The value of the attributes query parameter, id, signifies that if a user object exists that satisfies the expression provided as the value of the filter query parameter, then the service is expected to respond with a urn:ietf:params:scim:schemas:core:2.0:User or urn:ietf:params:scim:schemas:extension:enterprise:2.0:User resource, including only the value of that resource’s id attribute. The value of the id attribute is known to the requestor. It is included in the value of the filter query parameter; the purpose of asking for it is actually to request a minimal representation of a resource that satisfying the filter expression as an indication of whether or not any such object exists.

    If the service was built using the Common Language Infrastructure libraries provided by Microsoft for implementing SCIM services, then the request is translated into a call to the Query method of the service’s provider. The value of the properties of the object provided as the value of the parameters argument are as follows:

    • parameters.AlternateFilters.Count: 2
    • parameters.AlternateFilters.ElementAt(x).AttributePath: "id"
    • parameters.AlternateFilters.ElementAt(x).ComparisonOperator: ComparisonOperator.Equals
    • parameters.AlternateFilter.ElementAt(x).ComparisonValue: "54D382A4-2050-4C03-94D1-E769F1D15682"
    • parameters.AlternateFilters.ElementAt(y).AttributePath: "manager"
    • parameters.AlternateFilters.ElementAt(y).ComparisonOperator: ComparisonOperator.Equals
    • parameters.AlternateFilter.ElementAt(y).ComparisonValue: "2819c223-7f76-453a-919d-413861904646"
    • parameters.RequestedAttributePaths.ElementAt(0): "id"
    • parameters.SchemaIdentifier: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"

    Here, the value of the index x may be 0 and the value of the index y may be 1, or the value of x may be 1 and the value of y may be 0, depending on the order of the expressions of the filter query parameter.

  5. Here is an example of a request from Azure Active Directory to an SCIM service to update a user:

     PATCH ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
     Authorization: Bearer ...
     Content-type: application/json
     {
       "schemas": 
       [
         "urn:ietf:params:scim:api:messages:2.0:PatchOp"],
       "Operations":
       [
         {
           "op":"Add",
           "path":"manager",
           "value":
             [
               {
                 "$ref":"http://.../scim/Users/2819c223-7f76-453a-919d-413861904646",
                 "value":"2819c223-7f76-453a-919d-413861904646"}]}]}
    

    The Microsoft Common Language Infrastructure libraries for implementing SCIM services would translate the request into a call to the Update method of the service’s provider. Here is the signature of the Update method:

     // System.Threading.Tasks.Tasks and 
     // System.Collections.Generic.IReadOnlyCollection<T>
     // are defined in mscorlib.dll.  
     // Microsoft.SystemForCrossDomainIdentityManagement.IPatch, 
     // Microsoft.SystemForCrossDomainIdentityManagement.PatchRequestBase, 
     // Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier, 
     // Microsoft.SystemForCrossDomainIdentityManagement.PatchOperation, 
     // Microsoft.SystemForCrossDomainIdentityManagement.OperationName, 
     // Microsoft.SystemForCrossDomainIdentityManagement.IPath and 
     // Microsoft.SystemForCrossDomainIdentityManagement.OperationValue 
     // are all defined in Microsoft.SystemForCrossDomainIdentityManagement.Protocol. 
    
     System.Threading.Tasks.Task Update(
       Microsoft.SystemForCrossDomainIdentityManagement.IPatch patch, 
       string correlationIdentifier);
    
     public interface Microsoft.SystemForCrossDomainIdentityManagement.IPatch
     {
     Microsoft.SystemForCrossDomainIdentityManagement.PatchRequestBase 
       PatchRequest 
         { get; set; }
     Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier 
       ResourceIdentifier 
         { get; set; }        
     }
    
     public class PatchRequest2: 
       Microsoft.SystemForCrossDomainIdentityManagement.PatchRequestBase
     {
     public System.Collections.Generic.IReadOnlyCollection
       <Microsoft.SystemForCrossDomainIdentityManagement.PatchOperation> 
         Operations
         { get;}
    
     public void AddOperation(
       Microsoft.SystemForCrossDomainIdentityManagement.PatchOperation operation);
     }
    
     public class PatchOperation
     {
     public Microsoft.SystemForCrossDomainIdentityManagement.OperationName 
       Name
       { get; set; }
    
     public Microsoft.SystemForCrossDomainIdentityManagement.IPath 
       Path
       { get; set; }
    
     public System.Collections.Generic.IReadOnlyCollection
       <Microsoft.SystemForCrossDomainIdentityManagement.OperationValue> Value
       { get; }
    
     public void AddValue(
       Microsoft.SystemForCrossDomainIdentityManagement.OperationValue value);
     }
    
     public enum OperationName
     {
       Add,
       Remove,
       Replace
     }
    
     public interface IPath
     {
       string AttributePath { get; }
       System.Collections.Generic.IReadOnlyCollection<IFilter> SubAttributes { get; }
       Microsoft.SystemForCrossDomainIdentityManagement.IPath ValuePath { get; }
     }
    
     public class OperationValue
     {
       public string Reference
       { get; set; }
    
       public string Value
       { get; set; }
     }
    

    In the example of a request to update a user, the object provided as the value of the patch argument has these property values:

    • ResourceIdentifier.Identifier: "54D382A4-2050-4C03-94D1-E769F1D15682"
    • ResourceIdentifier.SchemaIdentifier: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
    • (PatchRequest as PatchRequest2).Operations.Count: 1
    • (PatchRequest as PatchRequest2).Operations.ElementAt(0).OperationName: OperationName.Add
    • (PatchRequest as PatchRequest2).Operations.ElementAt(0).Path.AttributePath: "manager"
    • (PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.Count: 1
    • (PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.ElementAt(0).Reference: http://.../scim/Users/2819c223-7f76-453a-919d-413861904646
    • (PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.ElementAt(0).Value: 2819c223-7f76-453a-919d-413861904646
  6. To de-provision a user from an identity store fronted by an SCIM service, Azure AD sends a request such as:

     DELETE ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
     Authorization: Bearer ...
    

    If the service was built using the Common Language Infrastructure libraries provided by Microsoft for implementing SCIM services, then the request is translated into a call to the Delete method of the service’s provider. That method has this signature:

     // System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
     // Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier, 
     // is defined in Microsoft.SystemForCrossDomainIdentityManagement.Protocol. 
     System.Threading.Tasks.Task Delete(
       Microsoft.SystemForCrossDomainIdentityManagement.IResourceIdentifier  
         resourceIdentifier, 
       string correlationIdentifier);
    

    The object provided as the value of the resourceIdentifier argument has these property values in the example of a request to de-provision a user:

    • ResourceIdentifier.Identifier: "54D382A4-2050-4C03-94D1-E769F1D15682"
    • ResourceIdentifier.SchemaIdentifier: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"

Group provisioning and de-provisioning

The following illustration shows the messages that Azure AcD sends to a SCIM service to manage the lifecycle of a group in another identity store. Those messages differ from the messages pertaining to users in three ways:

  • The schema of a group resource is identified as http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/Group.
  • Requests to retrieve groups stipulate that the members attribute is to be excluded from any resource provided in response to the request.
  • Requests to determine whether a reference attribute has a certain value are requests about the members attribute.

Figure 6: Group provisioning and de-provisioning sequence