AAD AADSTS50146 acceptMappedClaims App Registrations JWT OAuth2 SAML

Add sAMAccountName to Azure AD Access Token (JWT) with Claims Mapping Policy (and avoiding AADSTS50146)

TLDR

This blog is one of the most read blogs on this site, for that reason I plan to update this blog soon on few other aspects, such as secondary option of using custom token sign-in key. Apparently lot of organizations are migrating apps to use Azure AD and need to have sAMAccountName as one of the claims, so I figured TLDR way is also needed? 🙂

As always confirm all changes and settings in your test environment in order to ensure that the proposed approach is what you are looking for, and doesn’t introduce problems.

Simple approach

Using the presented approach you will have:

  • App that includes the value of sAMAccountName in claim called ”onpremisessamaccountname” for both access and id -tokens
  • Single app registration: This approach works for Web Apps requesting tokens to itself
    • If you have mobile app, just add the web app as API to in applications settings and ’app permissions’

Read the Reference article

Recommendation, see MS docs article from claims for different implementation (Custom sign-in key), this one uses tenant registered domain in appid uri to acknowledge the customized token settings

Configuration

Prerequisites

  • Existing app registration
  • Preview version of AzureAD Powershell module (ensure that you are using one of the newer versions, otherwise errors from the Graph API endpoint will arise)

Configuration steps

  • Add custom policy to Azure AD
#Get sAMAccountName for existing app registrations
AzureADPreview\Connect-AzureAD

$policytemplate = @"
{
    "ClaimsMappingPolicy":  {
                                "Version":  1,
                                "IncludeBasicClaimSet":  true,
                                "ClaimsSchema":  [
                                                     {
                                                         "Source":  "user",
                                                         "ID":  "onpremisessamaccountname",
                                                         "JwtClaimType":  "onpremisessamaccountname"
                                                     }
                                                 ]
                            }
}
"@

$pol =  New-AzureADPolicy -Definition ($policytemplate) -DisplayName ("Policy_sAMAccountName_" + ([System.Guid]::NewGuid().guid)) -Type "ClaimsMappingPolicy" -IsOrganizationDefault $false
 
$spnob =  Get-AzureADServicePrincipal -all $true | Out-GridView -PassThru

Add-AzureADServicePrincipalPolicy -Id $spnob.ObjectId -RefObjectId $pol.Id 
  • Set Application ID URI for the application which matches the root part of domain name registered in your tenant (*appname.dewi.red, example app.dewi.red, for this you need to have the *.domain.com part registered in your tenant )
    • I haven’t tested if this works with the onmicrosoft.com domain, that’s why I recommend custom domain registered in the tenant
  • From app manifest select ”acceptMappedClaims”

Example: Expected result from NodeJS app

  • The sAMAccountname is emitted in claim called ”onpremisessamaccountname”
  • The login URL from app is as follows (using variables from metadata, which the application uses)
    • `${authorization_endpoint}?client_id=${client_id}&redirect_uri=${redirect_uri}&resource=${resource}&response_mode=${response_mode}&response_type=${response_type}`
var loginurl = `${authorization_endpoint}?client_id=${client_id}&redirect_uri=${redirect_uri}&resource=${resource}&response_mode=${response_mode}&response_type=${response_type}`
                if (authorization_endpoint.includes('v2.0')) {
                    var loginurl = `${authorization_endpoint}?client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&response_mode=${response_mode}&response_type=${response_type}`
                }


The old blog begins from here with bit more detail (Its still messy, and needs some cleaning up, nonetheless the facts hold, but I plan to add new info about using custom sign-in keys, (if you don’t do the TLDR approach, which IMO is the best and simplest approach)

With the possibilities available (and quite many of blogs) regarding the subject, I cant blame anyone for wondering whats the right way to do this. At least I can present one way that worked for me

Here are the total ways to do it (1. obviously not the JWT token)

  1. With SAML federations you have full claims selection in GUI
  2. Populate optional claims to the API in app registration manifest, given you’ve updated the schema for the particular app
  3. Create custom Claims Policy, to choose emitted claims (The option we’re exploring here)
  4. Query the directory extension claims from Microsoft Graph API appended in to the directory schema extension app* that Graph API can call

Please note, for sAMAccountName we’re not using the approach where we add directory extensions to Graph API queryable application = NO DIRECTORY EXTENSION SYNC IN AAD CONNECT NEEDED


Checklist for using Claims Mapping Policy

Pre: Have Client application, and web API ready before proceeding

#Example App to Add the Claims 
AzureADPreview\Connect-AzureAD
$Definition = [ordered]@{
    "ClaimsMappingPolicy" = [ordered]@{
        "Version" = 1
        "IncludeBasicClaimSet" = $true
        "ClaimsSchema" = @(
            [ordered]@{
                "Source" = "user"
                "ID" = "onpremisessamaccountname"
                "JwtClaimType" = "onpremisessamaccountname"
            }
        )
    }
}
$pol =  New-AzureADPolicy -Definition ($definition | ConvertTo-Json -Depth 3) -DisplayName ("Policy_" + ([System.Guid]::NewGuid().guid) + "_" + $template.Values.claimsschema.JwtClaimType) -Type "ClaimsMappingPolicy" 
 
$entApp =  New-AzureADApplication -DisplayName  ("DemoApp_" + $template.Values.claimsschema.JwtClaimType)
$spnob =  New-AzureADServicePrincipal -DisplayName $entApp.DisplayName -AppId $entApp.AppId 
Add-AzureADServicePrincipalPolicy -Id $spnob.ObjectId -RefObjectId $pol.Id 
#From the GUI change the Identifier and acceptMappedClaims value (From the legacy experience)

  • Generally: The app that will emit the claims is not the one you use as the clientID (Client subscribing to the Audience)
    • Essentially you should create un-trusted client with clientID, and then add under Api permissions the audience/resource you’re using
  • Ensure that SPN has IdentifierURI that matches registered custom domain in the tenant
    • The reasoning is vaguely explained here & here
      • Whatever research work the feedback senders did, it sure looked in depth 🙂
  • Update the app manifest to Accept Mapped Claims
    • (Works now in the new experience too) Do this in the legacy experience, the new experience at least in my tenant didn’t support updating this particular value
”Insufficient privileges to complete the operation”

if mapped claims are not accepted in manifest, and pre-requisites are not satisfied you might get this error

”AADSTS50146: This application is required to be configured with an application-specific signing key. It is either not configured with one, or the key has expired or is not yet valid. Please contact the application’s administrator.”

  • Below is example for the Manifest changes (AcceptMappedClaims, and verified domain matching URI)
     "id": "901e4433-88a9-4f76-84ca-ddb4ceac8703",
    "acceptMappedClaims": true,
    "accessTokenAcceptedVersion": null,
    "addIns": [],
    "allowPublicClient": null,
    "appId": "9bcda514-7e6a-4702-9a0a-735dfdf248fd",
    "appRoles": [],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2019-06-05T17:37:58Z",
    "groupMembershipClaims": null,
    "identifierUris": [
        "https://samajwt.dewi.red"
    ],

Testing

If you’re planning to use non-verified domain based identifier

”AADSTS501461: AcceptMappedClaims is only supported for a token audience matching the application GUID or an audience within the tenant’s verified domains.

References

https://github.com/MicrosoftDocs/azure-docs/issues/5394

https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory/develop/active-directory-claims-mapping.md

https://github.com/Azure-Samples/active-directory-dotnet-daemon-certificate-credential#create-a-self-signed-certificate

https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory/develop/v2-protocols-oidc.md#fetch-the-openid-connect-metadata-document

https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory/develop/active-directory-claims-mapping.md#example-create-and-assign-a-policy-to-include-the-employeeid-and-tenantcountry-as-claims-in-tokens-issued-to-a-service-principal

Decode JWT access and id tokens via PowerShell

5 comments on “Add sAMAccountName to Azure AD Access Token (JWT) with Claims Mapping Policy (and avoiding AADSTS50146)

  1. Paluuviite: Azure AD – Add Custom claims for WS-Federation applications | SecureCloudBlog

  2. Paluuviite: Azure AD sign in errors (AADSTS error) troubleshooting – Sergii's Blog

  3. Hello, I got AADSTS501461. How do I setup a ”verified domain matching URI”?

    Tykkää

Jätä kommentti