I have an id_token_hint with a token from an https://sts.windows.net/. I'm willing to use it as a trusted party based on the role present in the token. Here's a JWT token example:
{
"iss": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/",
"iat": 1610050840,
"nbf": 1610050840,
"exp": 1610054740,
"aio": "E2JgYPi646//0000000000000000000=",
"app_displayname": "my_app_displayname",
"appid": "00000000-0000-0000-0000-000000000000",
"appidacr": "1",
"idp": "https://sts.windows.net/00000000-0000-0000-0000-000000000000/",
"idtyp": "app",
"oid": "00000000-73e4-46ae-b464-000000000000",
"rh": "0.AAAAiKphxJIQoUmmKLTdWWDB80kfo3ST3nNJgG0000000000000.",
"roles": [
"Mail.Send",
"Policy.ReadWrite.TrustFramework"
],
"sub": "00000000-73e4-46ae-b464-000000000000",
"tenant_region_scope": "EU",
"tid": "00000000-0000-0000-0000-000000000000",
"uti": "jDVAsZtcd0ezvvkFN00000",
"ver": "1.0",
"xms_tcdt": 1599800000
}
As you can see here I have a field roles, which contains an array of roles. I'm trying to parse this array into specific claims like IsPolicyReadWriteRole and IsMailSendRole. However, I cannot find any examples over the starter pack or examples how to do that. I don't need these claims to be themself, I just plan to use them as a precondition in the orchestration step.
You can extract claims from id_token_hint using the instructions and sample mentioned here - https://learn.microsoft.com/en-us/azure/active-directory-b2c/id-token-hint
Then you can use the getsingleitemfromstringcollection claim transformation to get the claim value.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/stringcollection-transformations#getsingleitemfromstringcollection
And then you can use claimExist or claimEquals predicate to test for the value.
The id_token_hint validation technical profile will look like below
<ClaimsProvider>
<DisplayName>Trustframework Policy Engine TechnicalProfiles</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="TpEngine_IdTokenHint_ExtractClaims">
<DisplayName>Trustframework Policy Engine ID Token Hint Setup Technical Profile</DisplayName>
<Protocol Name="None" />
<Metadata>
<Item Key="METADATA">https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration</Item>
</Metadata>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Related
We have a client whose IdP issues JWT's with group claims in the following format:
"groups": [
"Domain Users",
"US Users",
"Administrators"
]
But when there is only a single group:
"groups": "Domain Users"
Now obviously, this is bad practice, but we have little to no control over our client's decision to use inconsistent data types. As expected, B2C throws an exception when trying to parse a claim it expects to be a stringCollection but is actually a string.
Is there any workaround for this scenario?
EDIT:
Here is the groups ClaimType as defined in TrustFrameworkExtensions:
<ClaimType Id="groups">
<DisplayName>Groups</DisplayName>
<DataType>stringCollection</DataType>
<AdminHelpText>User's groups.</AdminHelpText>
</ClaimType>
And the OutputClaim in the external IdP TechnicalProfile:
<OutputClaim ClaimTypeReferenceId="groups" PartnerClaimType="group" />
I'm using Graph to query a user profile in Azure B2C. I'm able to query the users, but I don't see the Source field to determine the Source of Authority. What field is this?
I'm currently using the .28-preview of the Microsoft.Graph.Beta NuGet package.
And this is what I see in the debugger under Identities:
How would I tell the difference if that was a Google account or an Azure AD account?
Using Microsoft Graph, it’s the issuerId field within the Identities array and only returns on beta version.
Source is not included in the identities array, and is also not included in the properties.
As this issue with PowerShell shows, onPremisesSyncEnabled property will help.
I solved this by creating a custom attribute and then in the custom policies setting the custom attribute based on signup method (see alternative solution near the end).
How to define custom attributes and use them with the MS Graph API and custom policies is explained pretty well here. The hardest part is perhaps getting the custom policy right. I did everything in TrustFrameworkExtensions.xml. First defining an "extension_authoritySource" ClaimType:
<ClaimType Id="extension_AuthoritySource">
<DisplayName>AuthoritySource</DisplayName>
<DataType>string</DataType>
</ClaimType>
Then in <TechnicalProfile Id="Facebook-OAUTH"> I added an OutputClaim which sets this custom attribute to facebook, but this will only be persisted if a PersistedClaim is made in UserWriteUsingAlternativeSecurityId as shown below:
<OutputClaim ClaimTypeReferenceId="extension_AuthoritySource" DefaultValue="Facebook"/>
To persist the custom attribute I added the following to ClaimsProviders:
<ClaimsProvider>
<DisplayName>Azure Active Directory</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="AAD-Common">
<Metadata>
<Item Key="ClientId">[b2c-extensions-app application ID]</Item>
<Item Key="ApplicationObjectId">[b2c-extensions-app application ObjectId]</Item>
</Metadata>
</TechnicalProfile>
<!-- Write data during a local account sign-up flow. -->
<TechnicalProfile Id="AAD-UserWriteUsingLogonEmail">
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="extension_AuthoritySource" DefaultValue="local"/>
</PersistedClaims>
</TechnicalProfile>
<TechnicalProfile Id="AAD-UserWriteUsingAlternativeSecurityId">
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="extension_AuthoritySource" DefaultValue="social"/>
</PersistedClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Note that with the above email signups will always be set as "local", while UserWriteUsingAlternativeSecurityId sets it as "social", but is overwritten by the output claim from facebook.
My thinking here is that UserWriteUsingLogonEmail is only ever used by email signup, whereas UserWriteUsingAlternativeSecurityId could potentially be used by several federated logins, although at the moment I only use facebook.
Alternative without Custom Attribute
Alternatively, if you are not using custom policies or cannot use the approach above for another reason, you can use the MS Graph API and look in the "identities" array which contains the sign in type. So for a given user GET: https://graph.microsoft.com/v1.0/users/[Users objectID Guid]?$select=identities
In this array you can find for a local signup:
{
"signInType": "emailAddress",
"issuer": "[yourdomain].onmicrosoft.com",
"issuerAssignedId": "[email]"
}
and for facebook:
{
"signInType": "federated",
"issuer": "facebook.com",
"issuerAssignedId": "[number]"
}
Every user also has a "userPrincipalName" item in the identities array so you will have to have some logic to loop through the array and only look for the signInType which you want to support. Yet another reason for preferring using custom attribute and setting the authority source yourself.
I just followed the tutorial on the page and created a certificate and exposed it to the azure portal.
I also uploaded the policy files and modified them with my tenant.
I'm running the application on my localhost, but when I wanna browse to that link, I got following error in jwt.ms:
AADB2C90232: The provided id_token_hint parameter does not contain an accepted issuer. Please provide another token and try again. Correlation ID: 1f9cd754-7033-40ea-91a2-b2f91b867fb9 Timestamp: 2020-06-29 13:05:18Z
I saw that the issuer in the the token is related to localhost:
{
"alg": "RS256",
"kid": "1D8082E33223E5EA5094B62B4BB5B3944779D3AD",
"x5t": "HYCC4zIj5epQlLYrS7WzlEd5060",
"typ": "JWT"
}.{
"name": "Western Miller",
"email": "test#test.be",
"nbf": 1593436327,
"exp": 1594041127,
"iss": "https://localhost:44351/",
"aud": "ba6d05ab-ec87-4d04-b83f-dc62ebb727d8"
}.[Signature]
Anyone who knows what I need to place in the iss that's working by just running locally?
This occurs when the id_token_hint you generate in your web service contains an issuer claim (iss), that is not accepted by the id token hint technical profile.
See in the below XML, that the issuer item must contain a string that matches exactly your iss claim in the generated id_token_hint.
<TechnicalProfiles>
<TechnicalProfile Id="IdTokenHint_ExtractClaims">
<DisplayName> My ID Token Hint TechnicalProfile</DisplayName>
<Protocol Name="None" />
<Metadata>
<!--Sample action required: replace with your endpoint location -->
<Item Key="METADATA">https://your-app.azurewebsites.net/.well-known/openid-configuration</Item>
<Item Key="IdTokenAudience">your_optional_audience_override</Item>
<Item Key="issuer">your_optional_token_issuer_override</Item>
</Metadata>
You should put https://localhost:44351/ in the issuer metadata item.
I'm currently using built-in attributes.
I'd like to get the "age_range" and "gender" from the FB.
Do I need to deal with custom policies as explained in the following topic:
how to get Facebook profile picture using Azure AD B2C
how to get Facebook profile picture using Azure AD B2C
to get them?
Thanks!
Yes, you will have to create a custom policy for that, and then:
1: Declare the "ageRange" and "gender" claim types in the extension file.
2: Add both the "age_range" and "gender" fields to the "ClaimsEndpoint" metadata item and the "ageRange" and "gender" output claims to the "Facebook-OAUTH" technical profile.
3: Issue the "ageRange" and "gender" claims in the relying party file.
If you are wanting to save the "age_range" and "gender" fields from Facebook as attributes to Azure AD B2C, then you must:
1: Follow the Azure Active Directory B2C: Creating and using custom attributes in a custom profile edit policy steps to create the custom attributes for "AgeRange" and "Gender".
2: Change the claim type declarations, as well as all other references to them, from "ageRange" and "gender" to "extension_AgeRange" and "extension_Gender".
3: Add the "extension_AgeRange" and "extension_Gender" claims in the extension file to the "AAD-UserWriteUsingAlternativeSecurityId" and "AAD-UserReadUsingAlternativeSecurityId" technical profile:
<ClaimsProvider>
<DisplayName>Facebook</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="AAD-UserReadUsingAlternativeSecurityId">
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="extension_AgeRange" />
<OutputClaim ClaimTypeReferenceId="extension_Gender" />
</OutputClaims>
</TechnicalProfile>
<TechnicalProfile Id="AAD-UserWriteUsingAlternativeSecurityId">
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="extension_AgeRange" />
<PersistedClaim ClaimTypeReferenceId="extension_Gender" />
</PersistedClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Recently, I was looking for a way to sign id tokens in Azure AD B2C using certificates. I found that we have to use custom policy to do this.
Here is how to do it.
Upload a pfx file (Ex. B2C_1A_signing) to "Policy Keys" through "Identity Experience Framework".
Override the token issuer claims provider in your relying party policy. If you are using Active Directory B2C Custom Policy Starterpack, you can overwrite TrustFrameworkBase.xml by default.
<ClaimsProvider>
<DisplayName>Token Issuer</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="JwtIssuer">
<DisplayName>JWT Issuer</DisplayName>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_signing" />
</CryptographicKeys>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Notice that the issuer_secret is changed to reference the storage reference id of the certificate.
Check metadata
{
"keys": [
{"kid":"E62C82DD3E3CED17DFE23D0FFB837E46C5B36182","exp":4652954830,"nbf":1497280630,"key_ops":["sign"],"x5c":["<Certificate>"}
]
}
Kid references the thumbprint of the cert and the cert is listed as x5c.
Send an authentication request.
{
"typ": "JWT",
"alg": "RS256",
"kid": "E62C82DD3E3CED17DFE23D0FFB837E46C5B36182",
"x5t": "5iyC3T487Rff4j0P-4N-RsWzYYI"
}.{
"exp": 1505922183,
"nbf": 1505918583,
"ver": "1.0",
"iss": "https://login.microsoftonline.com/<>/v2.0/",
"sub": "<>",
"aud": "<>",
"acr": "b2c_1a_signup_signin",
"nonce": "defaultNonce",
"iat": 1505918583,
"auth_time": 1505918583,
"name": "Chi Yao"
}.[Signature]