Tuesday, September 19, 2017

Introducing a generic (mostly) all purpose extensibility schema for the Microsoft Graph

If you’ve followed my blog lately you know I’m experimenting with using Graph Extensions from the Microsoft Graph to persist metadata for resources in the graph, more specifically I’m storing metadata about different types of Office 365 Groups.

image

I decided to go with schema extensions over open extensions as this allows me to query and filter on my schema properties, instead of just reading and writing the properties. If you plan on only reading and writing data, I recommend using open extensions – why? Read on!

Take a look at https://developer.microsoft.com/en-us/graph/docs/concepts/extensibility_schema_groups for information about using schema extensions.

I had a question going on over at StackOverflow and the comments here gave me a real eye opener. (Now is the time to concentrate and read with full attention.)

Once you make a schema extension available, this schema is visible and available to EVERYONE in the whole wide world of Office 365 at that very instant. Let that sink in for a bit. AVAILABLE FOR EVERYONE!

Let’s play with an example to illustrate the issue. Say you create the following schema extension for a customer:

{
    "id": "NorwegianRoyalSchema",
    "description": "Metadata to describe peculiarities about members of the Royal family. For a good time call 555-6969.",
    "targetTypes": [
        "User"
    ],
    "owner": "<guid>",
    "properties": [{
            "name": "BelievesInAngels",
            "type": "Boolean"
        }, {
            "name": "LikesToParty",
            "type": "Boolean"
        }, {
            "name": "LikesExperimentingWithDrugs",
            "type": "Boolean"
        }, {
            "name": "MaxNumberOfAllowedDrinks",
            "type": "Integer"
        }
    ]
}

Would you like this schema to show up for the whole wide world!? If your answer is yes, that’s ok, but the way this is built by Microsoft shows you really need to pay attention to what you put into the name, description and names of properties in your schema. Potentially you leak information which should have stayed private.

Ideally, only schemas belonging to applications you have consented to in your tenant would show up, which makes perfect sense, but until then, maybe there’s a better approach? – Again, keep on reading!

The all purpose schema

If you list all schemas with a call to https://graph.microsoft.com/v1.0/schemaExtensions you will find my first schema attempt named extbufqc89t_CollaborationMetadata, which you are free to use. You will also find another schema named techmikael_GenericSchema, which is the crux of this post.

techmikael_GenericSchema is a generic schema which has a set of re-usable properties for graph objects of types:

  • Group
  • User
  • Device
  • Organization

The schema provides 10 string, 5 integer, 5 boolean, 5 date time and 5 binary properties, and each property is a triple on the format:

"properties": [{
        "name": "KeyString00",
        "type": "String"
    }, {
        "name": "LabelString00",
        "type": "String"
    }, {
        "name": "ValueString00",
        "type": "String"
    }, {
        "name": "KeyInteger04",
        "type": "String"
    }, {
        "name": "LabelInteger04",
        "type": "String"
    }, {
        "name": "ValueInteger04",
        "type": "Integer"
    }
]

If you get the convention, each property has a key, value and a label.

Say you want to add metadata to a user object in the Microsoft Graph. You could then run the following payload in a patch operation against the user object.

{
    "techmikael_GenericSchema": {
        "KeyString00": "Name",
        "LabelString00": "Display name",
        "ValueString00": "Mikael Svenson",

        "KeyString01": "Title",
        "ValueString01": "CTO Puzzlepart",

        "KeyBoolean00": "IsMVP",
        "LabelBoolean00": "Is Microsoft MVP",
        "ValueBoolean00": true
    }
}

If you want to filter out all users being an MVP, you could run the following filter query:

https://graph.microsoft.com/v1.0/users?$filter=techmikael_GenericSchema/ValueBoolean00 eq true&$select=displayName,id,description,techmikael_GenericSchema

Which of the three properties per triple you use is all up to you, but using the key and label properties in addition to the value property might help identifying the property usage and help with rendering. You could stick to only using the Value<Type>XX properties, and handle the naming logic in your application, it’s all up to you. Personally I will use all three, as it will give information about the value itself for anyone exploring the data.

Summary

I have made available a generic schema for you to use freely in all your solutions. I can not delete the schema nor can I change any of the existing properties, thus there is no possibility of me breaking your solution. If you do take a dependency on my schema, feel free to drop me a note about how you are using it.

Note: If you want to use schema extensions against Exchange objects, I could provide one, but Exchange does not support boolean and integer values – hence the types used in the above schema.