Azure AD B2C Internal Error uploading Custom Policy - azure-active-directory

I am experiencing an issue where a set of custom policies that upload without issue to one tenant (development tenant), fail to upload to another (production tenant). The policies function correctly on the (working) development tenant.
I upload the files in the following order:
TrustFrameworkBase.xml uploads OK
TrustFrameworkExtensions.xml uploads OK
SignUpOrSignin.xml fails with above error
ProfileEdit.xml fails with above error
PasswordReset.xml uploads OK
The only clue I have is that if I query the extension claims in the B2C app for the failing tenant, it only shows 2 out of 8. If I run the same query against the working tenant, it shows all 8. I am doing this querying using this example app: https://github.com/AzureADQuickStarts/B2C-GraphAPI-DotNet.
As far as I can tell, the two tenants are configured the same, and I have checked the various IDs etc are configured correctly. But it is always possible I have missed something!
Can anyone help?
The xml files: https://1drv.ms/f/s!ApxUZQaL9hp0h1ACYgWzgzsGwCOc
More info
I can actually run the policies that upload with an error. But when I try to create an user account via running the policy I get a message saying "Unable to validate the information provided." at the top of the page, inside the <div> with the id claimVerificationServerError. This may tie-up with the missing extension claims in the B2C app. So it looks like the problem is with creating the extension claims. But the same policy uploads and works on another tenant. How could the extension claims be valid on one tenant, but not on another?

In your base policy, there is the following claim of dateOfBirth:
<ClaimType Id="extension_DateOfBirth">
<DisplayName>Date of Birth</DisplayName>
<DataType>date</DataType>
<UserHelpText>Date of birth</UserHelpText>
<UserInputType>DateTimeDropdown</UserInputType>
<PredicateValidationReference Id="DateOfBirthDateRange" />
</ClaimType>
Since this claim starts with "extension_" and it is used in a technical profile with "AAD-" as prefix, it will be automatically created as an extension attribute in AAD during the policy uploading. However, the DataType "date" is not supported (only DateTime is supported) in AAD. This is causing policy uploading failure.
Regarding how to map "date" claim in B2C policy to AAD "DateTime" attribute, I will reply back to this thread after more investigation on these policies is done.
Edit: I was trying to find this doc: https://msdn.microsoft.com/Library/Azure/Ad/Graph/api/entity-and-complex-type-reference#extensionproperty-entity when I first replied but could not find it. Thanks Mat for sharing. Hope this link is helpful for solving issues related to datatype of extension attributes in AAD.

Extension attributes need to be created at a per tenant basis. So if your policy requires extension attributes, you need to create them explicitly.

Related

Azure B2C - Can't get a B2C user flow to work with another Azure AD instance as a custom identity provider

I have set up a B2C instance OK and managed to get a basic Blazor (server) app working with it a using the Microsoft Identity Platform (using AD groups for permissions - it was a hassle but works).
However, I'm trying to use an external Azure AD as a custom identity provider in the user flow, so that I am not just restricted to just email/id/social accounts, but can have guest accounts from other directories use the app without having to manage their sign-in's. To do that I performed a web app registration in the AD tenant that I wanted to use to authenticate those accounts against (as suggested in a couple of tutorials).
The application I registered in the external AD has a Redirect URI in the format "https://{My B2C Directory Name}.b2clogin.com/{My B2C Directory Name}.onmicrosoft.com/oauth2/authresp", which matches the name of my B2C instance, and I have added the client id and secret generated from that app registration and put the details into the custom identity provider I have created for the sign-in flow, as per the instructions here (including the mappings etc.):
https://learn.microsoft.com/en-us/azure/active-directory-b2c/identity-provider-azure-ad-single-tenant?pivots=b2c-user-flow
I also found a slightly older tutorial here, which is pretty similar (different mappings) that I've tried to follow (and adapt the bits that are out-of-date).
https://medium.com/the-new-control-plane/connecting-azure-ad-b2c-to-azure-ad-via-the-b2c-custom-identity-provider-42fbc2832e32
However when I run the user flow I get "AADSTS900971: No reply address provided." - this happens even when I run the flow directly from the User Flows tab in B2C with a 'Reply URL' explicitly set to "http://jwt.ms" (just to capture the token contents).
I'm confused about the reply URL being missing because they exist in both registered apps. Also, it's not saying they're mismatched, just that one isn't set at all (but appears to be).
It feels like I'm missing something simple - does anyone have any idea what that might be?
Ok so I did a couple of things to resolve this:
Re-registered the application in the AD I want to authenticate with (following this tutorial again: https://learn.microsoft.com/en-us/azure/active-directory-b2c/identity-provider-azure-ad-single-tenant?pivots=b2c-user-flow)
I was careful to ensure that the redirect URI in the format:
https://{B2C Instance Name}.b2clogin.com/{B2C Instance Name}.onmicrosoft.com/oauth2/authresp
was all lower case.
I also had to change from just a 'sign-in' user flow to the 'sign-up, sign-in' one, and then applied the custom identity provider to that flow. Apparently you need that even for users from another AD to be able to complete their invite process (otherwise you just end up with a user doesn't exist error - even if you've invited/added them to the B2C users list).
I also elected to 'Grant admin consent for Default directory' under the API Permissions tab for the application being registered in the external AD (to be used for the custom identity provider).
The flow seems to work now. The only thing that would be useful would be to have an invite only sign-up, sign-in flow so that you could invite specific people without breaking the invite process.
If anyone knows how to do that please do post something.

Azure Active Directory override claim value in OIDC id-token

I'm looking for a way to ensure that the unique_name claim value is always the user email for a specific app in AAD which is accessed via SSO. I've noticed that for users which have an AAD account, the unique_name claim value is the email address, but for external users (invited to the directory) it is prefixed by "live.com#" (e.g. live.com#email#domain.com). The application uses the OIDC protocol. I've been trying different things from Microsoft docs:
Setting a different source for the unique_name claim
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-saml-claims-customization
(I'm not sure if this applies, given the app uses OIDC, not SAML)
(By the way, that documentation is a bit out of date because I found that the "User Attributes & Claims" section is now in SSO https://learn.microsoft.com/en-us/answers/questions/248748/cant39-find-the-34user-attributes-amp-claims34-sec.html)
Building a claim-mapping policy
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-claims-mapping
None of these worked.
I know this would be trivial in AAD B2C with custom policies. Is it possible to override the unique_name claim with the email claim in AAD?
Update 07/01/2022
After further investigation I found that the unique_name claim is only supported in v1 tokens https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens, https://github.com/MicrosoftDocs/azure-docs/issues/62971 (the current version is v2) and it's transformed into "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" by the ADAL client. This customization I'm after is for a legacy .NET app which uses ADAL on the v1 AAD endpoint.
The only way I can think of how to achieve this is via a claim-mapping policy, however I haven't been able to do make it work. Any ideas would be appreciated.
I believe I've found an answer to my question and the conclusion is that it's not possible to override the unique_name claim, because it's a restricted claim. The closest I got was to map the mail claim to a custom claim (e.g. unique_name2). This is what I did:
https://learn.microsoft.com/en-gb/azure/active-directory/develop/active-directory-claims-mapping
I installed the Azure AD PowerShell Module public preview (I had to uninstall the AD Powershell module first because I already had a later version)
I followed the instructions on the document above to connect to AAD and view any existing claim mapping policies
Connect-AzureAD -Confirm
Get-AzureADPolicy
I followed the instructions on https://learn.microsoft.com/en-us/answers/questions/80295/claim-transformation-in-azure-id-token-upn-data-to.html to build a claim mapping policy, although I had to adapt it because it wasn't working. I ran the following commands:
3.1 I used the search command to search for my app (called "test").
GET-AzureADServicePrincipal -SearchString Test
This outputs a table like the following:
ObjectId AppId DisplayName
3.2 I ran the following command to create a new mapping policy which maps the "mail" claim to the "unique_name2" claim. (When I tried mapping to "unique_name" it works, but the "unique_name" claim doesn't get overridden, because it's a restricted claim)
$Policy=New-AzureADPolicy -Definition
#('{"ClaimsMappingPolicy":{"Version":1,"IncludeBasicClaimSet":"true",
"ClaimsSchema":[{"Source":"user","ID":"mail"},{"Source":"transformation","ID":"DataJoin","TransformationId":"JoinTheData","JwtClaimType":"unique_name2"}],"ClaimsTransformations":[{"ID":"JoinTheData","TransformationMethod":"Join","InputClaims":[{"ClaimTypeReferenceId":"mail","TransformationClaimType":"string1"}],
"InputParameters":
[{"ID":"string2","Value":""},{"ID":"separator","Value":""}],"OutputClaims":[{"ClaimTypeReferenceId":"DataJoin","TransformationClaimType":"outputClaim"}]}]}}')
-DisplayName "MapMailToUniqueName2" -Type "ClaimsMappingPolicy"
3.3 I ran the following command to add the custom policy to my app service principal (copying the id from step 3.1). This means the policy will be applied only to that specific app.
Add-AzureADServicePrincipalPolicy -Id {my app service principal id}
-RefObjectId $Policy.Id
That's all. When I tested SSO on my app, I had an additional claim "unique_name2" which contains the value of the "mail" claim.
There probably is a more efficient way of creating the mapping policy in step 3.2 but the way described in the step 3 link wasn't working for me so I came up with a concatenation to a blank string.
It doesn't seem possible to override the unique_naim claim because it's a restricted claim. I later found that this is actually documented here https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory/develop/reference-claims-mapping-policy-type.md. I wish I had found this earlier.

Is there something special I need to do to ensure the AAD Connect synchronized extension attribute is included in the token claims?

I have a query about adding extension claims to an idToken using MSAL.JS 1.1.3 – it seems to work where an extension attribute was added into an AAD application but not via AAD Connect.
Is there something I need to do to ensure the AAD Connect synchronized extension attribute is included in the token?
I have the following setup with 2 extension attributes (extension_{id}customOptionalclaimApplicationUserCode (added in AAD) and extension{id}_stuExtensionAttriibute1 (added to AAD via AAD Connect from on-prem AD):
PowerShell displaying attributes
Customer wants to use manifest so I set this up.
The decoded token only includes extn.CustomOptionalClaimApplicationUserCode as per this image
The customer prefers to use manifest optional claims as per the example for least privilege per application instead of claims mapping policy.
To repeat the question: Is there something special I need to do to ensure the AAD Connect synchronized extension attribute is included in the token claims?
From your screenshot, extension_{id}_customOptionalclaimApplicationUserCode 's id is different from extension_{id}_stuExtensionAttriibute1's id.
One of the two ids is the id of the app itself. The other one is the app id used by AD Connect.
Now, the fact is that, from the API , one extension attribute is lying on an application.
However, you can only get the extension claim value from its application in a token. In other words, the resource id should be the same as the id in the extension, then you can get the extension value. For more details, you may refer to: Configuring optional claims
So, the result you got is expected. The extension synced from on premise will not be included in token.

Empty GUID error when using Azure AD consent flow

I'm currently trying to integrate with Azure AD using the admin consent flow.
I've set up an app in our domain, set a few permissions on it and am then navigating to the following link:
https://login.microsoftonline.com/mytestdomain.onmicrosoft.com/oauth2/authorize?client_id=12345678-1234-1234-1234-123456789012&response_type=code&redirect_uri=http://example.com/responsehandler&resource=12345678-1234-1234-1234-123456789012&prompt=admin_consent&state=12345
(Some of the values here have been swapped out for "example" values)
When I navigate there I get asked to sign in, which I do using a different test domain into which I want to import the app.
After signing in I'm shown a list of all the permissions that the app needs (which appear to be correct), I click accept but then I get the following error:
AADSTS90002: Requested tenant identifier '00000000-0000-0000-0000-000000000000' is not valid. Tenant identifiers may not be an empty GUID.
I'm not sure where this empty GUID is coming from and after some searching I can't find any reference to what might be causing it.
Daniel Camargo's comment above seems to have done the trick.
When I navigated to the login.microsoftonline.com link I was logging in with the user that created the domain.
If I log in with a test admin user that I created it works as I'd want.
I am not convinced that we had exactly the same problem, given that my case was involving a Cordova application, but I will share my scenario anyway:
I created a trial account for my proof of concept and for that I used my personal Microsoft account that I will call mypersonalaccount#outlook.com.
Thus, mypersonalaccount#outlook.com is now part of 2 directories: the outlook.com and my recently created mypersonalaccount.onmicrosoft.com.
When I was trying to authenticate in my Oauth2 application using mypersonalaccount#outlook.com I got that error. My humble guess is that the error is related to some sort of collision between the 2 accounts.
I later created a user1#mypersonalaccount.onmicrosoft.com and a guest account using my gmail account. Everything worked fine with these ones.
Was having the same problem, and the same after 1 week of work by the azure team, was solved.
My problem was being trying to log in to VSTS with AAD accounts.

Microsoft Graph APIs: conditional access policies

A follow up on my earlier question - Are there any APIs available to manage conditional access policies for a tenant?
I'm using the API (https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/policy_list) to retrieve the list of policies created for my tenant and have been running into permissions issues.
According to the documentation this API requires a scope of Directory.AccessAsUser.All. On the Azure AD portal, I set the permissions for my test App to include "Read and write directory data" and "Access the directory as a signed-in user". I set these permissions on both Windows Azure Active Directory and Microsoft Graph APIs. When I make a call to https://graph.microsoft.com/beta/policies, I keep getting 403 Forbidden with the error message "Insufficient privileges to complete the operation.". The other operations like getting the users in the directory, getting identityRiskEvents, etc all work fine.
Am I missing anything here?
Thanks in advance!
Actually the answer is no. The GRAPH REST API List Policies does not return conditional access policies yet.
The REST API doc states:
Currently only one type of policy is available:
Token Lifetime Policy - Specifies the lifetime duration of tokens
issued for applications and service principals.
Check the microsoft faq documentation on configuring conditional access.
Are Graph APIs available for configuring conditional access policies?
Currently, no.
FAQ Link
No, There is a REST API List policies of Operations on policy described in Graph API reference, which you can use it to list all policies for your tenant.
Edit: This article lists only Token Policy's are being returned at this moment: https://learn.microsoft.com/nl-nl/graph/api/resources/policy?view=graph-rest-beta
Microsoft have recently released access to conditional access policies in their Graph API beta (https://learn.microsoft.com/en-gb/graph/api/resources/conditionalaccesspolicy?view=graph-rest-beta). The current methods they support for the conditional access policy resource type are:
List
Create
Get
Update
Delete
Similar methods are available for named locations included in a policy.

Resources