We try to create an AAD service principal for retrieving data from out Log Analytics workspace.
Our AAD region is located in Germany
Log Analytics is located in North Europe
When attempting to create API permissions, the address to the API itself is mentioning westus2.api.loganalytics.io (west US region) which is a no go for our company data privacy.
Is there any reason of this default and not editable settings ? Is there any way to overcome it ?
Well, if so, you could get the token for ARM API endpoint, then call the ARM API.
In this way, no need to add the API permission for your AD App, just make sure your AD App has an RBAC role e.g. Contributor, Log Analytics Reader in the Access control (IAM) of your workspace, if not, follow this doc to add it.
Then use the client credential flow to get the token.
POST /YOUR_AAD_TENANT/oauth2/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&resource=https://management.azure.com/
&client_secret=YOUR_CLIENT_SECRET
After getting the token, use it to call the api like the sample below.
GET https://management.azure.com/subscriptions/6c3ac85e-59d5-4e5d-90eb-27979f57cb16/resourceGroups/demo/providers/Microsoft.OperationalInsights/workspaces/demo-ws/api/query
Authorization: Bearer <access_token>
Prefer: response-v1=true
{
"query": "AzureActivity | limit 10"
}
For more details, refer to this link.
Related
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.
In Microsoft 365, we’re able to create a personal contact but we can’t view the contacts of users, let alone add personal contacts to users mailboxes. We keep getting an ErrorAccessDenied message in the output.
Can anyone please advise on how we can get this resolved?
Microsoft Graph Explorer uses user token (delegated permission) to access the contacts data.
It only supports POST /me/contacts.
To access others' contacts, we need to implement Get access without a user which uses client credentials flow.
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials
In this way you can get an application token (application permission). You can use it to access other users' contacts.
You can use Postman to have a test. Microsoft Graph explorer doesn't support client credentials flow.
Within our department we have a Classic ASP website that has been using our corporate Google accounts for authentication and to insert events into our Google Calendars. The organisation has just switched from Google to Office 365 and I'm trying to switch the code to use Outlook instead - with no success.
I can use the access token to GET https://graph.microsoft.com/v1.0/me and see the basic profile, but if I try to read calendar events or send an e-mail I see the message:
"error": {
"code": "NoPermissionsInAccessToken",
"message": "The token contains no permissions, or permissions can not be understood."
I created an Azure account with my personal Microsoft account and added an application. I added my colleagues and my corporate account as guest users. I set the permissions required and did the admin consent thing:
I then followed the steps on this page.
I first visit https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize, including the following query items:
client_id={client id}
response_type=code
redirect_uri={our URL}
response_mode=query
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={number}
This returns a "code", which I send to https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/token, including:
grant_type=authorization_code
client_secret={client secret}
client_id={client id}
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={same number as above}
redirect_uri={same URL as above}
code={code returned from /authorize}
This returns the id, access and refresh tokens. If I decode the access token using https://jwt.ms/, it seems to contain the appropriate audience and scope:
"aud": "https://graph.microsoft.com"
"scp": "Calendars.ReadWrite email Mail.Send openid profile User.Read"
...although I notice that there is no "roles" entry, which I see in some of the documentation. Is that an issue?
I then send the access token to https://graph.microsoft.com/v1.0/me with the following headers:
"Authorization", "Bearer {access token}"
"Host", "graph.microsoft.com"
"Content-Type", "application/json"
"Prefer", "outlook.timezone Europe/London"
That will return my e-mail address, etc., but if I change the URL to anything else, such as /me/photo/$value, /me/calendar/events, or try to send an e-mail I'm told that there are no permissions in the token.
I see that there are other similar questions, but they are mostly for the client_credentials flow (I'm not sure that makes any difference), and none of the answers has helped me resolve my problem.
Can someone please let me know if I've obviously missed anything - or I'm going about this in the wrong way to access Graph data on the client side? It seemed so straightforward with Google, but I'm finding the Microsoft documentation and examples a bit less detailed.
Adding guest users is meaningless.
What you have done is Admin consent for the Azure AD with your personal Microsoft account.
What you actually need to do is Admin consent for the target Azure AD/ O365 tenant.
Construct a consent link as following:
https://login.windows.net/{tenant ID of the target Azure AD}/oauth2/authorize?response_type=id_token&client_id={client ID}&redirect_uri={reply url}&response_mode=form_post&nonce=a4014117-28aa-47ec-abfb-f377be1d3cf5&resource=https://graph.microsoft.com&prompt=admin_consent
Access it in a browser and log in with an admin account of target Azure AD.
Another issue is that you are using Get access on behalf of a user. So you have to assign Delegated permissions rather than Application permissions in the Azure AD app.
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.
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 .