What Scope and or resource to set to get token that works with office 365 api? - azure-active-directory

We have acquired the Admin consent in both delegated and application ServiceHealth.Read permissions in Office 365 Management API for our Client app in Azure AD.
We are unable to figure out what the scope and or resource needs to be in token acquisition process if we want to make calls to the office365 management api.
Whether its the client_credentials grant method of direct token acquisition
Or the authorization code then token for signed-in user method
It would be preferable if its for the client_credentials grant method, but if it has to be through auth code, that's fine too.
We can use the following already to grab our reports but do not know how to allow that authentication to also cover Office365 Management API Service Health
curl --location --request GET "https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data "client_id={clientid}&client_secret={clientsecret}&scope=https://graph.microsoft.com/.default&grant_type=client_credentials"
When adding ServiceHealth.Read to the end or by itself it returned invalid_scope as an error
When place only https://manage.office.com/ServiceHealth.Read/.default in the scope it gives the error invalid_resource with the description including that the resource not found in tenant
A similar problem occurred when trying to get the authorization code and setting the resource as ServiceHealth.Read and while setting that as the scope instead gave a authorization code, the resulting token was deemed invalid.

Authorization Code Grant Flow
I quickly tried this out with an Azure AD app registration that has ServiceHealth.Read delegated permission for Office 365 Management APIs.
Scope value used - https://manage.office.com/ServiceHealth.Read
I was able to successfully get back an access token following the Authorization Code Grant flow. I'll share the detailed request parameters passed shortly, but this should answer your direct question about what scope value to use.
Since I used Azure AD V2 endpoints, I didn't really need to specify a resource. In your sample requests mentioned in question I see that you are also using Azure AD V2 endpoint.
Detailed steps
Step 1 - Get the Authorization Code
For this step, I directly used browser and then sign in using a valid user from my Azure AD tenant.
// Line breaks only for clear reading. Remove line breaks and paste in browser URL to test.
https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?
client_id=29a95b.....
&response_type=code
&redirect_uri=https://rohitapp/
&response_mode=query
&scope=https://manage.office.com/ServiceHealth.Read
&state=12345
Response should be something like
https://rohitapp/?code=
OAQABAAIAAACQN9QBRU....
&state=12345&session_state=f5da06....
Step 2 - Acquire Token from token endpoint
Take the Authorization code from last step.
For this step I used POSTMAN. You can use CURL as well.
POST https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Request Body
client_id=29a95b....
&scope=https://manage.office.com/ServiceHealth.Read
&code=OAQABAAIAAACQN9QBRU....
&redirect_uri=https://rohitapp/
&grant_type=authorization_code
&client_secret=Aj....
Final Token received, decoded in https://jwt.ms
Client Credentials Grant Flow
Scope value used - https://manage.office.com/.default
I did add the related app permission and give consent for it.
For this one I used POSTMAN again. You can use CURL as well.
POST https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Request Body
client_id=29a95....
&scope=https://manage.office.com/.default
&grant_type=client_credentials
&client_secret=Aj....
Final Token received, decoded in https://jwt.ms
Take a look at this Microsoft documentation around scope value for Client Credentials Grant.

Related

How to get data from Microsoft Bing Ads API

I'm trying to get Bing ads spends from my firm. According to the Microsoft documentation, I understood that it's mandatory to use Microsoft Azure portal, get developer_token, client_id, tenant_id, client_secret, and access/refresh token to download the csv files with the data I want.
So, this is what I did:
I've received an invitation from my firm to Microsoft advertising onto this email adress:
abc#myfirm.fr, and I've generated my developer token.
With this email address, I've created a web application onto Microsoft Azure portal, which allow all king of users. Getting client_id, tenant_id, and generated a client_secret.
The redirect URL that I have chosen is http://localhost (according to the documentation but not sure this is the good URL to choose).
With Postman, I have tried with this endpoint:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
and the params (previously obtained) needed for the OAuth 2.0 authentication to get my access token. Without success.
The issue is here.
When I request the access token, a new browser window opens, and asks for an email address on which to authenticate. I'm using my email address abc#myfirm.fr and I received authentication completed onto Postman but into the response body I have access_token: invalid.
The role of my account is super admin.
So I'm trying to authenticate with a professional Microsoft Azure Account and this time I received into the browser Invalid redirect url.
I have also tried to start all over again with different email address, like my personal email address, or with the email address of the creator of the Microsoft Advertising account, and I get the error contact your system Admin into the browser.
I have also tried with the Python SDK project given in the documentation, with the error message.
I must have forgotten or misunderstood something.
Should we use the same email address (or same account) on Microsoft Advertising, on Microsoft Azure, and when obtaining the access token?
Do you have to pay and take an Azure subscription? (Already done but without success)
Thanks in advance, sorry for my English.
EDIT:
Thank for ypur reply. The full request is: https://login.microsoftonline.com/common/oauth2/v2.0/authorize with the following params:
-type: OAuth 2.0
-Header Prefix: Bearer
-Grant Type: Authorization Code
-Callback URL: https://localhost
-Auth URL: https://login.microsoftonline.com/{my-tenant_id}/oauth2/v2.0/authorize
-Access Token URL: https://login.microsoftonline.com/{my-tenant_id}/oauth2/v2.0/token
-my client id
-my client secret
-scope: https://ads.microsoft.com/ads.manage OR also testing with https://graph.microsoft.com/User.Read
-State: None
-Client authentication: send client credentials in body
Give me an access_token but when I click on use token and send the request, I'm not getting an refresh token
Once a user provides consent, you can get an access token and act on behalf of the user.
So when the browser session starts, you should enter your Microsoft Advertising credentials.
Remember to set scope=https://ads.microsoft.com/ads.manage in the request for acquiring the authorization code.
If you prefer to automate this process, you can refer to this script and steps to obtain an access token.

invalid_grant error when obtaining access token

I am trying to build a website where a user can log in via Azure AD B2C. After logging in, I'm trying to present a secure area where the user can change their Azure B2C user attributes (first name, last name, etc) via the Microsoft Graph API.
I am attempting to follow along with the Get a Token documentation
Everything is working up to step #3, where a call gets made out to https://login.microsoftonline.com/common/oauth2/v2.0/token to obtain an access_token using the code I received on my return URL.
Here's the general flow of what I am doing:
End user clicks a login link on my localhost site that links out to my Azure B2C tenant policy. Link looks something like this:
https://login.microsoftonline.com/mytenantname.onmicrosoft.com/oauth2/v2.0/authorize
?client_id=[MyAppID]
&response_type=code+id_token
&redirect_uri=http%3A%2F%2Flocalhost%3A17000%2Fprocessing%2Findex
&response_mode=query
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.write
&state=[MyCustomState]&p=[MyCustomPolicy]
User logs in and gets redirected to the redirect_uri.
redirect_uri successfully recieves code, id_token, and state values.
I take the code value from that and makes a POST https://login.microsoftonline.com/common/oauth2/v2.0/token request with the following body:
POST https://login.microsoftonline.com/common/oauth2/v2.0/token
HTTP/1.1
grant_type=authorization_code
&code=[code]
&client_secret=[application secret]
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.readwrite
&redirect_uri=http%3A%2F%2Flocalhost%3A17000%2Fprocessing%2Findex
The response code I receive back from that endpoint is the above error message.
{
"error": "invalid_grant",
"error_description": "AADSTS9002313: Invalid request. Request is malformed or invalid.\r\nTrace ID:6d7a8e32-bcbf-4fc4-a37a-87dae4781b00\r\nCorrelation ID:252912b7-5775-491a-968f-00ab03696dd9\r\nTimestamp: 2019-06-2722:11:18Z",
"error_codes": [9002313],
"timestamp": "2019-06-27 22:11:18Z",
"trace_id": "6d7a8e32-bcbf-4fc4-a37a-87dae4781b00",
"correlation_id": "252912b7-5775-491a-968f-00ab03696dd9"
}
Other StackOverflow posts mention verifying that the redirect_uri's have to match between the initial login and the subsequent access_token requests. They appear identical to me, but I am still receiving errors.
Any ideas what could be going wrong?
This is something you need to understand about OAuth on B2C before you are able to successfully request for a token.
This error means that the requested scope (resource) can’t be accessed by you (login user) because of the lack of permissions.
So, to fix that, you need to grant these required permissions to access that resource, by following these steps:
Define a new scope.
Grant Admin consent on that scope.
Request that scope when you request for a token.
In other words, in B2C-->App Registrations--> (Your App), shown in the image below, start with “Expose an API”, here you define a new scope of access, scope of resources or API, just a metadata that you know it represents some resources or API.
Then you click on “API Permissions”, here you will add the scope you just created and grand admin access in needed. But al least you need to add permissions to your newly defined scope.
The third and last step is when you hit: https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token
Make sure to pass the scope that you added. (Use the scope that you added)
The details are explained in here but I can simplify it for you.
configure b2c
So you need to go to your B2C
Seems you are trying to get access token using Authorization Code Grant V2.0
Your request doesn't match with Authorization Code Grant V2.0 format and you have encountered that error.
You should send token request for Authorization Code Grant V2.0 is like below:
Token Endpoint: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
client_id:b603c7be-_YourApp_ID-e6921e61f925
scope:https://graph.microsoft.com/User.ReadWrite.All
redirect_uri:https://www.getpostman.com/oauth2/callback
grant_type:authorization_code
client_secret:Vxf1SluKbgu4P_YourAppSecret_DSeZ8wL/Yp8ns4sc=
code:OAQABAAIAAADCoMpjJXrxTq9VG9te-7FXrnBIp82sWR1nC
See Screen shot for details:

Client Credentials access token not working office 365

I am using client credentials flow to generate an access token. Following is the request.
I received the access token and I am using to call Web API like
https://graph.microsoft.com/v1.0/me/mailfolders/inbox/messages
Following is the screenshot
Calling Web API gives InvalidAuthenticationToken Error.
Any workaround on this.?
You're resource should be set to https://graph.microsoft.com.
In your screenshot, theresource is set to https://outlook.office.com but you're calling a Microsoft Graph. Since you're providing an access_token for a different resource, Microsoft Graph is rejecting it.
You also need to make sure you've requested the proper Microsoft Graph permissions in the Azure Portal. To call /mailFolders/inbox/messages for example, you need request permission for either Mail.Read or Mail.ReadWrite.
Finally, you cannot use /me with the Client Credentials grant. The /me is simply shorthand for /users/{current-user-id}/. Since Client Credentials does not have a current user, the API has no idea which user me is. You will need to reference a specific user entity in the path:
/v1.0/users/{userPrincipalName}/mailfolders/inbox/messages

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.

Can service/daemon app use 'common' instead of 'tenant-id' when obtaining token from Azure AD v2.0 endpoint

I am developing a daemon app that can perform actions on user inboxes in multiple tenants. Once an admin from a tenant gives the app the required permissions, it should be able to access users inboxes in that tenant. I am doing the following now.
Get consent from admin
https://login.microsoftonline.com/common/adminconsent?client_id={client-id}&redirect_uri=https%3A%2F%2Fredirect.test.com
Global Admin from a tenant (e.g. myutils.onmcirosoft.com) gives required permission.
Get access token by using common instead of tenant-id
curl -X POST _https://login.microsoftonline.com/common/oauth2/v2.0/token --data "grant_type=client_credentials&client_id={client-id}&client_secret={clientsecret}&scope=https://graph.microsoft.com/.default
It gives a access token.
Access messages of admin#myutils.onmicrosoft.com using the token obtained in step 3.
curl -X GET -H "Authorization: Bearer <token>" https://graph.microsoft.com/v1.0/users/admin#myutils.onmicrosoft.com/messages
Above curl request gives the following 404 response:
HTTP/1.1 404 Not Found
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/plain
request-id: e602ada7-6efd-4e18-a979-63c02b9f3c76
client-request-id: e602ada7-6efd-4e18-a979-63c02b9f3c76
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"West US","Slice":"SliceB","ScaleUnit":"000","Host":"AGSFE_IN_22","ADSiteName":"WST"}}
Duration: 1537.3097
Date: Tue, 19 Sep 2017 09:31:08 GMT
In step 3 if I replace common with tenant-id of myutils.onmicrosoft.com it is working.
Is common supported with Azure AD v2.0 endpoint? This link says common is not supported for v1 endpoint. Is it the same for v2.0 endpoint as well?
Just to expand on Nan Yo's answer, the reason you need the tenant-id is due to Graph API itself being a multi-tenant.
Without a tenant-id, Graph would have no way of knowing which tenant to route your calls too. For example,/users returns a list of users but without a tenant-id there is no way to determine which tenant it should pull the users from.
When you use authorization_code or implicit grants, it uses the user's credentials to determine which tenant calls should be routed too. With client_credentials you don't have those credentials to pull those routing queues from.
You can however determine the tenant id during Admin Consent. Along with the admin_consent result, it also returns the tenant. For a multi-tenant service you would need to store that id to use when obtaining a token prior to making a call to Graph.
When using the client credentials flow in Azure AD V2.0, you need to specify the actual tenant that you want a token for. Otherwise , even you get an access token , you will find no application roles include in the access token . An access token will issued from one tenant and could access resource of that tenant , it is impossible to use one access token to query resources of multi tenants .
Please acquiring your token not from /common/oauth/v2.0/token endpoint , use /{tenent-id}/oauth2/v2.0/token endpoint with the tenant id .
Please click here for more details .

Resources