I'm trying to overload the OAuth ID Token by adding additional claims. I can already use the Graph API to get the claims that I need but I would like to understand if it's possible to add the additional claims directly into the ID Token? I've updated the manifest by adding the required claims in and then flipping "acceptMappedClaims" to true, however I still don't see these in the ID token. What am I missing?
"optionalClaims": {
"idToken": [
{
"name": "employeeid",
"source": "user",
"essential": true,
"additionalProperties": []
},
{
"name": "mail",
"source": "user",
"essential": true,
"additionalProperties": []
}
],
"accessToken": [],
"saml2Token": []
},
"acceptMappedClaims": true,
This depends on where the ID token is generated from. If it's on-premises AD and federated identity is used take a look at Customizing the OIDC id_token in ADFS 2016.
If it's just a cloud identity I'd take a look at the second link jwmiller5 posted or this one: how-to-set-claims-from-asp-net-openid-connect-owin-components.
Hope this helps,
Bernie
If you are trying to add additional claims into your AD token, you would need Azure AD premium and you can add the values as attributes. See Claim augmentation with Azure AD authentcation
If you just need the claims in one particular application, you can add the claims in the app itself. See Azure AD PostAuthentication add claims
Related
According to https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-optional-claims it should be possible to add optional claims to a JWT access token or ID token issued by Azure AD, and email is a predefined optional claim. We have added these lines to the manifest for the API application (and to the client application, just in case we were misunderstanding):
"optionalClaims": {
"idToken": [],
"accessToken": [
{
"name": "email",
"source": null,
"essential": true,
"additionalProperties": []
}
],
"saml2Token": []
},
The issuing of ID tokens and access tokens continues to work as before. But access tokens on behalf of an authenticated user whose profile does have an email still do not include the email claim. We originally set essential to false, but that value has made no difference. The email claim is included, and always has been, in the ID token returned to the client by our custom policy.
We are working in an Azure B2C tenant, not AAD, and I wonder if optional claims are not supported in B2C access tokens. Is that the case, or is there something else we just aren't understanding about this documentation?
I am working in Azure AD B2C to add custom extensions per application. Theses extensions must be returned in the jwt when the login is requested by the application.
So I create the extension on the app using the graph api
POST https://graph.microsoft.com/v1.0/applications/{{appid}}/extensionProperties
{
"name": "name",
"dataType": "String",
"targetObjects": [
"User"
]
}
Then I associate a value for a specific user
PATCH https://graph.microsoft.com/v1.0/users/{{userid}}
{
"extension_{{appid(without dashes}}_name": "1234"
}
Now I go on the app manifest to add the optional claim.
"optionalClaims": {
"idToken": [
{
"name": "extension_{{appid(without dashes}}_name",
"source": "user",
"essential": true,
"additionalProperties": []
}
],
"accessToken": [
{
"name": "extension_{{appid(without dashes}}_name",
"source": "user",
"essential": true,
"additionalProperties": []
}
],
"saml2Token": []
},
Save but the claim never appear on the jwt token.
I also tried using the answer of this post but didn't work either.
The problem is you’ve used Optional claims setup, which works for AAD but not AAD B2C.
Follow this: https://learn.microsoft.com/en-us/azure/active-directory-b2c/user-flow-custom-attributes?pivots=b2c-user-flow
If you want to select your custom attribute through the Azure Portal - AAD B2C - User Attributes blade, and the attribute was created via Graph API, you have to recreate it in the Portal for it to reconcile.
You would also need to target the b2c-extensions-app AppId when defining the attribute with Graph API.
I tried to reproduce the same in my environment and got the claims successfully
As Jas Suri - MSFT commented, this will only work if you are adding optional claims to Azure AD application.
I created the extension attribute via Graph API like below:
I associated the above extension attribute to a specific user like below:
Please check whether that extension attribute is visible in optional claims UI or not and add like below:
When you check the manifest, it will be added automatically like below:
I generated the JWT token using auth-code flow via Postman like below:
After decoding the JWT token (ID-Token), I got the claims successfully like below:
In my scenario there is a Azure Application Registration (client_app) with credentials. This application is used to request an oauth2 access token. A second Application Registration (main_app) is the scope, which is providing App Roles and more.
My goal is to include information from client_app in a jwt token claim, when requesting the token using the client credential flow on an azure /oauth2/v2.0/token endpoint.
This is a token request:
POST /<tenant id>/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=<Application ID of client_app>
&client_secret=<secret of client_app>
&scope=<Application ID URI of main_app + "/.default">
&grant_type=client_credentials
The response of the token request is a valid token including roles (granted App Roles from main_app to client_app), aud, sub and idtype: app claims. But my optional claims are missing.
MS docs state, that it is possible to include optional claims using directory extensions
Schema and open extensions are not supported by optional claims, only the AAD-Graph style directory extensions. This feature is useful for attaching additional user information that your app can use [...]
So I tried adding a directory extension to my main_app (extension_<main_app ID>_someAttrName), added an optional claim to main_app and stored a value to this directory extension in client_app. Unfortunately the extension value is not reflected in the token.
I tried adding the directory extension on the client_app itself (extension_<client_app ID>_someAttrName) and map the directory extension to main_app by using ClaimsMappingPolicy. Unfortunately the extension value is not reflected in the token.
It seems to me, that the claims are missing, since they do not originate from a user object. MS docs provide a lot of information to add optional claims, but most scenarios involve a user. E.g. the optional claims source property of a manifest:
The source (directory object) of the claim. There are predefined claims and user-defined claims from extension properties. If the source value is null, the claim is a predefined optional claim. If the source value is user, the value in the name property is the extension property from the user object.
As I understand it, only null and "user" is supported. I want to include a directory extension originating from an Application Registration (client_app). And since I have to use the client credential flow (server-to-server) there is no user involvement.
So how do I add custom optional claims to a token when using client credential flow, when no user object is involved? There is an application object involved. So how do I need to configure claims to reflect custom application data (e.g. directory extensions)?
Manifest of main_app:
{
"id": "<main_app ID>",
"acceptMappedClaims": true,
"accessTokenAcceptedVersion": 2,
"appId": "<main_app APP ID>",
"appRoles": [{
"allowedMemberTypes": ["Application"],
"isEnabled": true,
"origin": "Application",
"value": "readAll"
},{
"allowedMemberTypes": ["Application"],
"isEnabled": true,
"origin": "Application",
"value": "writeAll"
}],
"identifierUris": ["api://<main_app ID>"],
"optionalClaims": {
"idToken": [],
"accessToken": [ {
"name": "extension_<main_app ID>_someAttrName",
"source": "application", <-- propably invalid, "user" or null is supported
"essential": false,
"additionalProperties": []
}, { ... }
],
},
} /# trunced for readability
Manifest of client_app:
{
"id": "<client_app ID>",
"accessTokenAcceptedVersion": null,
"appId": "<client_app APP ID>",
"passwordCredentials": [{...}],
"extension_<main_app ID>_someAttrName": "some-string-value"
} /# trunced for readability
My ClaimsMappingPolicy definition looks like this:
"ClaimsMappingPolicy": { "Version": 1, "IncludeBasicClaimSet": "true",
"ClaimsSchema": [ {
"Source": "application",
"ExtensionID": "extension_<client_app ID>_someAttrName",
"JwtClaimType": "someAttrName"
} ]
}
I reached out to Azure support engineers, and they told me, that it's not possible to include directory extension based claims originating from Application Registrations. They did not go into detail but replied this:
I apologize to inform we got to know that reflecting extension claims in JWT token won't be possible. Since directory extensions can't be added to servicePrincipal objects.
I'm assuming the requesting entity is a service principal when using the client credentials flow.
I am using OAuth2 Code flow and trying to get the user's groups back in my access token. Everything I'm reading says I should see either a groups claim or a hasgroups claim, but I see neither.
I've altered the following fields in the App registration manifest for my client app:
"groupMembershipClaims": "SecurityGroup",
"optionalClaims": {
"idToken": [],
"accessToken": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": [
"dns_domain_and_sam_account_name"
]
}
],
"saml2Token": []
},
Here is an example of my querystring for the login redirection url (login.microsoftonline.com)...
client_id=<clientId>
&response_type=code
&redirect_uri=<redirectUri>
&response_mode=query
&scope=<appScope>%20offline_access
&state=67890
Here is an example of my querystring for my requesting the token using authCode (login.microsoftonline.com/{tenantId}/oauth2/v2.0/token)
client_id=<clientId>
&scope=<uriEncodedScopes>%20offline_access
&redirect_uri=<uriEncodedRedirectUri>
&code=<authCode>
&client_secret=<uriEncodedClientSecret>
&grant_type=authorization_code
Everything is working great, but I can't figure out how to get groups info back in my token.
UPDATE
I added %20openid to my scope in both urls, and now I'm getting an id_token, but I still don't see "groups" or "hasgroups" in either token.
UPDATE
I just added the same manifest changes (groupMembership, optionalClaims) to my API App Registration (instead of my client) - the API that exposes the scope, and I see no change whatsoever. Access token and Id token don't have any reference to groups at all.
Per my test, it should work. And you just need to configure the groupMembershipClaims, optionalClaims in your API App Registration, refer to the reason below.
You could refer to my test sample below, I tried with a work account or personal account, both work.
Request the authorization code(the api://3e013fde-xxxxxxa422f3/User.Test is my API permission):
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize?
client_id=xxxxxxxxxxxxxxx
&response_type=code
&redirect_uri=https://localhost
&response_mode=query
&scope=openid offline_access api://3e013fde-xxxxxxa422f3/User.Test
&state=12345
Request the token:
Decode the token in https://jwt.io/, the groups claim is included.
Note:
My client App and API App are both created today, I suppose there are may some difference between the app created in the old App Registration(it is not existing in the portal currently), app registration portal(it has been moved to the new App Registrations), new App Registration(theApp Registrationin portal currently).
And from this doc:
There is also a weird thing during my test, when I create a new API App Registration, just set "groupMembershipClaims": "SecurityGroup" without setting optionalClaims, the manifest will be like below.
"groupMembershipClaims": "SecurityGroup",
"optionalClaims": {
"idToken": [],
"accessToken": [],
"saml2Token": []
}
Then the Access token will not include groups, the ID token has the groups.
If I set it with yours, the Access token will have the groups.
"groupMembershipClaims": "SecurityGroup",
"optionalClaims": {
"idToken": [],
"accessToken": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": [
"dns_domain_and_sam_account_name"
]
}
],
"saml2Token": []
}
But when I set it return to
"groupMembershipClaims": "SecurityGroup",
"optionalClaims": {
"idToken": [],
"accessToken": [],
"saml2Token": []
}
The Access token still has the groups.
From the portal - Token configuration (preview) and this doc - Configure group claims for applications with Azure Active Directory (Public Preview), the feature should be in preview, it may be a bug(I am not sure).
So in conclusion, I recommend you to use two new Apps to have a try.
I want to know if there is a way to retrieve the registered domain(s) for a tenant through REST API for Sharepoint/Office365.
Consider this scenario;
I have a tenant named abc.pqr and url for the "my" site(OneDrive) is abc-my.sharepoint.com.
Now when I create a user for this tenant, the UI panel gives the option to select a domain for this account. Available options are;
1) #abc.pqr
2) #abc.onmicrosoft.com
Now, the problem is, if I have a user of this sort >>> testUser#abc.onmicrosoft.com, how do I findout the registered domain for this tenant? Which in my case is abc.pqr.
Is there a way to find this through REST API?
Sounds like what you want to know is the list of verified domains in your Azure Active Directory tenant. (Azure AD is the directory service behind Office 365 and other Microsoft online services.)
The Azure AD Graph API—AAD's REST API—can provide this for you. In your case, the GET request you would want to make is:
https://graph.windows.net/abc.onmicrosoft.com/tenantDetails
Note: you can use either the tenant ID or any verified domain of the tenant instead of abc.onmicrosoft.com. The tenant ID can be obtained from the tid claim in the access token.
The JSON response will include something like this:
"verifiedDomains": [
{
"capabilities": "None",
"default": true,
"id": "0007ABE0983098",
"initial": false,
"name": "abc.pqr",
"type": "Managed"
},
{
"capabilities": "Email, OfficeCommunicationsOnline",
"default": false,
"id": "0007ABE0983098",
"initial": true,
"name": "abc.onmicrosoft.com",
"type": "Managed"
}
]
(There's a useful Quickstart for the Azure AD Graph API that shows how to start playing around with AAD Graph API, and the GraphExplorer.)
If you're using .NET, there is a full sample at https://github.com/AzureADSamples/WebApp-GraphAPI-DotNet. (More samples for other languages and platforms at https://github.com/AzureADSamples.)