4

As a newcomer to the SCIM (System for Cross-domain Identity Management) standard, please excuse any ignorance as I'm on the learning curve trying to figure out how to make clean/simple requests to provision users, delete users and modifiy users.

I'm attempting to use C#/.NET to make HTTP REST requests for a user via SCIM, using the System.Net.Http.HttpClient

https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.110).aspx

I can do this successfully and get a JSON response from the server, however in order to easily read the response object and manipulate it, I want to deserialize it.. After much reading around trying to use things like JsonConvert, dynamic etc. I stumbled upon a Microsoft nuget library which seemed to hint at being useful. Sadly there don't appear to be any docs for it*

UPDATED: One of the authors has updated the nuget page with a link to a blog post which goes some way to explaining usage.

Microsoft.SystemForCrossDomainIdentityManagement

https://www.nuget.org/packages/Microsoft.SystemForCrossDomainIdentityManagement/

The SCIM provider I'm attempting to get data from is Facebook, using the example they publish on their site for getting a user by email:

https://developers.facebook.com/docs/facebook-at-work/provisioning/scim-api#getuserbyemail

Here's a code sample in C# which attempts to get the user from the SCIM service and deserialize them. I'm finding that the queryResponse I get back is deserialized correctly as the properties are populated, however the Core1EnterpriseUser which is the first and only of the resource objects, has null/default properties.

var userName = "foo.bar@foobar.com";
var response = await client.GetAsync($"Users?filter=userName%20eq%20%22{userName}%22");

if (response.IsSuccessStatusCode)
{
    var json = await response.Content.ReadAsStringAsync();
    var jsonResponseProperties = await Task.Factory.StartNew(() => { return JsonConvert.DeserializeObject<Dictionary<string, object>>(json); });

    var userFactory = new QueryResponseJsonDeserializingFactory<Core1EnterpriseUser>();
    var queryResponse = userFactory.Create(jsonResponseProperties);

    if (queryResponse.TotalResults == 1)
    {
        var user = queryResponse.Resources.First();
        var id = user.Identifier; // this and other properties are null/false etc.
    }
}

Here's a sample of the JSON that is returned by the service when I query it:

{
   "schemas": [
      "urn:scim:schemas:core:1.0"
   ],
   "totalResults": 1,
   "itemsPerPage": 10,
   "startIndex": 1,
   "Resources": [
      {
         "schemas": [
            "urn:scim:schemas:core:1.0",
            "urn:scim:schemas:extension:enterprise:1.0",
            "urn:scim:schemas:extension:facebook:starttermdates:1.0",
            "urn:scim:schemas:extension:facebook:suppressclaimemail:1.0"
         ],
         "id": 180383108978226,
         "userName": "foo.bar\u0040foobar.com",
         "name": {
            "formatted": "Foo Bar",
            "familyName": "Bar",
            "givenName": "Foo"
         },
         "title": "Vice President",
         "active": true,
         "emails": [
            {
               "primary": false,
               "type": "work",
               "value": "foo.bar\u0040foobar.com"
            }
         ],
         "urn:scim:schemas:extension:enterprise:1.0": {
            "department": "IT"
         },
         "urn:scim:schemas:extension:facebook:starttermdates:1.0": {
            "startDate": 0,
            "termDate": 0
         }
      }
   ]
}

UPDATE:

I'm in dialog with one of the authors of the project and he kindly pointed me at this blog post:

http://blogs.technet.com/b/ad/archive/2015/11/23/azure-ad-helping-you-adding-scim-support-to-your-applications.aspx

He has also updated the nuget library which now includes support for v1 of SCIM, also pointing out that as the JSON data suggests the version used by Facebook is v1: "urn:scim:schemas:core:1.0" so now I can use Core1 rather than attempting to use Core2 classes (I've updated the question above to use Core1EnterpriseUser).

I'm still not able to get my response deserialized correcty at present and will update the question with more information as I have it.

Again, I don't have to use this library if it becomes apparent that it's not easily going to work, as I know the brief description on nuget suggests it was created for Azure AD.

However I'd appreciate any advice on how this type of thing could/should be done as I'm sure there must be a lot of people out there using SCIM - how do you parse your responses/generate your requests such that you have actual objects? Can you automatically parse responses for schemas in order to augment the object with the correct properties?

I was up late last night hand crafting some model classes to handle the response objects - which I do seem to have working. If I can't get the nuget library working (the preferred option) then I'll have to go with my own. :/

Thanks again peteski

peteski
  • 1,455
  • 3
  • 18
  • 40
  • Please check the answer in: https://stackoverflow.com/questions/45729018/deserialize-facebook-workplace-scim-rest-api-response/45730105#45730105 – Asaad Mamoun Aug 17 '17 at 08:54

1 Answers1

1

Although I'm still none the wiser about best practices with SCIM, I've managed to get the code working now - with massive thanks to one of the nuget library's authors Craig McMurtry at Microsoft!

There were a few things to iron out along the way, such as the nuget package being updated to include the previous support for older v1 SCIM objects. But here's a snippet of what worked based on the example in my question, but it turned out to be using the Newtonsoft serializer. :(

In the code above the line:

var jsonResponseProperties = await Task.Factory.StartNew(() => { return JsonConvert.DeserializeObject<Dictionary<string, object>>(json); });

Was replaced with:

var jsonResponseProperties = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);

Et voilà! My object's properties are now deserializing...

peteski
  • 1,455
  • 3
  • 18
  • 40
  • I am facing the same issue. Your solution may solve a part in my solution but I want to deserialize the json to strongly types objects. Thanks anyway – Asaad Mamoun Aug 17 '17 at 08:31