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
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.
How can you determine if the JWT token used in Authorization: Bearer ... is an access token or a refresh token. In other words what prevents the user from using his JWT refresh token in the Authorization header instead of the acces token.
When I look at the payload of both the access token and the refresh token in this guide section https://github.com/starkandwayne/ultimate-guide-to-uaa/blob/master/docs/refresh-tokens.md#jwt-refresh-tokens I don't see any real way to identify which one is which.
Refresh token:
{
"jti": "3e53955fcff6429a8a187c4c37f1b592-r",
"sub": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"scope": [
"openid",
"airports.all"
],
"client_id": "airports",
"cid": "airports",
"user_id": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"origin": "uaa",
"grant_type": "password",
"user_name": "airports-all",
"rev_sig": "4c3b3810",
"iat": 1530739971,
"exp": 1533331970,
"iss": "https://192.168.50.6:8443/oauth/token",
"zid": "uaa",
"aud": [
"openid",
"airports"
]
}
Access token:
{
"jti": "fe39323464d74fb5a6fcb71d89f722c4",
"sub": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"scope": [
"openid",
"airports.all"
],
"client_id": "airports",
"cid": "airports",
"azp": "airports",
"user_id": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"origin": "uaa",
"grant_type": "password",
"user_name": "airports-all",
"email": "airports-all#example.com",
"auth_time": 1530739970,
"rev_sig": "4c3b3810",
"iat": 1530739971,
"exp": 1530783171,
"iss": "https://192.168.50.6:8443/oauth/token",
"zid": "uaa",
"aud": [
"openid",
"airports"
]
}
What is the standard? Put a different scope?
As in the link you've posted, the recommendation is to use opaque refresh tokens that are not JWTs, and you should use that configuration.
The client (usually a UI) should only ever send access tokens to the back end and any other type of token should be rejected. The correct configuration enforces this.
The back end's job is to validate the received JWT. A non standard setup as above could mean that this will work with a refresh token, but this is bad in 2 ways:
The API message credential has a very long lifetime and security risks are greater if a token is intercepted somehow
The solution is not portable and is likely to break for the client in future, or if you ever change providers
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'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