401 Unauthorized on Graph and OneNote API after getting token succesfully - azure-active-directory

I've registered an native app on Azure Active Directory and given all permissions for Graph and OneNote APIs, obtaining tokens succesfully on behalf of users using username and password credentials. I've been able to create and update notebooks and perform other actions on graph using those tokens, but they suddenly stopped working despite no changes to the code making those requests.
I can still do other changes such as creating list items on SharePoint, but any action regarding OneNote notebooks result in 401 with the following response:
{
"error": {
"code": "40001",
"message": "The request does not contain a valid auth token.",
"innerError": {
"request-id": "472a74fd-c050-495a-9ec3-04d1ec3c4461",
"date": "2018-06-26T20:49:28"
}
}
}
I've confirmed the app registration has every permission on both Graph and OneNote APIs
I've confirmed tokens are being requested for the correct resource. In fact I was using Graph, switched to the OneNote API after this problem showed up on Graph, and after a while the same problem happened on OneNote API as well.
I've tried using .NET ADAL AuthenticationContext.AcquireTokenAsync(resource, ClientId, userCredential) or making the request directly to https://login.windows.net/{tenantId}/oauth2/token with the following body and both had the same result
"resource=" + resource
+ "&client_id=" + ClientId
+ "&grant_type=password"
+ "&username=" + Username
+ "&password=" + Password
+ "&scope=openid";
I've tried accessing a notebooks from a SharePoint site open to all users on the tenant and got the same issue, I've tried creating OneNotes on the user personal onedrive and got the same issue, so it's not an issue of the user not having access to the notebook
So, I've made a few dozens of thousand calls on Graph API, then this problem showed up. Another few dozens of thousand calls on OneNote API then this problem showed up. Any ideas of what could be going on? Is there a limit to the number of actions regarding OneNotes that can be made in these APIs?
EDIT : There's two other things I've discovered that are worth mentioning.
The first is that the Graph Explorer was still working normally even while my tokens weren't. I assume the explorer uses authorization code flow to get tokens on behalf of users while I'm using username/password, so the username/passwords authorization flow probably has something to do with the issue. The second thing is that today the Graph API is once again working for OneNote endpoints, which means my app has likely been locked out of making OneNote actions for a time period (24h maybe?)

This also happened to us, I have modified the authentication to below and this authenticates successfully.
$body = "grant_type=client_credentials&client_id=CLIENTID&client_secret=CLIENTSECRET=&resource=https%3A%2F%2Fonenote.com%2F"
$auth = Invoke-RestMethod -Uri 'https://login.microsoftonline.com/TENANTNAME.onmicrosoft.com/oauth2/token' -Body $body -Method post -ContentType application/x-www-form-urlencoded
$accesstoken = $auth.access_token
Just make sure the client id is encoded as it will throw an error if not.

Related

Using Google OAuth with React-Django Application

I am working on a web application with ReactJs frontend and Django backend. In this app, I will need to send calender notifications to the users and overall need a user authentication feature for which I planned to use google oauth. From react, I am able to log in the user and get the access tokens but since they expire in an hour, I planned to get the authorization code and use it to get the refresh/access tokens from the backend whenever a user logs in/needs to send API request. The issue is that I am not able to find any good resource on how to get refresh tokens from the backend given I have the authorization code. Most of the HTTP based methods I have found are very outdated and I have searched some of the google documentation but have not found anything worthwhile. Since I could not find any package that would handle this, I have been trying to send POST request to the URL mentioned here (https://developers.google.com/identity/protocols/oauth2/web-server#python_1) but only get a 400 response. Below are 2 methods I have tried.
to_send={'code':user_data['code'], 'client_id': cl_id , 'client_secret': cl_secret,
'redirect_uri':'http://localhost:3000/', 'grant_type':'authorization_code'}
test=requests.post('https://oauth2.googleapis.com/token', data=to_send)
print(test)
credentials = service_account.Credentials.from_service_account_file('path/key.json')
scoped_credentials = credentials.with_scopes(['https://www.googleapis.com/auth/drive.metadata.readonly'])
authed_session = AuthorizedSession(scoped_credentials)
response = authed_session.request('POST', 'https://oauth2.googleapis.com/token', data = to_send)
print(response)
Ive also tried other things like creating a flow object.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( JSON_PATH, scopes=API_SCOPE)
flow.redirect_uri = REDIRECT_URL
flow.fetch_token(code=user_data['code'])
credentials = flow.credentials
where user_data['code'] is the authorization token and I get the error
oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Bad Request

Getting access tokens from Postman: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests

We recently made a switch from Implicit Grant Flow to Authorization Code Flow with PKCE for our application, and now we're having some trouble getting access tokens from Azure AD from Postman. The app is registered in Azure AD and we're basically using the Postman procedure described here: https://developer.mypurecloud.com/api/rest/postman/index.html#enable_authorization. Calling the https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize endpoint works ok, but it hits an error when calling https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token:
"Error: Cound not complete OAuth 2.0 token request: "AADSTS9002327: Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests.\r\nTrace ID: 8253f622-3425-4d0a-817c-281f86097300\r\nCorrelation ID: 9d84460f-ec02-4ace-af03-14d948e3d4ad\r\nTimestamp: 2020-04-15 14:02:03Z"
This is the access token request:
How can we get access tokens from Azure AD using Postman with this authorization flow?
Apparently this is a problem as the documentation is confusing.
Over the Azure Active Directory App Registration. Make sure you add the redirect url over the "Mobile and desktop applications" category.
When you read the documentation looks like you need to add the Redirect URL under the Single Page Apps. It even shows confirmation message saying "Your Redirect URI is eligible for the Authorization Code Flow with PKCE." but is not true.
This error can occur when the "Origin" header is missing from the request (see: GitHub comment).
Try adding the header:
Origin: http://localhost
If you're experiencing this failure whilst trying to authenticate using Postman, ensure that you have a platform authentication for Web.
Go to Azure AD > App Registrations > {your app reg} > Authentication > Add a platform. Redirect URI should be https://oauth.pstmn.io/v1/callback when using the browser.
For me I was trying update the MSAL v1 implementation to v2 implementation where I got this issue. After doing migration from web to SPA in the Azure where it clearly takes about the same fixed my issues.
https://learn.microsoft.com/en-us/answers/questions/315313/azure-app-registration-causing-the-following-error.html
https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-browser#implicit-flow-vs-authorization-code-flow-with-pkce
To get an refresh_token you have to add "offline_access" to the scope.
The documentation of the response to the access token request says:
An OAuth 2.0 refresh token. The app can use this token acquire additional access tokens after the current access token expires. Refresh_tokens are long-lived, and can be used to retain access to resources for extended periods of time. For more detail on refreshing an access token, refer to the section below.
Note: Only provided if offline_access scope was requested.
Documentation
I was able to resolve this by doing the following:
Within the Azure Portal:
Navigate to the App Registration that you are using for your protected API.
Next, navigate to the Authentication blade within the Manage menu.
Within your Single-page application platform, add the following Redirect URI, https://oauth.pstmn.io/v1/callback.
Save these changes within the Azure Portal.
Next, within Postman's New Token Configuration:
Manually set the Callback URL to the same URI specified above (i.e. https://oauth.pstmn.io/v1/callback).
Once the above are done, clear your cookies from within Postman, and re-attempt retrieval of the token.
Follow these steps:
In your registered app, add platform for mobile and desktop application like below image:
Get your code which will be redirected to https://login.live.com/oauth20_desktop.srf?code=<code>.
If you are using Postman to get token so cross origin issue chances can be there. So try below php code to get token:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://login.microsoftonline.com/{tenenat-id}/oauth2/v2.0/token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"grant_type=authorization_code&code={auth-code}&client_id={client-id}&scope=https%3A%2F%2Fmanagement.azure.com%2F.default&redirect_uri=https://login.live.com/oauth20_desktop.srf");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);
var_dump($server_output);
1.You should first get the code in the browser,Enter the following request information in the browser address bar:
2.Then enter the obtained code and other request information in postman, you will get the access token
3.Please check: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

Azure Active Directory Authorization Token Has Expired

We are working on a custom connector for Power Apps. This connector basically uses post, get, patch, delete methods of the Dynamics Rest API. For authentication, we are using AAD as mentioned.
We are writing swagger JSON and uploading the file to create/update the custom connector, after which we have to provide CRM URL, Client ID, and Client Secret.
Everything was working smoothly until the custom connector started throwing error that the authorization token has expired.
{
"status": 400,
"source": "https://unitedstates-002.token.azure-apim.net:443/tokens/unitedstates-002/-5Ftest-20final-5Fc8793734b9d234d8-5F1ae6317311eb737e/a6bf39bb183d4f89870ba39642194dbe/exchange",
"message": "Error from token exchange: Bad authorization token. The access token has expired."
}
This error went away after we recreated the custom connector using the same swagger JSON without any change.
How can we avoid this error without needing to recreate the connector every time? Is there anything we are missing regarding to AD Tokens?
You can set the token lifetimes as per the documentation.
Please see here for more information:
Configurable token lifetimes in Azure Active Directory
Edit: This is apparently being deprecated May 1, 2020, but you should call for a refresh token if the token you currently have has expired.

Delete groups in Microsoft Graph API in C#

I get an authorization 401 error code when I try to delete a Group from the API in C# but if I try it in postman it succeeds. Feels kinda weird because I run the same command but it doesn't work...
The problem I think I have is that to DELETE a group in Office 365 I need to login to my account and that the application can't makes this action.
I gave all Group.ReadWrite.All access and all other permissions for the application. So I think I need to pass my Login credentials for Azure AD or am I incorrect.
Request :
StatusCode: 401,
ReasonPhrase: 'Unauthorized',
Version: 1.1,
Content: System.Net.Http.NoWriteNoSeekStreamContent,
Headers:
EDIT
I tried to not use my GetAccessToken() and use the token I got when using OAUTH 2.0 verification in Postman. If I took that bearer token I had no problem running my script and using DELETE.
So my question what the difference of using ADAL in C# code and the call that Postman Auth2.0. When using Postman I get a login page where I login to my Azure account, can I replicate this in code? For the authentication in C# I use this example.
NEW EDIT
As one wrote in the chat, I checked the access token and what roles I had on a website.
roles: [
"EduRoster.Read.All",
"Mail.ReadWrite",
"User.ReadWrite.All",
"Calendars.Read",
"People.Read.All",
"Group.Read.All",
"Directory.ReadWrite.All",
"MailboxSettings.Read",
"Contacts.ReadWrite",
"Group.ReadWrite.All",
"Notes.Read.All",
"Directory.Read.All",
"User.Read.All",
"Mail.Read",
"Calendars.ReadWrite",
"Mail.Send",
"MailboxSettings.ReadWrite",
"Contacts.Read",
"Member.Read.Hidden",
"Notes.ReadWrite.All"]
Some clarification: If you have a token and it doesn't have the necessary claims/permissions to make the API call you are trying, you'll should get a 403 Forbidden. If the token is missing in the API request or malformed, you'll get a 401 Unauthorized. Please see https://developer.microsoft.com/en-us/graph/docs/concepts/errors.
Are you making direct HTTP REST calls to Graph, or are you using the client library? I suggest that you look at some of our samples to get started for examples of token acquisition together with calls to Microsoft Graph. Try https://github.com/microsoftgraph/console-csharp-snippets-sample (uses a .Net client library) or https://github.com/microsoftgraph/aspnet-connect-rest-sample (uses direct HTTP REST calls).
Also are you acquiring a token in the context of a (signed-in) user, or in the context of the application (no signed in user)? If the former, you need to request a "delegated" permission. If the latter, you need to request an "application" permission. Please see these concepts: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user and https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
Hope this helps,
You're on the right track.
The Delete Group method support both Delegated (Authorization Code or Implicit OAUTH grants) and Application (Client Credentials OAUTH grant) models. Both Delegated and Application flows require the Group.ReadWrite.All scope.
The reason you're getting a 401 Unauthorized error is that your application hasn't received Admin Consent for the tenant you're connected too. When using Client Credentials there is no User to authenticate so before your application can interact with the tenant, an Admin must first explicitly authorize your application and the scopes you're requesting.
You can find a walk through at v2 Endpoint and Admin Consent.

How to check other user availability with Microsoft Graph API?

I'm trying to implement checking availability for specific user (actually a room) in O365 calendar. I'm using Graph API as it's recommended by Microsoft.
My first approach was using POST on https://graph.microsoft.com/v1.0/me/findMeetingTimes with the message body prepared according to template given in Graph API Explorer. On the API Explorer everything seems to work fine but when I try to run exactly the same request with my applications token I receive 403:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "b130177d-e138-4cc7-8e72-5d3529a9dc24",
"date": "2017-03-21T08:47:10"
}
}
}
I checked the app's delegated permissions in AAD and they seem to be fine. For Microsoft Graph those are granted:
Calendars.ReadWrite.Shared
Calendars.Read.Shared
Calendars.ReadWrite
Calendars.Read
I get exactly the same response (403) when I try to simply list user's events: https://graph.microsoft.com/v1.0/users//events In Graph API Explorer 500 is returned.
I found the following bug description: https://github.com/microsoftgraph/microsoft-graph-docs/issues/559 (and probably this one too) Is it related with the issues above?
Any clue what I might be doing wrong?
Is there any other way to achieve the same using different endpoint or API assuming that I still want to use oAuth for authorization?
I will be grateful for any hint
Update: Outlook Calendar API seems to work. Still appreciate any ideas why Graph API doesn't?
The FindMeetingAPI needs A work or a school account . If you are logging in using your personal email ID , you might not be able to login. Moreover , you need to set permissions to Calendars.Read Calendars.Read.All Calendars.ReadWrite User.Read"

Resources