I've successfully written an API that can access a downstream API (using v1 ADAL.NET), so, I have some codes for that.. (the clients were based on AutoRest)
Furthermore, I've successfully gotten a sample Microsoft Graph web app running (but, it's coded for v2 and MSAL)
Does anyone have an example of an API accessing a downstream API (i.e. Microsoft Graph). While I can successfully get my access token, when I go to make the call I only get a Microsoft.Graph.ServiceException:
InvalidAuthenticationToken
Message: Access token validation failure.
Sample access token:
Header:
{
"alg": "RS256",
"typ": "JWT",
"x5t": "[removed]",
"kid": "[removed]"
}
Payload:
{
"aud": "https://graph.windows.net",
"iss": "https://sts.windows.net/[removed]/",
"iat": "1533754778",
"nbf": "1533754778",
"exp": "1533758925",
"acr": "1",
"aio": "[removed]",
"amr": "wia",
"appid": "[removed]",
"appidacr": "1",
"e_exp": "263047",
"family_name": "My Last Name",
"given_name": "My Name",
"ipaddr": "[removed]",
"name": "My Name My Last Name",
"oid": "[removed]-7593-4755-1234-bbbb1234aaaa",
"onprem_sid": "[removed]",
"puid": "[removed]",
"scp": "Directory.Read.All Mail.Send User.Read",
"sub": "[removed]",
"tenant_region_scope": "NA",
"tid": "[removed]",
"unique_name": "me#[removed].com",
"upn": "me#[removed].com",
"uti": "[removed]",
"ver": "1.0"
}
--- UPDATE ---
Maybe this is it? Downloading...
--- SOLVED ---
I was using the wrong resource uri. See my answer below for details
OK, the key things I've learned about interacting with Microsoft Graph API:
Yes, you CAN use the new client api NuGet from here with v1 and v2 app registrations
An example of the GraphServiceClient client in use is found at this QuickStart but it goes against v2 using MSAL
Borrow code from this sample project to do v1 (ADAL.NET) interactions with traditional app registrations in the portal
Where I went wrong: somewhere along the way, I thought the resourceUri I was supposed to use was https://graph.windows.net, but it's really just: https://graph.microsoft.com
Related
We are having a problem with a feature available in the beta version of Graph. We are using this endpoint to extract sensitivity labels from drive item:
POST https://graph.microsoft.com/beta/drives/{drive-id}/items/{item-id}/extractSensitivityLabels
According to the documentation, we need Files.Read.All, Files.ReadWrite.All, Sites.Read.All or Sites.ReadWrite.All permissions to access this endpoint:
https://learn.microsoft.com/en-us/graph/api/driveitem-extractsensitivitylabels?view=graph-rest-beta&tabs=http#permissions
Deserialized token we used for authentication:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/xxx/",
"iat": 1655160900,
"nbf": 1655160900,
"exp": 1655247600,
"aio": "xxx",
"app_displayname": "xxx",
"appid": "xxx",
"appidacr": "2",
"idp": "https://sts.windows.net/xxx/",
"idtyp": "app",
"oid": "xxx",
"rh": "xxx",
"roles": [
"Sites.Manage.All",
"Sites.ReadWrite.All",
"Files.ReadWrite.All"
],
"sub": "xxx",
"tenant_region_scope": "EU",
"tid": "xxx",
"uti": "xxx",
"ver": "1.0",
"wids": [
"xxx"
],
"xms_tcdt": "1509395911"
}
However, we receive a 403 response with the content:
{
"error": {
"code": "accessDenied",
"message": "Cannot call this API using the current App Id.",
"innerError": {
"date": "2022-06-14T08:00:52",
"request-id": "xxx",
"client-request-id": "xxx"
}
}
}
We have tested other graph beta endpoints and had no problems with them. What could be causing this problem?
Seems that currently this only work with Delegated permissions.
I did not find any trace in the docs if there are some pre-allowed appIds that would be allowed to call this API in Application context.
First of all you are calling a particular drive's item and this looks like you don't have access for that particular file drive/item , we can suggest you to please check if are able to access particular drive and items which you want to add extract sensitivity labels ,by calling Get API .
GET /drives/{drive-id}/items/{item-id}
Thanks
When I request an OAuth token from Azure AD for an application user (using a client_id and client_secret) targeting the correct resource audience (target application), I don't know how to get Azure AD to populate a claim for the client's DisplayName attribute (primarily for an application client, but also users should work too) in Azure AD.
POST /<tenant_id>/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=<client_id>&resource=<target_aud_app_uri>&client_secret=<client_secret>
{
"typ": "JWT",
"alg": "RS256",
"x5t": "xxx",
"kid": "xxx"
}.{
"aud": "<target_aud_app_uri>",
"iss": "https://sts.windows.net/<tenant_id>/",
"iat": 1619676176,
"nbf": 1619676176,
"exp": 1619680076,
"aio": "xxx",
"appid": "<client_id>",
"appidacr": "1",
"idp": "https://sts.windows.net/<tenant_id>/",
"idtyp": "app",
"oid": "xxx",
"rh": "xxx",
"roles": [
"XXX"
],
"sid": "xxx",
"sub": "xxx",
"tenant_ctry": "AU",
"tenant_region_scope": "OC",
"tid": "xxx",
"uti": "xxx",
"ver": "1.0"
}.[Signature]
In the target application configuration in Azure AD, I've added all the optional claims it allows in the UI, and even tried adding 'display_name' via the manifest but it doesn't know how to pick it up. Is there a way to do this?
This question has been asked before.
This is possible under the Microosft.graph namespace only cannot be used for any custom app. In other words, only the ms graph api token has app_displayname claim. For the token of the application custom api, it is currently not possible to add the app_displayname claim, at least for now this is impossible.
I suggest you submit user voice, and I will vote for it.
Through an Oauth2 client credentials flow, i get an access token which seems to have the right audience, roles... for the Microsoft Graph API.
Nevertheless, a call to the Graph API to get messages a of a specific user sends back :
{
"error": {
"code": "UnknownError",
"message": "",
"innerError": {
"request-id": "1c24f471-ebca-489a-8264-8ef4cd66c72d",
"date": "2019-04-19T10:55:34"
}
}
}
The payload of the token does seem ok :
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/customer-tenant-XXXXXXXXXX/",
"iat": 1555670233,
"nbf": 1555670233,
"exp": 1555674133,
"aio": "42ZgYFgUNyvl6hTle8+nbZH4qu2/DwA=",
"app_displayname": "XXXXXXXXXXXXXXXX",
"appid": "OUR-ID-XXXXXXXXXXXXX",
"appidacr": "2",
"idp": "https://sts.windows.net/customer-tenant-XXXXXXXXXX/",
"oid": "YYYYYYYYYYYYYYYYYYYYYY",
"roles": [
"Mail.ReadWrite",
"Calendars.Read",
"Directory.Read.All",
"Chat.Read.All",
"ChannelMessage.Read.All",
"MailboxSettings.ReadWrite",
"Reports.Read.All"
],
"sub": "YYYYYYYYYYYYYYYYYYYYYYYYYY",
"tid": "WWWWWWWWWWWWWWWWWWWWWWWWWWW",
"uti": "ZZZZZZZZZZZZZZZZZZZZZZZZ",
"ver": "1.0",
"xms_tcdt": 1546954974
}
The exact same authentication flow process on my test company account works perfectly. The only difference is that our customer has a 2016 Hybrid Exchange set-up. The individual flow (Oauth2 authorization code for one user) DO work to access one user mailbox.
Is there any parameter that should be set on customer Exchange configuration to have OAuth2 client_credentials flow working ?
I'm having issue authenticating with Azure Active Directory which is linked to a power BI service. I'm trying to get an access token so that I can access the power bi rest API.
If i use postman, I'm able to successfully use their OAuth2 login to retrieve a token that has the correct credentials to communicate with the power bi rest API.
However, when I try to do this with the adal.js the token is invalid. To simplify this to be able to reproduced, I based my project off
https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi
You need to update window config in : \active-directory-javascript-singlepageapp-dotnet-webapi\TodoSPA\App\Scripts\app.js
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: <insert tenant>,
clientId: <insert clientid>,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
endpoints: {
"https://api.powerbi.com": "https://analysis.windows.net/powerbi/api",
}
};
Workaround
I'm able to get the token via silent authentication where you have to hard code the username and password.
I followed this http://community.powerbi.com/t5/Developer/How-to-use-Power-BI-Rest-API-without-GUI-authentication-redirect/m-p/14218#M119 to create the request for silent authentication:
Post Url: https://login.windows.net/<tenant>/oauth2/token
Body:
password: <password>
username: <username>
client_id: <clientid>
client_secret: <secret>
grant_type: password
scope: openId
resource: https://analysis.windows.net/powerbi/api
I also validated that the account I used had the correct permission by using postman and authorization with OAuth2. The token I received had the correct permission for PowerBI.
Post Man Configuration
On postman, click on Authorization Tab -> Set Type to OAuth2.0 -> Get New Access Token:
The configuration you would use:
AuthUrl: https://login.microsoftonline.com//oauth2/authorize?resource=https://analysis.windows.net/powerbi/api
Access Token URL: https://login.microsoftonline.com//oauth2/token
Grant Type: Authorization Code:
Client ID:
Client Secret:
Go to https://dev.powerbi.com/apps to generate the clientID/ClientSecret and set the Redirect URL: https://www.getpostman.com/oauth2/callback
postman generated token:
{
"aud": "https://analysis.windows.net/powerbi/api",
"iss": "https://sts.windows.net/<id>/",
"iat": 1500464096,
"nbf": 1500464096,
"exp": 1500467996,
"acr": "1",
"aio": <value>,
"amr": [
"pwd"
],
"appid": <app_id>,
"appidacr": "1",
"family_name": "Sunderam",
"given_name": <userName>,
"ipaddr": "23.252.49.99",
"name": <name>,
"oid": <oid_id>,
"platf": "3",
"puid": <puid_id>,
"scp": "Content.Create Dashboard.Read.All Data.Alter_Any Dataset.Read.All Dataset.ReadWrite.All Group.Read Group.Read.All Metadata.View_Any Report.Read.All Report.ReadWrite.All",
"sub": <sub_id>,
"tid": <tid_id>,
"unique_name": <user_email>,
"upn": <user_email>,
"ver": "1.0",
"wids": [
<wid_id>
]
}
adal.js token
{
"aud": <aud_id>,
"iss": "https://sts.windows.net/<id>/",
"iat": 1501037728,
"nbf": 1501037728,
"exp": 1501041628,
"aio": <aio_id>",
"amr": [
"pwd"
],
"family_name": <name>,
"given_name": <name>,
"ipaddr": "23.252.49.99",
"name": ,"name"
"nonce": "b21969c3-ae73-4928-bcd0-e9c501f791e4",
"oid": <oid_id>,
"platf": "5",
"sub": <sub_id>,
"tid": <tid_id>,
"unique_name": <user_email>,
"upn": <user_email>,
"ver": "1.0"
}
Notice that the postman token has the scp, appid, and wids.
Any Advice appreciated,
Thanks,
Derek
You need to check the token via the request. For example, you can check it via the developer tools-Network tab(Chrome, F12).
And based on the token and code, the config seems incorrect. For the endpoints is the collection of {Endpoint-ResourceId} used for automatically attaching tokens in webApi calls.
You can use the config like below:
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: <insert tenant>,
clientId: <insert clientid>,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
endpoints: {
"https://analysis.windows.net/powerbi/api": "https://api.powerbi.com",
}
};
More detail about this library, you can refer this link.
I'm currently developing an Outlook addin using the new web technologies.
What is not clear to me though: The method Office.context.mailbox.getCallbackTokenAsync works differently on Desktop (Web) and iOS. On the Web, I get a token which decodes to the following:
{
"nameid": "...",
"ver": "Exchange.Callback.V1",
"appctxsender": "https://.../core.html?button=ItemRead#0e7219f7-4c4d-47e7-b98a-7b9b9de02b80",
"appctx": {
"oid": "...",
"puid": "10033FFF8670ACD2",
"smtp": "...",
"upn": "...",
"scope": "ParentItemId:AAMkADQ2ZWI1NWUzLWFjNTgtNDhkNi05MTRlLTE0ZjkzYjhiZmIxYgBGAAAAAAAiCmOBDIX4TojSJs8PRerdBwCiXa8K4T4FToTXRfNegy16AAAAAAENAACiXa8K4T4FToTXRfNegy16AANl/D0YAAA="
},
"iss": "00000002-0000-0ff1-ce00-000000000000#0e7219f7-4c4d-47e7-b98a-7b9b9de02b80",
"aud": "00000002-0000-0ff1-ce00-000000000000/outlook.office365.com#0e7219f7-4c4d-47e7-b98a-7b9b9de02b80",
"exp": 1491917568,
"nbf": 1491917268
}
I can successfully call EWS to get the attachment of the e-mail (like so: https://github.com/OfficeDev/office-js-docs/blob/master/docs/outlook/get-attachments-of-an-outlook-item.md)
On iOS however, the token I get looks like this - and it's also not possible to get the ewsUrl property.
{
"oid": "...",
"puid": "....",
"smtp": "...",
"upn": "..",
"ver": "Exchange.Callback.V2",
"appid": "00000002-0000-0ff1-ce00-000000000000",
"deploymentid": "https://outlook.office365.com/",
"tid": "0e7219f7-4c4d-47e7-b98a-7b9b9de02b80",
"acr": "1",
"appidacr": "0",
"scp": "Mail.ReadWrite Mail.Send Calendars.ReadWrite Contacts.ReadWrite",
"iss": "https://outlook.office365.com/",
"aud": "https://outlook.office365.com",
"exp": 1491918090,
"nbf": 1491917190
}
This token does not work when used as a bearer token for EWS, so my guess is it would only work with the REST Api? Can Exchange.Callback.V2 in general only used with the REST Api? What is the criteria when to call EWS and when REST?
How do I support scenarios that are not Office365, when there is a on-premise Exchange 2016 server with no REST support?
Thanks
Tobias