Apr 10, 2018

Connecting to Microsoft OAuth 2.0

Connecting to OAuth 2.0 authentication might be a common and critical task to do for many developers, especially in Microsoft Office 365 environment. It could be a connection to OneDrive, Excel, SharePoint, OneNote, even the big developer platform such as Microsoft Graph. It could be connecting to any other cloud app services such as twitter, facebook, google, pinterest, or any other cloud services in this world.

You can take a look to find out how we deal with Microsoft OAuth 2.0 authorization code is retrieved and how the flow works for you at: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-code.

In practical way, you can follow my step-by-step below if you find the article is not clear enough or lack of examples. This article will be focusing on Microsoft Online credential which can be used with Azure Active Directory or Microsoft Online account.

finger-769300_640


Registering Your App

Before you can make connection to any cloud services using OAuth 2.0, you would need 2 things, Client ID and Client Secret. Anything that connects using OAuth 2.0 is considered an app, and you need to register that before proceeding. This will usually generates you a Client ID and commonly with Client Secret, which acts same like your own username and password.

There are 2 ways to register your app. Firstly, registering via Azure Active Directory. This action can only be done via Azure Portal and you might need to check with your organization’s admin to do so.


Secondly, you can register via Apps Registration Portal. If you are planning to use any of the Office 365 services such as Microsoft Graph, you can only use Microsoft Online account (Work or School account).

Now, keep safe the Client ID and Client Secret.


Authorize: Retrieving Authorization Code

The first step to authenticating yourself is to authorize you. The easiest part is to run the query to authorization URL. You can run in any browser the following URL. It’s segmented so you can see different section of the URL.

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=<YOUR_CLIENT_ID>&
client_secret=<YOUR_CLIENT_SECRET>&
response_type=code&
response_mode=query&
redirect_uri=<YOUR_REDIRECT_URI>&
scope=<YOUR_SCOPE_OR_ACCESS>

You can provide your Client ID and Client Secret accordingly to the URL. You need to provide your Redirect URI which you have configured in the previous steps.

Lastly, the scope is something you need to know of what is your access. Scope is space delimited information. If your application is not expecting user to login every time your app need access, you can put offline_access to the scope.

For Microsoft Graph, you will need to add https://graph.microsoft.com/ to each of the permission you would like to add. For example, if you want permission to read the current user’s profile, your scope would be https://graph.microsoft.com/user.read. For your information, user.read is the most basic permission you need to get.

The complete reference of the permission is stated in this article: https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference.

For example, this is my application’s authorization URL as stated below.

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=665cdc2c-19bf-4b56-afbd-a3da0e4dfd42&client_secret=sfbSDX121%5D!%3ArsydZXGH06!&response_type=code&response_mode=query&redirect_uri=http%3A%2F%2Flocalhost&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read.all%20https%3A%2F%2Fgraph.microsoft.com%2Fsites.readwrite.all%20https%3A%2F%2Fgraph.microsoft.com%2Ffiles.readwrite.all%20offline_access

Once I pasted into any browser’s URL, I will be prompted to login into my account. Please bear in mind that the account you’ve used to register your app and the account you are using now to authorize, may not be the same. This is like vendor-customer relationship, where vendor provides the app and customer is the one consuming the app. When your customer given access to your app, it doesn’t give your account access automatically but just the app created by you.

image

image

That is what your customer will see during the login and authorization process. Once you click Accept, you will be redirected to redirect URL. In my case, it’s an error because my redirect URL is just http://localhost.

image

But if you notice in the address bar, you will get code directly in the URL. This is your authorization code.

http://localhost/?code=OAWSBAAIAAABHh4kmS_aKT5XrjzxRAtHzetylGZkgFOVlJD1Smtz4p5BmjDsr-KuyCUVdLxi7ThS62ZSCfQE5Qx7L4SK6g_jncSHSPTu8i6hk8jvL-vZFhZe2TiUKB4VtFz9NEZ3Nj5oFOy0m2U6KuDdYRJQRUZXZP173s2bUNYRnv6gwy3aBbM7Oy9CRAPs0oeJPFaiarw0WnOOPrqGEFAJuswi3EQlNdHLHh7ahAZ0PvA2BJ8kNi173wOpgZ00wl2zFKHjvZLk_lw-Hfmk0YtHfan3URnped_qp8YRVw__MJj7S9k8M_zULmI_Ak_zR26DJGqpLkHPlpzvyvjRokatP5tlZme9AUHHlemCeT8tvbYL3Fsxz4VirqYrCuGs4jhr24i1AnVn5OcN8cSfbUr_d9BVt5L8SuO25MT8U6Gl5H_jKhEitybrjAJDC311F8tvSCusLuAN8PAR2KZk8E-o_BVPJiM23NLlenccaMdIlxtDGumJjIToyE-jEKbfdlmhIofUgTz5yDCJ2YGYDeJY_IWS0T4f055zTEBNB3nv4TxKV2dsOAhd-1tbOS8H-dExTXKQtfA0XW72sfT8kAfiw8sapg3n-0ZWTWD5imzFnZi8tAKH2c1JcKtXZvrXJPDVbS64hFzetrHJwLeJtU9lZDPx_4XS7pHbnSS757N_ZhKZRkxztcaFy_1NgC-pylyJwxYBz450gAA&session_state=267bdefa-b3b1-49bd-adf0-893e7c0ba659

Keep it safe, now we are going to retrieve token with this code.


Token: Retrieving Refresh Token and Access Token

If the nature of your application is always requesting access even when user is not connected, you don’t need Refresh Token. But if you need (for example to be used in Nintex Workflow or any application that always running in the background), you will need Refresh Token. You will get Refresh Token, only if your scope in the earlier process is set to offline_access.

Access Token is the limited time token you need to access the resource. Refresh Token, is the token to refresh the Access Token when it got expired. You can read the specifications here: https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/.

To get token, you can use online tool like Swagger or you can download Insomnia. This is due to the token URL doesn’t accept GET method unlike authorize URL above. For Swagger, you can put the type of request to POST, and paste down the following endpoint.

https://login.microsoftonline.com/common/oauth2/v2.0/token.

Then on the Authentication & Headers, I need to define 2 things. I set authentication to No Authentication. Then I need to define the headers such as below.

Content-Type application/x-www-form-urlencoded
Accept application/json


On the Body, reconstruct the information below.

client_id=<YOUR_CLIENT_ID>&
client_secret=<YOUR_CLIENT_SECRET>&
grant_type=authorization_code&
redirect_uri=<YOUR_REDIRECT_URI>

In my case, I got this information ready as below.

client_id=665cdc2c-19bf-4b56-afbd-a3da0e4dfd42&client_secret=sfbSDX121%5D!%3ArsydZXGH06!&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost&code=OAWSBAAIAAABHh4kmS_aKT5XrjzxRAtHzetylGZkgFOVlJD1Smtz4p5BmjDsr-KuyCUVdLxi7ThS62ZSCfQE5Qx7L4SK6g_jncSHSPTu8i6hk8jvL-vZFhZe2TiUKB4VtFz9NEZ3Nj5oFOy0m2U6KuDdYRJQRUZXZP173s2bUNYRnv6gwy3aBbM7Oy9CRAPs0oeJPFaiarw0WnOOPrqGEFAJuswi3EQlNdHLHh7ahAZ0PvA2BJ8kNi173wOpgZ00wl2zFKHjvZLk_lw-Hfmk0YtHfan3URnped_qp8YRVw__MJj7S9k8M_zULmI_Ak_zR26DJGqpLkHPlpzvyvjRokatP5tlZme9AUHHlemCeT8tvbYL3Fsxz4VirqYrCuGs4jhr24i1AnVn5OcN8cSfbUr_d9BVt5L8SuO25MT8U6Gl5H_jKhEitybrjAJDC311F8tvSCusLuAN8PAR2KZk8E-o_BVPJiM23NLlenccaMdIlxtDGumJjIToyE-jEKbfdlmhIofUgTz5yDCJ2YGYDeJY_IWS0T4f055zTEBNB3nv4TxKV2dsOAhd-1tbOS8H-dExTXKQtfA0XW72sfT8kAfiw8sapg3n-0ZWTWD5imzFnZi8tAKH2c1JcKtXZvrXJPDVbS64hFzetrHJwLeJtU9lZDPx_4XS7pHbnSS757N_ZhKZRkxztcaFy_1NgC-pylyJwxYBz450gAA

Then click Send button.

You are probably spent too much reading this article if you get this response just like below.

{
    "error": "invalid_grant",
    "error_description": "AADSTS70002: Error validating credentials. AADSTS70008: The provided authorization code or refresh token is expired. Send a new interactive authorization request for this user and resource.\r\nTrace ID: 0296e013-d1b7-495c-a563-0474edb70500\r\nCorrelation ID: 904d52ff-61e7-46d8-be2b-f7bd4411e63b\r\nTimestamp: 2018-04-11 02:26:38Z",
    "error_codes": [
        70002,
        70008
    ],
    "timestamp": "2018-04-11 02:26:38Z",
    "trace_id": "0296e013-d1b7-495c-a563-0474edb70500",
    "correlation_id": "904d52ff-61e7-46d8-be2b-f7bd4411e63b"
}

That means you will need to go to authorization process once again to refresh your authorization code. Otherwise, you should get this response just like below.

{
    "token_type": "Bearer",
    "scope": "https://graph.microsoft.com/Files.ReadWrite.All https://graph.microsoft.com/Sites.ReadWrite.All https://graph.microsoft.com/User.Read https://graph.microsoft.com/User.Read.All",
    "expires_in": 3599,
    "ext_expires_in": 0,
    "access_token": "eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCSGg0a21TX2FLVDVYcmp6eFJBdEh6Mzd0WXFZbDFrR3ZzLU5NcElmZ0dGTUhxYTFjUC1WYlFBV3c0MWg1WjI3cDJnbGstWWc1bVl5amEzOGgyYmM0TFNoX3RCQkJneVBwaVpQeHptQmFwQ1NBQSIsImFsZyI6IlJTMjU2IiwieDV0IjoiRlNpbXVGckZOb0Mwc0pYR212MTNuTlpjZURjIiwia2lkIjoiRlNpbXVGckZOb0Mwc0pYR212MTNuTlpjZURjIn0.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC84YjhmNWY4NS0xNjM4LTQwNmItODFlOC0yNjJhMmIzZjhhNmYvIiwiaWF0IjoxNTIzNDE0MjY5LCJuYmYiOjE1MjM0MTQyNjksImV4cCI6MTUyMzQxODE2OSwiYWNyIjoiMSIsImFpbyI6IlkyTmdZUGhhd3F4NmJMT28yNUxBV1hMYjJWY0dLdHo4d2ZDNTRPWFRQL3o1dHlUWjNVd0IiLCJhbXIiOlsicHdkIl0sImFwcF9kaXNwbGF5bmFtZSI6Ikluc2lnaHRTRy5vcmcgaVdlYiIsImFwcGlkIjoiODc0Y2RjMmMtMTliZi00YjU2LWFmYmQtYTNkYTBlNGRmZDQyIiwiYXBwaWRhY3IiOiIxIiwiZmFtaWx5X25hbWUiOiJBcmRpIiwiZ2l2ZW5fbmFtZSI6IlJhZGl0eW8iLCJpcGFkZHIiOiIxMTguMjAxLjExNi4zOCIsIm5hbWUiOiJSYWRpdHlvIEFyZGkiLCJvaWQiOiI4ZTNlODI0Yi0xZThlLTQ1OWEtOTRmZC03MzUxMWRhYTliMmQiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzNGRkZBNEMwOTg5NSIsInNjcCI6IkZpbGVzLlJlYWRXcml0ZS5BbGwgU2l0ZXMuUmVhZFdyaXRlLkFsbCBVc2VyLlJlYWQgVXNlci5SZWFkkwdsbCIsInNpZ25pbl9zdGF0ZSI6WyJpbmtub3dubnR3ayJdLCJzdWIiOiJ2VFFnc2F6NUJZZUtoRHozTkliRDNVRDBPWTdWSmpybzhHa0dDX3R4dTg0IiwidGlkIjoiOGI4ZjVmODUtMTYzOC00MDZiLTgxZTgtMjYyYTJiM2Y4YTZmIiwidW5pcXVlX25hbWUiOiJyYWRpdHlvLmFyZGlAaW5zaWdodHNnLm9yZyIsInVwbiI6InJhZGl0eW8uYXJkaUBpbnNpZ2h0c2cub3JnIiwidXRpIjoiZ3pVYUZ0UFdWRS1IeGpoM0lvSUdBQSIsInZlciI6IjEuMCIsIndpZHMiOlsiNjJlOTAzOTQtNjlmNS00MjM3LTkxOTAtMDEyMTc3MTQ1ZTEwIl19.pJx3sb_HVBP3i-yw1k5R0WKO13n0KIIl8V63nGj4ZOyCggVgmCC6oGvmkN3Zb1uUJmLV9n0uC9E34rrU4d7q_VWivSj9ObaF0-GJvnsSB6mZdEVCz4caELg_k8wGiuQH5hFT7LfCCxDPUSSVn3HsL-X90zdQNSc23ck7OTIXu1wswFLj5707X8Om5q3pN4X8HT49lEpyhR1fAhLLoeJ3iNad0CHrISGcsnY9_RG88vTUmKrDHb41pSEaCqcxh65mV9Cz31SyA_6aO3Dk9DRNT0uQ6BNsDCUKzM9deBBuTkQBcIo5Lq-l9mZxSeeZnvLJjULHzclO7DTjqQ2-z0vTGw",
    "refresh_token": "OAQABAAAAAABHh4kmS_aKT5XrjzxRAtHziijDNrnmVHPJtapQL8E-H84NjSZnHYCq8fFqD6Ahska-7SoGIblWIKWrR732svxflATCV1onNSA3PWgJtH2BK6vmuXxWFtpLMtWxle61s9O5FiibY9eqkAyP3TixgfP-HdQZNUkSoJlQ4zn4In91HAXWa_Ms8LXkYI_xcbQJA4vVyvt4pJWofh8daFceHblKoxQnxS3GTouI6QBYaUbRhF0idPNJBbButwHos1klYHFQCkYwjjWT69yR1mT0Q9LLxn_RFHeUMXfVkXJtEygAEf0tKHb0rH3cSrviuRWVw3p8_aJ6vBy7htzsX40-BJKGRL7c3EMtsbNPSLaRLOxVcP-kuwDqmG4bN7xCfttzY-Oh3uyMIExvzkCmA1gVdrCARUhD0VbbqlZoAL81aE6XTsVdT0ZBYY36uX-11ioFpheG9euHUQedZ38BbPewTyzXIHkgxVFf1VqH6FKrCrG9qyG3TN8LLWFUXJ-joiX1uvYljKzJv41hGJToqooup9GlCUUPNVPoP1AjLJ7MTu6iqffC0Dufzu5WLXG1zgW7gdoSMEu5s_c1waSAz5QZvjXkNN0oJ0YQS3OxR9bAEWvdcAHp48B12Hmi6cjGrjbchcWi87mbe_zD3XrLqKWs0NAxVpyZ9-tkwhpzOfgOEntnKxzc5J79g1Q_Zr5C67BTY3D22PB_Sf3NLS3p-EKvHtQJb7aeCsNAhRZONeF-XQJfW-Ta96AN2MzZfQyCJ6cUmM3DX-CJNlqNb3zftjR4Hfgk2vpC4IVVjFzbOSWEEHx7nCAA"
}

Now, basically you can use the access_token to access the resource you need for your application!


Using Access Token in your application

Now that you need to access the resource with your application, you need to add one more header: Authorization.

Content-Typeapplication/json
Acceptapplication/json
AuthorizationBearer <access_token>


Refreshing Access Token

When your access token expires, you need to refresh it. You will get response just like below.

{
	"error": {
		"code": "InvalidAuthenticationToken",
		"message": "Access token has expired.",
		"innerError": {
			"request-id": "f25d5237-1153-4a87-b721-46b8308015ce",
			"date": "2018-04-11T06:43:31"
		}
	}
}

To refresh, it’s practically almost the same when you are trying to get access token itself. You need to run POST method on the following endpoint.

https://login.microsoftonline.com/common/oauth2/v2.0/token 

Go with the following Header below.

Content-Typeapplication/x-www-form-urlencoded
Acceptapplication/json

And with the following Body.
client_id=<YOUR_CLIENT_ID>&
client_secret=<YOUR_CLIENT_SECRET>&
grant_type=refresh_token&
refresh_token=<YOUR_REFRESH_TOKEN>&
redirect_uri=<YOUR_REDIRECT_URI>


That’s all folks and happy authenticating! Open-mouthed smile