OAuth 2.0 to access Microsoft APIs

Shivam Garg
6 min readApr 1, 2021

I have used OneNote Apis to migrate my Google Keep notes to Microsoft OneNote.

What is actually happening in OAuth Authorization Process?

So the process involves following steps,

  1. A consent window pops up, Where you request the user to give her consent and ask the Microsoft server for an authorization code.
  2. Microsoft sever returns the Authorization code.
  3. You use Authorization code, Client_id, etc to ask for Token.
  4. Microsoft sever returns the Token.
  5. You use that token to make the API call to the Microsoft database.
  6. Microsoft database returns the data.

After Sometime when the token expires,

  1. You can use Refresh_token to ask for the new token.
  2. Microsoft server returns you a new token.
  3. You use that token to make the API call to the Microsoft database, and the Microsoft database will return the data.

How to use OAuth in your application?

  1. firstly, register your application on the Microsoft Azure portal.
  2. Then, Authenticate the user.
  3. Then, Make the API calls.

# Registering your application on Microsoft Azure Portal

So everything starting with registering your application on Microsoft Azure Portal, for this you must have an account on the Azure portal. Register for a free trial, or opt of as pay per use basis. So moving on to the process of registering your app. Visit here to register your app.

  1. From all the services listed select App Registration

2. By clicking on + New Registration You will be prompt with a window asking for few details, like the type of account, redirect URI, etc.

3. What you want your app name to be? What kind of users can access your App? What's the redirect_uri?

a. Type in a name,

b. There are 4 types of accounts supported,

  • Accounts in your internal Organisational directory, (single-tenant)
  • Accounts in any organizational Directory, (multi-tenant)
  • Account in any Organisational Directory + Personal account, (work, School accounts, or personal account)
  • Personal accounts only (single user account)

when you’re developing an app to access a single user’s account to provide him services, select Personal accounts only.

c. Redirect URI, For a Web-based Application, You need to specify a redirect_uri where the Microsoft server can return the authorization code.

After submitting this form you’ll be redirected to a Dashboard Overview, with the following list of option in the sidebar,

# what could be found in each section?

  1. Overview, is just a Dashboard.
  2. QuickStart, Documentation for the type of app you are building.
  3. Integration Assistant, assisting with a requirement for the type of app you’re creating.
  4. Branding, Adding Business details of your app.
  5. Authentication, edit redirect_uri. And If you’re using implicit flow, you’ve to check it here.
  6. Certificates & Secrets, You’ll be creating a client_secret here. Remember to copy the value of client_secret, You won’t be able to retrieve it after you leave this page.
  7. Token Configuration, I haven’t done anything here.
  8. API permissions, Add all the permissions that your application needs.
  9. Manifest, at the end of the list this tab contains the configuration of your app in JSON format.

Now after finishing with setting up your app on the portal, You’d need only Client_id, Client_secret, tenant_id and store them in a file where you’re developing your application.

# Okay, so the first thing to do is authenticate your user,

Redirect User to https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize? and providing Request Option like Client_id, Redirect_URI, etc. in the query parameters, like shown in the image below.

To check for what scope you need see the reference at the bottom.

let url = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?"const scope = "Notes.Create Notes.Read Notes.Read.All";const options = {
client_id: cred.clientID,
response_type:"code",
redirect_uri:config.redirectUri,
response_mode:"query",
scope:"offline_access " + scope,
state:123,
prompt:"consent"
}
url = url + querystring.stringify(options);
// URL will become something like that
//https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=1234abcd-1234-1234-abcd-abcdbdaeaa5&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fcode&response_mode=query&scope=offline_access%20Notes.Create%20Notes.Read%20Notes.Read.All%20Notes.ReadWrite%20Notes.ReadWrite.All%20User.Read&state=1&prompt=consent

This will provide the user with a Consent screen, where they will give their consent to the application to use their MicroSoft account.

Then Microsoft server will return a response with either an error message or code along with scope as a query parameter in the redirect URI. Example: http://localhost:8000/auth/code?code=M.R3_RAY.12345678-6f2b-d5b4-5dc5-69fa0b4716a2&state=123

Now use this code to make a Post API call to https://login.microsoftonline.com/consumers/oauth2/v2.0/token?

Here, data passed in Body must contain the code that we get by previous call, Client_id, Client_secret(that we get from azure portal), Redirect_URI, and Grant_type.

In grant type its specified, what kind of credentials are being used to get the access token for the User’s data. Here, I am using authorization code to get the access token. Hence, I am specifing that.

const url = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token?";const scope = "Notes.Create Notes.Read Notes.Read.All";const data=  querystring.stringify({
grant_type: "authorization_code",
code: req.query.code,
client_secret: cred.clientSecret,
client_id: cred.clientID,
scope,
redirect_uri: config.redirectUri
})
const headers= {
"Content-Type": "application/x-www-form-urlencoded"
}
let token_object = await axios({
method: "post",
url,
headers,
data
})

This will return you a response which would look like this,

{
token_type: 'Bearer',
scope: 'Notes.Create Notes.Read Notes.Read.All',
expires_in: 3600,
ext_expires_in: 3600,
access_token: 'EwCAA8l6BAAU6k....',
refresh_token: 'M.R3_RAY....'
}

Now you can simply hit OneNote APIs by using This access_token, and save refresh_token in separate file, it will be used to ask for new token later.

await fse.writeJSONSync("./Cred/refresh_token.json", tokenObject.data.refresh_token);

# After Some time when the token expires use the refresh_token to ask for a new token,

You need to make a Post request on the same URL, that is, https://login.microsoftonline.com/consumers/oauth2/v2.0/token? with the same Headers, but the body a little bit changed as shown below.

Here, data passed in Body must contain the refresh_token ( that we get when we get the access_token by using autherization_code), Client_id, Client_secret, Redirect_URI, and Grant_type.

Here, I am using refresh_token to get the access_token. Hence, I am specifing that in grant_type.

const url = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token?";const refresh_token = await fse.readJson("./Cred/refresh_token.json");const scope = "Notes.Create Notes.Read Notes.Read.All";const data=  querystring.stringify({
grant_type: "refresh_token"",
refresh_token,
client_secret: cred.clientSecret,
client_id: cred.clientID,
scope,
redirect_uri: config.redirectUri
})
const headers= {
"Content-Type": "application/x-www-form-urlencoded"
}
let token_object = await axios({
method: "post",
url,
headers,
data
})

And the response you’ll be getting this time will also be a bit different, but it will contain your new access_token. But there won't be any refresh_token in this response, so keep this refresh_token safe.

{
token_type: 'Bearer',
scope: 'Notes.Create Notes.Read Notes.Read.All',
expires_in: 3600,
ext_expires_in: 3600,
access_token: 'EwCAA8l6....',
}

--

--