简体   繁体   中英

Azure Ad fails to update users using Patch on microsoft.systemForCrossDomainIdentityManagement nuget package

We have created a SCIM integration using microsoft.systemForCrossDomainIdentityManagement nuget package which has been described in here:

https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/use-scim-to-provision-users-and-groups

We have tested the APIs using Postman and they work as they should but when we test them with Azure AD the patch requests fail.

Looking at the logs and narrowing them down we figured that the request is not in the same format as what microsoft.systemForCrossDomainIdentityManagement expects.

One patch request from AD is like below (which will fail):

{ "schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ {"op":"Replace","path":"displayName","value":" User X"} ]}

While the request that works is like this:

{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"] ,

"Operations":[ {"op":"Replace","path":"displayName","value":

[ {"$ref":null,"value":"User x"}]}]

}}

  • Please note the difference between 2 requests which in the 1st call is a string and in the second one is a list of objects.

How should we fix this?

The Nuget package take the request and deliver the IPatchRequest so the request doesn't even receive to our part of the code and both parts are Microsoft :|

Since there was no answer from Microsoft after more than a month, they only other way that I know to fix this is to intercept the call before it gets to Microsoft's part of the code (using a middle ware) and change it to the format that they are expecting :\\

I have discussed the problem and the solution further in the link below, but I am still waiting for a fix from Microsoft :\\ http://pilpag.blogspot.com/2019/02/enabling-scim-using-microsoftsystemforc.html

The easy fix is like this:

public class PatchRequestUpdaterMiddleware : OwinMiddleware

{

     private const string OperationValueFinderRegex = "({[\\s\\w\":,.\\[\\]\\\\]*op[\\s\\w\":,.\\[\\]\\\\]*\"value\"\\s*:\\s*)(\"[\\w\\s\\-,.@?!*;\'\\(\\)]+\")"; //{"op":"x","value":"Andrew1"}

public override async Task Invoke(IOwinContext context)

    {

        if (context.Request.Method.ToLower() != "patch")

        {

            await Next.Invoke(context);

            return;

        }

        var streamReader = new StreamReader(context.Request.Body);

        string body = streamReader.ReadToEnd();

        body = Regex.Replace(body, OperationValueFinderRegex, m => $"{m.Groups[1].Value}[{{\"value\":{m.Groups[2].Value}}}]"); //{"op":"x","value":"Ashkan"} ==>> {"op":"x","value":[{"value":"Ashkan"}]}

        context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));

        await Next.Invoke(context);

    }

 }

And just add this to the provider that you have created:

class myProvider:ProviderBase

{

....

   private void OnServiceStartup(IAppBuilder appBuilder, HttpConfiguration configuration)

        {

...

  appBuilder.Use<PatchRequestUpdaterMiddleware>();

...

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM