Announcing the new version of Graph API: api-version=1.5
The Azure AD Graph team is very pleased to announce the availability of the next version of Azure AD Graph API, api-version=1.5. With this release we've opened up a new set of scenarios for developers, which we'll describe in more detail below:
- Authorize access to your applications based on group claims or application specific roles claims present
in tokens. Through Graph API you can now:- Configure the group membership claims issuance policy on an application
- Define roles specific to your application. These roles can be chosen when assigning the application to users, groups or service principals, either programmatically or through the Azure Management Portal. When the user signs in to the application the user token will contain a roles claim with any of the application roles the user was assigned to - either directly or indirectly through group assignment.
- Expose your application as a web API secured by Azure AD by defining OAuth2.0 permission scopes. These permission scopes may then be chosen by client applications that call your web API.
- Directory Extensions is now released for General Availability, with a new additional capability that differential query will now respond with any changes to schema extended properties too.
For full details of all the changes in api-version 1.5 (from the previous api-version=2013-11-08), please see https://msdn.microsoft.com/en-us/library/azure/dn835125.aspx.
NOTE: In this blog we'll also provide some details on the latest application manifest updates. You should note that the operations described in 1 and 2 above are also configurable through the application manifest.
At the same time as releasing a new version of Graph API, we've also released a new Graph client library with lots of cool new capabilities. You can check out our blog post for that here.
General information about version 1.5
In this release we also focused on improvements based on developer’s feedback. Versioning scheme has been updated to numeric major.minor format and is better aligned with versioning scheme of Office 365 REST APIs GA release.
The schema namespace of Graph API has changed from Microsoft.WindowsAzure.ActiveDirectory to Microsoft.DirectoryServices. This affects all entities and complex types exposed by Graph API.
Additionally starting with this version, we plan to start adding new entities and properties more frequently without revisiting the service version in order to allow developers to take advantage of new features sooner. If you are using the WCF client library, then you should make sure to set “IgnoreMissingProperties” to true. You’ll need this anyway to support directory schema extensions. Please do let us know what you think. We are looking forward to hearing your feedback about this approach.
Application roles
You can define roles specific to your application. Imagine you have a Dental Practice app - you might define the following roles:
- "Dentist" role allowed to create, view and update
patient health records - "Receptionist" role allowed to create and manage patient
information (but not personal health details), and manage appointments.
These application roles can be assigned to a user or group (as well as a service principal). Then when a user signs in to the application, the user token will contain a roles claim with any of the application roles the user was assigned to - either directly or indirectly through group assignment. This then allows your application to make authorization decisions purely based on the roles claim. We'll show you how to create, view, update and delete application roles, as well as assigning and removing assignments of application roles.
Adding and viewing application roles
NOTE: application roles can be created as part of application creation - however that is not shown here. Instead we'll just how you how to add app roles to an existing application. The following shows the addition of the 2 roles described above.
PATCH |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY: { "appRoles": [ { "allowedMemberTypes": [ "User" ], "description": "Dentists may create and update patient's health records", "displayName": "Dentist", "id": "31952ade-a03c-414c-8340-2f11e9099106", "isEnabled": true, "value": "dentist" }, { "allowedMemberTypes": [ "User" ], "description": "Receptionists may manage patient information and appointments", "displayName": "Receptionist", "id": "55048f57-6105-4fef-bb3a-96dcc6db90bb", "isEnabled": true, "value": "receptionist" } ] } |
allowedMemberTypes describes the entities that the role may be assigned to. User means the role can be assigned to a useror group. Application means the role can be assigned to another application - in the form of a service principal. This latter scenario is allows a different client application to call this application's API in a particular role. More details can be found on the AppRole complex type description.
Viewing a role
Viewing a role is as simple as getting the application entity:
The application role is returned in the appRoles collection.
Updating a role
The following updates the existing Dentist role to allow it to be assigned to an application, as well as changing the description.. Note that the whole appRoles collection must be sent again in the update, including the edits that you wish to make. If you want to add a new app role then you need to add it to the existing collection.
PATCH |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY: { "appRoles": [ { "allowedMemberTypes": [ "User", “Application” ], "description": "Dentists may create, update and delete patient's health records", "displayName": "Dentist", "id": "31952ade-a03c-414c-8340-2f11e9099106", "isEnabled": true, "value": "dentist" }, { "allowedMemberTypes": [ "User" ], "description": "Receptionists may manage patient information and appointments", "displayName": "Receptionist", "id": "55048f57-6105-4fef-bb3a-96dcc6db90bb", "isEnabled": true, "value": "receptionist" } ] } |
Deleting a role
Deleting a role is possible, but you'll need to be sure to update your application code to account for the fact that existing users, groups and service principals may have already been assigned this deleted role. Your app code will still need to support this roles claim value showing up.
To delete an app role, you must first update the app role (PATCH) by setting isEnabled to false. Once that is done, create a new JSON appRoles collection payload without the app role you want to delete, and update using PATCH.
Viewing application role assignments
The following will list all application role assignments for a user:
GET https://graph.windows.net/contoso.com/users/jon\@contoso.com/appRoleAssignments?api-version=1.5
Similarly for a group:
Similarly for a service principal (to see the app role assignments an application has to call into a resource application):
To view the list of all app role assignments to a resource (represented by a service principal) – this will allow you to tell which users, groups and service principals are assigned to this resource:
Assigning application roles
The following will assign the dentist application role described earlier to a user.
POST |
https://graph.windows.net/contoso.com/ users/jon@contoso.com/appRoleAssignments?api-version=1.5 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY: { "id": "31952ade-a03c-414c-8340-2f11e9099106", "principalId": "84b80893-8749-40a3-97b7-68513b600544", "principalType": "User", "resourceId": "29c7ed43-a9a1-4b31-8a64-fc90c3ca4e73" } |
RESPONSE 201 { "odata.metadata":https://graph.windows.net/contoso.com/$metadata#directoryObjects/Microsoft.DirectoryServices.AppRoleAssignment/@Element, "odata.type":"Microsoft.DirectoryServices.AppRoleAssignment", "objectType":"AppRoleAssignment", "objectId":"kwi4hEmHo0CXt2hRO2AFRKOaYLLQbgVIqOCz-qKlrO0", "creationTimestamp":"2014-11-12T18:53:46.3182573Z", "id":"31952ade-a03c-414c-8340-2f11e9099106", "principalDisplayName":"Jon Doe", "principalId":"84b80893-8749-40a3-97b7-68513b600544", "principalType":"User", "resourceDisplayName":"Dental Practice Manager", "resourceId":"29c7ed43-a9a1-4b31-8a64-fc90c3ca4e73" } |
NOTE: It is possible to assign a user or a group to a resource through appRoleAssignments. This is possible even if the resource does not declare any app roles. In this case you should set the “id” in the request body to a zero GUID value.
NOTE: Currently assignment of a service principal to a resource is broken and we’ll work to fix this problem, and update this post when it's fixed.
Removing application role assignments
OAuth2.0 Permission Scopes
Expose your application as a RESTful API secured by Azure AD by defining OAuth2.0 permission scopes. These permission scopes may then be chosen by client applications that call your API using the RequiredResourceAccess complex type.
Creating OAuth2.0 Permission Scopes
NOTE: Permission scopes can be created as part of application creation - however that is not shown here. Instead we'll just how you how to add permission scopes to an existing application. The following shows the addition of a single permission that represents the ability for the calling application to fully impersonate the signed in user without any constraint. This permission may be granted by both users and administrators (type = User) and contains different display names and descriptions depending on whether this app is being consented to by a user, or by an admin on behalf of the school or company.
PATCH |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY: { "oauth2Permissions": [ { "adminConsentDescription": "Allow the application to access Web API perms on behalf of the signed-in user.", "adminConsentDisplayName": "Access Web API perms", "id": "dedd4bf0-e402-4f49-9762-0d32c884e6c2", "isEnabled": true, "type": "User", "userConsentDescription": "Allow the application to access Web API perms on your behalf.", "userConsentDisplayName": "Access Web API perms", "value": "user_impersonation" } ], } |
Updating OAuth2.0 Permission Scopes
This follows the same pattern as updating application roles.
Deleting OAuth2.0 Permission Scopes
This follows the same pattern as deleting application roles.
Granting OAuth2.0 permissions
The mechanism for this has not been updated in 1.5, although the link has been renamed from "permissions" to "oauth2PermissionGrants".
Configuring your app to access other resources
While this is possible through the RequiredResourceAccess complex type, discovering other developer’s API appId and the oauth2Permissions or appRole unique identifiers they expose may be difficult. For those scenarios, it’s recommended to actually configure this through UX – either in the Azure Management Portal (under the configure applications “Access to other applications” section) or through the Office
365 API tools for Visual Studio.
RequiredResourceAccess can also be viewed and set through the application manifest file.
Updates to directory roles
In Graph API 1.5, roles has been renamed to DirectoryRoles, so that we avoid any confusion with appRoles (described earlier). DirectoryRoles represent the built-in roles exposed by the directory itself, some of which are described here.
By default, when a tenant is created, only the Company Administrator role is instantiated (along with an implicit User role). In order to assign users or service principals to one of the built-in roles, that role
first has to be instantiated from a directory role template. The set of available roles can be listed using the DirectoryRoleTemplate read-only entity.
GET |
https://graph.windows.net/contoso.com/directoryRoleTemplates?api-version=1.5 |
HEADERS Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
RESPONSE: 201 { "odata.metadata":https://graph.windows.net/contoso.com/$metadata#directoryObjects/Microsoft.DirectoryServices.DirectoryRoleTemplate, "value": [{ "odata.type": "Microsoft.DirectoryServices.DirectoryRoleTemplate", "objectType": "RoleTemplate", "objectId": "fe930be7-5e62-47db-91af-98c3a49a38b1", "deletionTimestamp": null, "description": "User Account Administrator has access to perform common user management related tasks.", "displayName": "User Account Administrator" }, { "odata.type": "Microsoft.DirectoryServices.DirectoryRoleTemplate", "objectType": "RoleTemplate", "objectId": "f023fd81-a637-4b56-95fd-791ac0226033", "deletionTimestamp": null, "description": "Service Support Administrator has access to perform common support tasks.", "displayName": "Service Support Administrator" }, { … }] } |
To instantiate the role from a template, use the objectId of the desired role template. So for example, if we want to instantiate the User Account Administratorrole, perform the following POST operation on DirectoryRoles, setting roleTemplateId to fe930be7-5e62-47db-91af-98c3a49a38b1:
POST |
https://graph.windows.net/contoso.com/directoryRoles?api-version=1.5 |
HEADERS Content-Type: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1T…. |
BODY: { "roleTemplateId": " fe930be7-5e62-47db-91af-98c3a49a38b1" } |
RESPONSE 201 { "odata.metadata":"https://graph.windows.net/contoso.com/$metadata#directoryObjects/Microsoft.DirectoryServices.DirectoryRole/@Element", "odata.type": "Microsoft.DirectoryServices.DirectoryRole", "objectType": "Role", "objectId": "0b4f933e-bca3-4c4c-8469-7431fa4244c3", "deletionTimestamp": null, "description": null, "displayName": null, "isSystem": null, "roleDisabled": null, "roleTemplateId": "729827e3-9c14-49f7-bb1b-9608f156bbb8" } |
Querying the DirectoryRoles will show the instantiated directory roles including the newly instantiated User Account Administrator role:
GET https://graph.windows.net/contoso.com/directoryRoles?api-version=1.5
You can assign a user to a directory role by performing a POST operation on a specific directory roles link members as described here, where the directory role is specified by its objectId (and not its role template ID). When an application is configured to request group membership claims, the directory roles (object id) that the user is a member of will appear in these claims.
A little information about the Application Manifest
Through the Azure Management Portal, you are able to download, as well as upload a file representation of your application (in JSON format). No actual file is stored in the directory - the application manifest is merely a GET on the application entity, and the upload is a PATCH on the application entity. As a result, in order to find documentation on the format and properties of the application manifest, simply review the MSDN reference documentation on the application entity.
The Azure Management Portal provides UX for you to update the most common properties of an application. For more advanced scenarios, that are not exposed in the UX, you can use the application manifest, as an alternative to writing an application to call the Graph API to update your applications. Example updates that can be performed though app anifest upload include:
- Declare permission scopes (oauth2Permissions) exposed by your web API
- Declare application roles (appRoles) exposed by your app
- Declaring known client applications
- Request Azure AD issue group memberships claim for the signed in user. NOTE: this can be configured to additionally issues claims about the user's directory roles memberships.
- Allow your application to support OAuth 2.0 Implicit grant flows (for embedded JS web pages or SPA)
- Enable use of X509 certificates as the secret key
The application manifest also provides a good way to track the state of your app registration, and this file representation can be checked in along with your app's source code.
NOTE: For the Graph API 1.5 release, the application manifest signature has changed. There is currently no versioning support, so any attempts to upload an older format application manifest (generated before the release of Graph API 1.5) will result in an error. In this case simply re-download your app manifest from the Azure Management Portal to get the latest format.
Directory Schema Extensions
Directory extensions is now released for General Availability.
You can use directory schema extensions to store application data in the directory without having to store the same data in your own application profile database. For more scenarios anddetails on the entities that can be extended, possible extensions, and how to use the Graph API to manipulate extensions please see our topic on Directory Schema Extensions.
NOTE: Any extensions you created during the preview period for this feature are supported in 1.5.
Additionally, differential query will now respond with any changes to schema extended properties too.
Feedback
We hope you like the new functionality that we've added to the graph API in version 1.5. Please let us know what you think.
Thanks,
The Azure AD Graph API team.
Comments
Anonymous
April 28, 2015
Graph API (api-version=1.5) : How to remove user from Application Role using C# .NETHi,I am using Azure AD for user and role management operations from my MVC web application. I am using version of Graph API as 1.5 and Microsoft.Azure.ActiveDirectory.GraphClient .Net library 2.0.6.I need to remove an AppRoleAssignement (Application Role) assigned to user by calling Graph API. I was referring Stackoverflow link. Is there any method available in which I can use in my C# code to delete AppRoleAssignment.When I get users from active directory, the AppRoleAssignement always come null, even if an application role is assigned to a user.Kindly, help me providing a correct version of dll and available method to delete AppRoleAssignment.Thank you.Anonymous
September 28, 2015
Thanks for this post. Referring to the note: "NOTE: Currently assignment of a service principal to a resource is broken and we’ll work to fix this problem, and update this post when it's fixed" How close is it getting to seeing that resolved?Anonymous
October 07, 2015
I follow this instruction but always get status 403 "Insufficient privileges to complete the operation" when I try with PATCH Method. I configured all permissions by check all options at "permissions to other applications" on my AAD.Anonymous
December 27, 2015
The comment has been removedAnonymous
January 29, 2016
Co-ask: Referring to the note: "NOTE: Currently assignment of a service principal to a resource is broken and we’ll work to fix this problem, and update this post when it's fixed" How close is it getting to seeing that resolved?Anonymous
February 22, 2016
I'm trying to add a new app role dynamically via Graph API for .NET (rather than having to manually tweak the manifest) but am getting an insufficient privileges error. id="Microsoft.Azure.ActiveDirectory.GraphClient" version="2.1.0" Error: {"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}} Very similar codes works for adding a new group just fine. Any clue as to how to programmatically add a new app role and add a user into the new role?