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.
Related
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
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