Microsoft has recently release Microsoft Graph to easily integrate Office 365 resources with applications. Graph API basically provides one single endpoint to call bunch of Web APIs to get access Office 365 resources.
In order to use Graph API from another application, the application must be registered in Azure Active Directory (AAD) first. When the application is registered, we can choose how the application is permitted to use resources – application permissions or delegate permissions. The latter one typically requires users to provide user credentials like username and password to get a proper access token. However, there must be requirements that the application doesn’t require users credentials but should directly access to Office 365 resources, which is called app-only
mode. For example, a back-end Web API application doesn’t require user credentials to communicate with Graph API. There are many articles on the Internet dealing with user credentials but not many articles coping with this app-only
mode. In this post, I will walk through how to register an application as app-only
mode and consume Graph API through the registered application.
The sample code used here can be found here. This sample application is built-in ASP.NET 5 and ASP.NET MVC 6. Therefore, in order to get the best development experience, I would recommend using Visual Studio 2015.
Registering Application
OK. First thing goes first. As the sample application is using AAD and Graph API, it’s a mandatory to register this app on your AAD first. Please follow the steps below.
Create User Account on AAD
You can skip this step, if you have already got a user account on AAD.
NOTE: Microsoft Account won’t work with this sample app.
Create a user account on AAD tenant. Once created, the user account should be a co-administrator of the Azure subscription that is currently being used.
Register Application to AAD
- Login to Azure Management Portal.
- Select Active Directory.
- Create a new application.
- Choose the
"Add an application my organization is developing"
option.
- Enter the application name like
"Graph API App-only Sample"
and select the"Web Application and/or Web API"
option.
- Enter
"https://(tenant-name)/GraphApiAppOnlySample"
for both fields.(tenant-name)
should look likecontoso.onmicrosoft.com
. Please note that both won’t be used at all.
Now the app has been registered.
Configure Application
- Once the app is registered, click the
configure
tab.
- Get the
Client ID
.
- Get the secret key. Note that the key is only displayed once after click the
Save
button at the bottom.
- Add another application called
Microsoft Graph
- Give
"Read directory data"
permission toMicrosoft Graph
, as only this permission is necessary to run the sample app.
ATTENTION: In the production environment, appropriate number of application permissions MUST be given to avoid any security breach.
The app has been configured.
Update Settings in Sample Application
As the app has been registered and configured, the sample Web API app should be setup with appropriate settings. Firstly, open appsettings.json
Then change values:
Tenant
:contoso.onmicrosoft.com
to your tenant name.ClientId
: Client ID from the app.ClientSecret
: Secret key from the app.AppId
:contoso.onmicrosoft.com
to your tenant name.
Trust IIS or IIS Express with a Self-signed Certificate
- You can skip this step, if you intend to publish this app to Azure.
- You can skip this step, if you already have a self-signed certificate on your root certificate storage.
All communications with AAD and Graph API are performed through a secure channel (SSL/TLS), this sample app MUST be signed with a root certificate. However, this is a developer’s local environment, so a self-signed certificate should be issued and stored as a root certificate. If you don’t store the self-signed certificate, you’ll see the following message popped up when you run VS2015.
The following steps show how to register self-signed certificate to the root certificate store using PowerShell.
Check Self-signed Certificate
First, Check if you have a self-signed certificate in your personal certificate store.
If there’s no certificate with name of CN=localhost
, you should create the one using makecert.exe
. The easiest way to execute makecert.exe
is to run Developer Command Prompt for VS2015
.
-r
: Create a self signed certificate.-pe
: Mark generated private key as exportable.-n
: Certificate subject X509 name. eg)-n "CN=localhost"
-b
: Start of the validity period inmm/dd/yyyy
format; default to now.-e
: End of validity period inmm/dd/yyyy
format; defaults to 2039.-ss
: Subject’s certificate store name that stores the output certificate. eg)-ss My
-len
: Generated Key Length (Bits). Default to2048
for ‘RSA’ and512
for ‘DSS’.
Store Self-signed Certificate to Root Store
Second, store the self-signed certificate to the root store.
Finally, you can verify the self-signed certificate has been stored into the root store.
Build and Run Sample Web API Application
All setup has been completed! Now, build the solution in Visual Studio 2015 and punch F5
key to get into the Debug
mode. Then you’ll get a JSON response of your tenant organisation details. How does it work? Let’s look into the code.
Get Access Token from AAD Using ADAL
In order to get an access token from AAD, we need to setup AuthenticationContext
instance and call a method to get one. The code snippet below is an extract from the sample application.
The graphApp
instance is created from appsettings.json
and injected to the controller. With this instance, both AuthenticationContext
instance and ClientCredential
instance have been created. Note that the ClientCredential
instance only uses clientId
and clientSecret
, not user credentials. In other words, this sample application won’t require any user to login and provide their login details. Let’s see the actual Get()
method.
This is the part to get access token. The AuthenticationContext
instance sends a request for Graph API with the ClientCredential
instance only containing clientId
and clientSecret
. When the authentication fails, the Get()
action will return the exception details as a JSON format. The authResult
instance now contains access token.
Call Graph API with Access Token
Now, we have the access token. In the same action method, let’s see how it is consumed to call Graph API.
The access token is set to the request header. In this sample code, we call organization
details through Graph API. If you use Fiddler, send a request to the application and you will see the full response details.
So far, we have had a brief look how to implement a simple Web API application as app-only
mode to consume Graph API. As stated above, this sample application is not for production use unless proper permissions are given. Once all appropriate permissions are setup, you can easily customise this app for your integration purpose. Hope this will help your development.
There is one mistake with this sample code that I spent a day trying to work around.
If you are registering the application yourself (in the step Register Application to AAD), you must have an administrator role in the Active Directory service where you are registering the app. Global Administrator will work, but I haven’t tested using any of the other administrative roles. Link to all roles and descriptions is here: https://docs.microsoft.com/en-us/azure/active-directory/active-directory-assign-admin-roles.
Just being a co-administrator for the Subscription is not enough.
Hi, Sean.
Thanks for the comment. Let me more clarify the roles that I have within my organisation.
I have a “co-administrator” role on the Azure subscription and a “user” role on Azure AD of my company. I have no issue with registering applications on AAD and change permissions.
Interesting, Justin. Appreciate the article by the way. Has really helped me get started.
I notice in your screenshot where you list your active directory tenants that you are a Global Administrator (the role column).
I ended up having to create a new MVC app and implement the Authorization Code flow grant, just for the sole purpose of getting the consent windows to pop up so that I could accept the permissions required.
Now Client Credential flow works as per your example perfectly. The takeaway is that the ‘consent’ step is still required for app only permissions, whether you manually consent as I did, or let it happen automatically somehow (which is appears to have done in your case, but I could not work out how).
Sorry for not helping you further as I’m not the expert of AAD. That screenshot was taken from my own tenant, not my company tenant.
Yeah, you’re probably right. I had a quick chat with my colleague about this and he said the same thing. As a “User” role, I can still register apps to AAD. In this case, as you mentioned in your comment, the consent step is required. On the other hand, if I register apps as the “Global admin” role, that consent step would not be necessary.
I might overlook at the additional step as I wasn’t that bothered too much.
Thank you for the sample. very helpful. I am wondering what do I need to do if instead of a mvc application I want this as a rest web service. Is there a east way of converting code to rest webservice. Thanks!
@Newbie Thanks for the comment!
Well, basically there’s no difference between MVP app and Web API app. In terms of authentication, you’ll need to provide both application Id (client Id) and secret key within your code so that you can get an access token for your requests.
Thanks for responding, As my name suggests I am new to programing, your sample perfectly served my purpose of pulling images from office 365 with out user intervention. But this needs to be done in a rest based web service and I am totally confused about code conversion.
Not sure how do I convert mvc controls to regular methods. You help is greatly appreciated.
specially how and where do I bind self signed certificate in a rest web service. Thanks again!