Reputation: 3498
I've setup an App Registration in Azure Active Directory so that I can access Microsoft OneNote notebooks/sections/pages via the Microsoft Graph.
It's allowing pretty much every Microsoft holding account to login, so I'm using https://login.microsoftonline.com/common/oauth2/v2.0/authorize
as my authorisation endpoint and https://login.microsoftonline.com/common/oauth2/v2.0/token
as my token endpoint.
Within the App Registration, I've set API permissions as:
I've added a localhost in my Redirect URIs which is listed as "web", so that i can follow the flow through.
The problem I am getting, is that when I eventually receive my access_token, I receive an error when using it as a Bearer Token against: graph.microsoft.com/v1.0/me/onenote/notebooks
{
"error": {
"code": "40001",
"message": "The request does not contain a valid authentication token. Detailed error information: {0}",
"innerError": {
"date": "2020-10-07T20:37:37",
"request-id": "c8b0c20e-d096-4fcb-9e97-841b1626537c",
"client-request-id": "a-uuid"
}
}
}
So following the flow through, I have something like this:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=99e1fc5a-bl4h-bl4h-bl4h-l0ng3rbl4h&redirect_uri=http://localhost/myapp&response_type=code&scope=https://graph.microsoft.com/User.Read openid offline_access https://graph.microsoft.com/Notes.Read.All&state=abc&response_mode=query
I'm a little unsure if i'm using the correct scope variables here. I want to be able to access all of a users OneNote notebooks/sections/pages and read their profile and do things offline,
http://localhost/myapp?code=M.R3_BL2.15c2b73a-486c-c0f6-95c1-8432603aa7a4&state=abc
code
from the querystring and make a POST like:curl --location --request POST 'https://login.microsoftonline.com/common/oauth2/v2.0/token' \
--form 'code=M.R3_BL2.15c2b73a-486c-c0f6-95c1-8432603aa7a4' \
--form 'grant_type=authorization_code' \
--form 'client_id=99e1fc5a-bl4h-bl4h-bl4h-l0ng3rbl4h' \
--form 'scope=https://graph.microsoft.com/User.Read openid offline_access https://graph.microsoft.com/Notes.Read.All' \
--form 'client_secret=shhhhASecret'
Now this will return me an access_token in some JSON.
{
"token_type": "Bearer",
"scope": "https://graph.microsoft.com/User.Read openid https://graph.microsoft.com/Notes.Read.All",
"expires_in": 3600,
"ext_expires_in": 3600,
"access_token": "EwCQA8l6BAAUO9chh8cJscQLmU+longstring",
"refresh_token": "M.R3_BL2.CecNbvRse*longstring",
"id_token": "eyJ0eXAiOiJKlongstring"
}
However, as stated, this access token doesn't seem to give me access to Microsoft Graph. I've tried different variations on scopes to use in my requests, but none seem to generate the correct access token.
The code I use for calling Microsoft Graph from node.js
const http = require('https');
class OneNote {
constructor(bearer) {
this.bearer = bearer;
this.HTTP_CODES = {
OK: 200,
Unauthorized: 401
};
}
async getNotebooks() {
const options = this._getOptions();
options.path += 'notebooks';
return this._requestData(options)
.catch((err) => {
throw err;
});
}
_getOptions() {
return {
method: 'GET',
hostname: 'graph.microsoft.com',
path: '/v1.0/me/onenote/',
headers: {
'Authorization': `Bearer ${this.bearer}`
}
}
}
async _requestData(options) {
console.log(options)
return new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
let data = '';
res.on('data', (d) => {
data += d;
});
if (res.statusCode === this.HTTP_CODES.Unauthorized) {
res.on('end', () => {
reject(data);
});
} else {
res.on('end', () => {
resolve(data);
});
}
});
req.on('error', (err) => {
reject(err);
});
req.end();
});
}
}
Upvotes: 0
Views: 1310
Reputation: 16498
You probably use a wrong permission(scope).
Based on Permissions for listing notebooks, required permissions for personal Microsoft account are Notes.Create, Notes.Read, Notes.ReadWrite
.
Notes.Read.All
is not required here.
So please add Notes.Read
delegated permission in the scope to fix this issue.
Upvotes: 1