Announcing the new version of the Graph API: api-version=2013-11-08
We're excited to announce the next version of the Graph API, api-version=2013-11-08 is now available. There are several updates that can be useful for your applications, and enable some new scenarios.
The major updates in this release include:
- Support for provisioning Federated users
- User License assignment
- Support for adding multiple members to a Group
- Managing a Group's Owner
- Sorting Groups by their Display Name property
- Additional Differential Query features
1. Provisioning Federated Users, by exposing a new user property: immutableId
We now expose a new user property called “immutableId” through the Graph API. What is the significance of this property? It is used to associate the on-premises user object account to the cloud user hosted in Azure Active Directory – for example, if you have an on-premise directory, and the user object from that directory has an identifier GUID with a value of “9c5923e9-de52-33ea-88de-7ebc8633b9cc", then the Azure AD User object can store this value in its immutableId property (stored as a string). The immutableId is used to link the on-premises account identity with the Azure AD account identity. Note: the immutableId value cannot contain spaces or the $ symbol.
Note: customers using the Microsoft DirSync tool, will automatically have sync’ed Azure AD Users’ immutableId property populated – DirSync writes this value as the base64 encoded value of the on-premises object Guid. Application should store the value that meets the requirements of their federated identity service provider
Here’s an example GET call, requesting only a user’s immutableId property:
GET https://graph.windows.net/contoso.com/users/Adam@contoso.com/immutableId?api-version=2013-11-08
RESPONSE (in JSON): { “value”:”6SNZnFLe6jOI3n68hjO5zA==” }
If you are creating an Azure AD User, and are using a federated domain for the User’s userPrincipalName property, then you must specify a value for the user’s immutableId property – for example, this is the POST operation to create a new user, assigning @Fabrikam.com to the user’s userPrincipalName, which is configured as a federated domain.
Creating a New User using a federated domain “Fabrikam.com” |
POST |
https://graph.windows.net/Contoso.com/users?api-version=2013-11-08 |
HEADERS: Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { "accountEnabled":true, "userPrincipalName":Derek@Fabrikam.com, "displayName":"Derek ", "mailNickname":"Derek", "passwordProfile":{ "password":"placeHold3r$", "forceChangePasswordNextLogin":false}, “immutableId”: “6SNZnFLe6jOI3n68hjO5zA==” } |
HTTP RESPONSE: 201 Created NOTE: in the above example, a password is required as part of the POST user creation call, but is not used because the User is using a Federated identity. |
In this new API version, we have also exposed a new user property, userType. This is a string value that can be used to allow tenants to classify the types of users within their organization. For example, regular employees can be identified by userType = “Member”, and guest accounts associated with vendors, consultants or temporary workers, could be have userType = “Guest” .
2. Support for User Licensing
This action was first available under a preview version (api-version=2013-04-10-preview) and is now officially supported in the “2013-11-08” release. This method allows assignment and removal of a subscription for any provisioned user account. For example, here’s an initial license assignment of the Enterprise Office Sku, which contains SharePoint Online, Lync Online and the Exchange Online service plans.
POST |
https://graph.windows.net/contoso.com/users/adam@contoso.com/assignLicense?api-version=2013-11-08 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { "addLicenses":[{"disabledPlans":[ ],"skuId":"6fd2c87f-b296-42f0-b197-1e91e994b900"}], "removeLicenses":[ ] } |
HTTP RESPONSE: 200 OK |
Here’s an example of updating a User’s license by disabling specific plans. In this example, there are 2 disabledPlans (SharePointOnline and LyncOnline"), leaving only the Exchange Service Plan.
Select User License Assignment |
POST |
https://graph.windows.net/contoso.com/users/adam@contoso.com/assignLicense?api-version=2013-11-08 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { "addLicenses":[ { "disabledPlans": [”5dbe027f-2339-4123-9542-606e4d348a72”, “0feaeb32-d00e-4d66-bd5a-43b5b83db82c” ], "skuId":"6fd2c87f-b296-42f0-b197-1e91e994b900" } ], "removeLicenses":[ ] } |
HTTP RESPONSE: 200 OK |
Finally, here’s how to remove the license from the user.
Remove User License Preview |
POST |
https://graph.windows.net/contoso.com/users/adam@contoso.com/assignLicense?api-version=2013-11-08 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { "addLicenses":[ ], "removeLicenses":["6fd2c87f-b296-42f0-b197-1e91e994b900"] } |
HTTP RESPONSE: 200 OK |
How do you get the subscription Sku Id and the plan ids? These can be read from the tenant object, by calling GET https://graph.windows.net/contoso.com/subscribedSkus
which will return the subscriptions available for the tenant – this includes the SkuId and servicePlans Id’s under the Sku. Availability of subscriptions can be calculated from the “consumedUnits” property and values
from “prepaidUnits” complex property, which includes counts of units that are “enabled”, “suspended” and in “warning” states. You can view this using the https://GraphExplorer.cloudapp.net demo – select
“Use Demo Company”, and execute this query: https://graph.windows.net/GraphDir1.OnMicrosoft.com/subscribedSkus?api-version=2013-11-08
3. Adding Group Members operation can now support multiple member objects in the same request.
We have always allowed adding a single object to a group, but we now support multiple objects being added to a group in one call. The example below adds two new users to a group. NOTE: The maximum allowed number of links to add in a single POST/PATCH request should be kept to 20 or below. Attempts to add a higher number of links can result in a failure response.
Update Group or Role membership |
PATCH |
https://Graph.windows.net/contoso.com/groups/02a8a087-a371-43f9-94df-cf0f654de307?api-version=2013-11-08 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { [ "/contoso.com/users/09f8c01f-53cd-466f-9d2e-b7fb6a77b119", "/contoso.com/users/2ac58744-e872-49fa-bfb2-d0ff8c0d5750" ] } |
HTTP RESPONSE: 204 No Content |
Note: Removing multiple members is not supported at this time.
4. Managing Group Owners
How do you find a Group’s owner? Easy - the following will return the Group's owner: GET https://Graph.windows.net/contoso.com/groups/02a8a087-a371-43f9-94df-cf0f654de307/owners?api-version=2013-11-08
The following will return the group object, and the owner objects in one call: https://Graph.windows.net/contoso.com/groups/02a8a087-a371-43f9-94df-cf0f654de307?$expand=owners?api-version=2013-11-08
And to assign an owner to a Group, the following POST operation can be executed:
Update a Group’s Owner |
POST |
https://Graph.windows.net/contoso.com/groups/02a8a087-a371-43f9-94df-cf0f654de307/$links/owners?api-version=2013-11-08 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY { "url": "https://graph.windows.net/contoso.com/users/88478020-a5b2-4176-b720-838af8dee190" } |
RESPONSE: 204 No Content |
And with other links, you can also find out what objects are owned for a User:
GET https://graph.windows.net/contoso.comt/users/adam@contoso.com/ownedObjects&api-version=2013-11-08
Or retrieve the user and the user's owned objects in one call: GET https://graph.windows.net/contoso.comt/users/adam\@contoso.com?$expand=ownedObjects&api-version=2013-11-08
5. Sorting lists of Groups by display name
We now allow your app to specify sorting by the Group’s display name property. For example: GET https://graph.windows.net/contoso.com/groups?$orderby=displayName?api-version=2013-11-8. And in case you missed it in my previous blog post, you can specify sort order for user lists, by either the displayName or userPrincipalName property.
6. Additional Differential Query features
Differential Queries can now return only updated properties and links – this allows faster processing and reduced payloads for Differential Query calls. This option is enabled by setting the header ocp-aad-dq-include-only-changed-properties to true as shown in this example.
GET |
https://graph.windows.net/contoso.com/users?api-version=2013-11-08&deltaLink= furK18V1T…. |
HEADERS ocp-aad-dq-include-only-changed-properties : true Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5nl0aEV1T…. |
Response: 200 OK |
For example if only the “displayName” property of user has changed. The returned object would be similar to this:
{
"displayName" : "AnUpdatedDisplayName",
"objectId" : "c1bf5c59-7974-4aff-a59a-f8dfe9809b18",
"objectType" : "User",
"odata.type" : "Microsoft.WindowsAzure.ActiveDirectory.User"
},
Differential Sync Support to Sync from “now” - a special header can be specified, requesting to only get an up-to-date deltaToken, this token can be used in subsequent queries, which will
return only changes from “now”. Here’s the example call:
GET |
https://graph.windows.net/contoso.com/users?api-version=2013-11-08&deltaLink= smLYT8V1T… |
HEADERS ocp-aad-dq-include-only-delta-token: true Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5nl0aEV1T…. |
Response: 200 OK |
The response will contain the deltaLink, but will not have the changed object(s), similar to this:
{ … "aad.deltaLink":https://graph.windows.net/contoso.com/users?deltaLink=MRa43...... }
We’ll dive into Differential Query calls in much more detail in the upcoming posts.
Give Use Feedback
We will be updating our sample applications to show some of the above mentioned features in the new version: https://msdn.microsoft.com/en-us/library/hh974459.aspx and in an upcoming post, we will include code snippets showing how to use these new capabilities.
Please let us know if the new features are useful, and let us know what other Api's will be useful for your scenarios. Leave a comment or your questions on this Post.
Thanks, Edward
Azure Active Directory Team
Microsoft Corp
Comments
Anonymous
November 25, 2013
About "Provisioning Federated Users", you're killing me with your spelling, is it: "immutableId", "immutabelId" or "immudatableId"??Anonymous
November 25, 2013
Apologies HansZ, it is corrected and should be "immutableId"Anonymous
November 26, 2013
Brilliant! Thanks for this. I've been trying to use standard oData libraries against GraphAPI but I've discovered that there is no support for the standard oData paging mechanism via $top and $skip in api-version 2013-04-05. Is this available in this version?Sincerely,//AdamAnonymous
November 27, 2013
Hi Adam, $top is available in the previous version (2013-04-05) and in this latest version (2013-11-08), however $skip is supported at this time. You can read my previous post about paging using $top and how to page forward and backwards. Here's an example of paging for the first 999 results:graph.windows.net/.../users$top=999&api-version=2013-11-08let me know if you have more questions after reading our previous Post about paging.Thanks, EdAnonymous
November 27, 2013
i missed a "not" in my previous reply - I meant to write "... $skip is not supported at this time".-EdAnonymous
December 10, 2013
Excellent!... Now I can move off PowerSshell directly to Graph as the two major limitations have been addressed:Federated Users LicensingAnonymous
December 18, 2013
The comment has been removedAnonymous
December 19, 2013
Looks like you're executing this correctly - I just validated that I could update this on an existing user in my tenant. how long of a value are you using for the immutableId property?Anonymous
December 24, 2013
Thanks for the response.I can confirm that all works fine. That was some "strange" encoding issue on my side.Anonymous
January 13, 2014
Great news - we've been waiting for license assignment and the ability to set ImmutableId.The only gap in support for us is the ability to update domain settings, moving them between managed and federated, and setting STS urls and signing keys. Will this be available on the Graph API and if so when?Anonymous
January 14, 2014
The comment has been removedAnonymous
January 17, 2014
Does the rest api support creating multiple users in one call? If yes can you post a sample payload?Anonymous
January 22, 2014
Yes, we support batching - there are some current limits on the batching:batch size is currently limited to 5 operations (e.g. 5 GETs, 5 POSTs etc.)batch operations must be of the same type (e.g you can't have a GET, POST, PATCH, DELETE in the batch) I will follow-up and show the sample payload and response.Anonymous
January 27, 2014
The comment has been removedAnonymous
January 28, 2014
I'm using this solution in the institution where i work. But at this moment I'm having a problem to list all users. Only 100 records are displayed. I'm using this operation: msdn.microsoft.com/.../dn151678.aspxHow can i show ALL users?Anonymous
January 29, 2014
Regarding the Error Creating User - if you receive 401 Unauthorized, then the only reason is the app doesn't have write permissions - can you do any other update operations, such as updating an existing user or deleting a user? Or creating,updating,deleting a security group?BTW, when using client creds (appId and secret), the context of the logged on user doesn't matter - the logged on user is just a user (non-Admin), but the app has read/write permissions, then the app will have read/write permission when the user executes the app.Thanks, EdAnonymous
January 29, 2014
Answer to Ricardo's question about only 100 users being returned for this query:graph.windows.net/.../usersBy default, the page size is 100. To specify a different page size, use $top - the maximum page size is 999 - for example: graph.windows.net/.../users$top=999Note, if there are more results beyond your page size, the response body will contain a property called odata.nextLink For example (note, I truncated the skiptoken value to make this more readable):"odata.nextLink": "directoryObjects/$/Microsoft.WindowsAzure.ActiveDirectory.User?$skiptoken=X'44537074....000000'"To get the next page of results, your next query would use the $skiptoken value - for example:graph.windows.net/.../users$top=999&$skiptoken=X'44537074....000000'If you want to read more about paging (including how to page forward/backward), please review #3 on my post:blogs.msdn.com/.../enhancing-graph-api-queries-with-additional-odata-supported-queries.aspxThanks, EdAnonymous
January 29, 2014
Response to Rob Potter's question regarding domain management, and configuring managed and federation properties on the domains - you are correct, we don't have these API's today - it is something we are planning to add, so we have parity with capabilities available in Msonline PowerShell - stay tuned.Thanks, EdAnonymous
January 30, 2014
Answer to P.K's question about how to update the immutableId property - after the immutableId property is set on a user, and the user has a UPN that is using a federated domain, then the way to modify the immutableId is through a 3 step process:change the user's UPN to use a non-federated (i.e. managed) domain - for example: a user with UPN = Adam@contoso.com has an immutableId value set, and the domain, contoso.com is a federated domain. We need to change the UPN to a managed domain (e.g. change UPN=Adam@contoso.onMicrosoft.com).Now update the immutableId value Now update the user's UPN back to the federated domain - set UPN=Adam@contosol.com these are the steps for modifying an existing immutableId property. Also note: if you delete a user that has an immutableId value set, and you attempt to create or update a user to use the immutableId of the deleted user, your create/update attempt will fail with "..object already exists.." This is because the object is in the soft-deleted state - to fix this, you will need to hard-delete the object, before attempting to re-use the immutableId on a new or existing object.Anonymous
March 10, 2014
Is there an equivalent to Windows AD LogonUser operation in Windows Azure AD. This is to allow a user to silently login with his user ID and password to Azure AD to retrieve a JWT Token.Anonymous
March 31, 2014
The comment has been removedAnonymous
March 31, 2014
I've solved the problem. I've been referring to an MS implementation document, which put the verb required as PATCH. Send through the request with a POST verb and it works fineAnonymous
April 01, 2014
How do I link the Offer Id provided in the MOSI PlaceOrder call to the subscriptions/subscribedSkus for that tenant?I know the MOSI SubscriptionId is an internal id to MOSI. However, we rely on the OfferId and send that across. Then, when querying GRAPH, I can get the SubscribedSkus....but this only gives me a list of servicePlans (inc. GUIDS); a SKU id (unique to the tenant); and an object Id.Given a tenant that has 2+ subscriptions (none of which to the same offerId), how do I link these to the offer Id?My question from above still stands also: how do i get the metadata for the 2013-11-08 api? I can make calls to this API but I can't retrieve the metadata (which is causing me problems with the immutableId not being present)?Appreciate your advice. ThanksAnonymous
April 05, 2014
Edward,A little delayed, sorry! Not being able to use GraphAPI with standard OData libraries is a bit of a hassle, given the mechanism is similar, would it be possible to implement the $skip method?After all, its part of the standard and I'm a little miffed as to why a non-standard method was used, curious decision (:msdn.microsoft.com/.../ff478141.aspx//AdamAnonymous
July 23, 2014
Whats the plan for updating these docs to include the new fields?msdn.microsoft.com/.../hh974483.aspxAlso how about something that describes permissible values for all known fields?Anonymous
July 23, 2014
How does one set a value for thumbnailPhoto via the REST api? It says Edm.Stream, but does that mean I pass the bytes as a base64 encoded string?Anonymous
July 23, 2014
What are the actual permissible values for 'userType'? The sentence below seems to imply the tenant can set it to any arbitrary string but that does not seem to be the case"In this new API version, we have also exposed a new user property, userType. This is a string value that can be used to allow tenants to classify the types of users within their organization. For example, regular employees can be identified by userType = “Member”, and guest accounts associated with vendors, consultants or temporary workers, could be have userType = “Guest” ."Anonymous
July 23, 2014
For the "assignLicenses" featurea) I am doing the exact same thing as the example where I disable 2 service plans within a sku. This is accepted by the service with a 200b) I then do a GET of that user I just adjusted the licenses for. The service plans I disabled are not reflected in the AssignedPlans return element, NOR does the number of total AssignedPlans seem to reflect the changeWhy is this?Anonymous
September 15, 2014
Is it possible to create a 'Microsoft Account' user with this version of the API?Anonymous
September 01, 2015
there exist several complementary "relationships": members|memberOf, owners|ownedObjects, manager|directReports ... if these were in an sql database, they might be represented in a simple relationship table. what i'd like to be able to do is get that whole table returned to me, instead of having to pick a value in either column and get all the values it has in the "other column" in AAD, this would amount to a call that would return links with "one endpoint of the relationship, the relationship 'method', and the other endpoint of the relationship" is there anything i can do to mimic this result? as it stands, if i have N users and M groups, i have to do at least min(M,N) separate queries... would like "one-stop-shopping" please!Anonymous
September 20, 2015
Does "ocp-aad-dq-include-only-changed-properties" still work? I've been trying to get it working with the 1.5 and 1.6 version apis and it always returns the entire object, not just the properties that were updated.Anonymous
November 23, 2015
We are trying for optimization (minimizing the time required for aggregation) of aggregation process. Currently we are using pagination but it takes lots of time min 25hrs . We wanted to reduce it to 4-5 hrs. How to achieve that ?. Is there any query to get all users in one call without using skiptoken? Or is there any other way to do it ?Anonymous
January 04, 2016
The comment has been removed