Can't reset B2C account password create via the Graph API - azure-ad-b2c

Hoping someone can shed some light on the following matter;
I got an Angular & .Net core Web API application that uses Azure B2C to authenticate users.
User accounts are created by the users themselves via the signin/signup custom policy or administrator can create accounts via the app using the Graph API.
Due to the requirements, the app uses usernames (as opposed to email addresses) to log into the application. So far I've managed to get everything working except for the following scenario:
When an account is created via the Graph API, the owner of that account cannot reset the account's password. The error is "An account could not be found for the provided user ID".
This isn't the case for accounts that get created via the custom signup policy so I did some comparison and found that for those account that get created via the Graph API, the Email is missing (which can be found under User -> Authentication Methods). I looked at populating that field, but it appears the "Mail" attribute is 'read only' (not sure if that's the right attribute anyway).
At the moment I'm having to manually set the email via Azure so those account's passwords can be reset by their owner if necessary. This is obviously not ideal and wanted to see if there is anyone that might have gotten around this issue, or a least get confirmation that this is indeed a limitation of the Graph API.
Thanks in advance for your help

So I managed to get this working using the approach outlined by Jas Suri. These are the steps that I went through
Created a custom attribute in my B2C tenant to hold the account email address
Included the custom attribute claim type (extension_emailAddress) as well as the strongAuthenticationEmailAddress in the TrustFrameworkBase.xml
Updated my apps's custom policies to include the technical profile for local account discovery. I basically just copied the necessary bits and pieces from here
Updated the local account discovery to perform the comparison against the extenstion_emailAddres instead of strongAuthenticationEmailAddress.
Added an extra step to the Sign up user journey so that the value in strongAuthenticationEmailAddress is copied to extension_emailAddress
Updated my Web API / Graph API "create user" function so that it sets the extension_appidguid_emailAddress
That's it. Now it doesn't matter how the account gets created, the email address will be stored in the extension attribute and the password reset will be able to find the account using that attribute.
happy to provide more details if anyone comes across this.

The problem is as you’ve identified, the Sign Up policy uses the strongAuthEmail attribute to store the verified email for a username based account. The Password reset policy will use this to verify the user owns the username. When creating the user with graph api, you can’t populate this field, it’s not exposed. The only option is to use a custom policy which stores this secure email in an extension attribute, and your graph api created users can then also target the same attribute to allow the stars to align.

Mail attribute is not the same as the Email under Authentication Methods, and currently there is no such graph api to set the Email value under Authentication Methods.
By the way, there is no need to create Azure AD B2C user for a user as users can sign up themselves.

Related

How to access Email of an User on B2C using Graph API

I want to know the email address of a user to send an email.
On my application, people can sign up with social accounts (google/facebook/Microsoft) or local accounts.
When creating a local account we use the email.
I found this info about how email is stored.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-policies
Email address storage: An email address can be required as part of a user flow. If the user authenticates with a social identity
provider, the email address is stored in the otherMails property. If a
local account is based on a user name, then the email address is
stored in a strong authentication detail property. If a local account
is based on an email address, then the email address is stored in the
signInNames property. The email address isn't guaranteed to be
verified in any of these cases. A tenant administrator can disable
email verification in the basic policies for local accounts. Even if
email address verification is enabled, addresses aren't verified if
they come from a social identity provider and they haven't been
changed. Only the otherMails and signInNames properties are exposed
through the Active Directory Graph API. The email address in the
strong authentication detail property is not available
Not sure why the field "Mail" on the user is not being used... but using GraphApi:
I make a GET: https://graph.microsoft.com/v1.0/Users?$select=displayName,mail,otherMails,signInNames
Some emails appear on "mail", others on the array of "otherMails", and "singInNames" can't be selected :( doesn't show any info, so are some users that I can't get the info about the email.
How can I solve this? Only using Azure AD Graph instead of Microsoft Graph API, since on that API signInNames are returned?
Isn't there any way of storing the emails always on the same property? Or at least one that I have access on Microsoft Graph API? Using Custom policies only with Claims transformation?
In the Microsoft Graph API you can use:
GET: https://graph.microsoft.com/v1.0/Users?$select=displayName,mail,identities,otherMails
You can find the email of a local account in the identities collection.
In the BETA version of the Graph API (graph.microsoft.com/beta) the identities and otherMails properties are also returned without a $select, in the v1.0 version only when specified in the $select.
I managed to get the email for a Azure B2C user through the following Microsoft Graph API call:
https://graph.microsoft.com/v1.0/users?$select=identities
You need to collect the email addresses from different places such as mail, otherMails and signInNames through AD Graph API. signInNames is NOT available in Microsoft Graph API.
Note that in the case where users sign in with username + email validation, there is no way to retrieve the email used.
Or you could add a custom attribute in custom policy, where you can require users to type in their email address. After that, you could use AD Graph to get the custom attribute (A sample here).
The Microsoft Graph is the successor of the old Windows Graph. The Microsoft Graph doesn't support the signInNames property for Users object anymore. One has to filter on identities instead. However identities isn't part of the default property set of the User object so one has to select it. Once that's done, one can filter on identities using an any clause.
Note that filtering on issuerAssignedId can only be done when both issuerAssignedId and issuer are used in the filter clause.
GET: https://graph.microsoft.com/v1.0/Users?$select=id,identities&filter=identities/any(c:c/issuerAssignedId eq '{email}' and c/issuer eq '{issuer}')

Custom Azure B2C Password Reset Flow via Username

I setup a password reset flow using Azure B2C and local Azure accounts that uses the user's email address and verification code. However, my client would like to have a password reset email sent to the user based on the user name, not email address. The user email would be looked-up behind the scenes and an email sent that would include a link to the password reset page as shown in the flow below.
After reading a gazillion articles on custom Azure B2C policies, I'm struggling to convince myself if it is possible to do what the client is asking for using Azure B2C.
In the sample password reset flow shown below, some of the areas I'm struggling with include:
Is it possible to create custom pages in the password reset flow such as the page in Step 4 that displays the user's masked email address, or the information page in Step 7?
Is there built-in functionality to look-up a user's email address and Active Directory Object ID based on their user name or would I have to call out to a custom Azure Function and use the Graph API to do this?
Is it possible to create and send a custom email that includes a hyperlink to the password reset page that includes the user's Active Directory Object ID as a query string parameter so the password reset page knows which user's password is being reset?
At the moment, it seems like it would be easier to create a completely custom ASP.NET MVC app to handle the requirements than it would be to use Azure B2C custom policies, but that isn't really a path I want to go down.
Is it possible to create custom pages in the password reset flow?
Yes you can create your own custom password reset user flow using azure active
directory B2C
In your case if you want to figure out your custom page you could
refer here
Is there built-in functionality to look-up a user's email address and
Active Directory Object ID based on their user name or would I have
to call out to a custom Azure Function and use the Graph API to do
this?
Using Microsoft Graph REST API you could fetch your user
information.
In your case you could use
List users
Get a user
To access user information you could also refer here in a great
details
Is it possible to create and send a custom email that includes a
hyperlink to the password reset page that includes the user's Active
Directory Object ID as a query string parameter so the password reset
page knows which user's password is being reset?
You can use the company branding feature to customize the
content of verification emails for resetting password.
Note : For better clarity you could check the Azure AD B2C: Frequently asked
questions (FAQ) before final work around Which definitely guide you to
define ultimate go ahead.
Update
As per Microsoft document right now you cannot create according to your sample exactly. See the screen shot there is and important remarks.
Thank you.
This GitHub project covers the case you describe. Still needs a lot of understanding about custom flows to get it working.
https://github.com/yoelhor/aadb2c-verification-link

Azure B2C custom attribute/claim added to existing user directory throws error on sign in

I have a custom policy which adds a custom value, HoldingId, to new users who sign up (using these docs) as the value is passed to the policy via the token (along with verified_email).
I was hoping to not need to create a custom policy for sign in, so used the Azure Portal UI to create the custom attribute against the b2c-extensions-app application (and am using the respective client and object ids to line it up with the custom policy), and using the Portal have added this custom attribute to the sign up/sign in policy claims.
Using the Graph API, I have been able to successfully confirm that the custom value is saving against newly signed up users (returning as extension_[AppId]_HoldingId), and these new users are able to sign in subsequently without issue using the built in sign in/sign up policy.
However, any users which already existed in the directory are no longer able to sign in. Unfortunately, because it's a built-in policy, I'm not sure of a way to dig into the logs a-la App Insights to see what's going on.
My suspicion is that because these existing users don't have this custom attribute against them, the built-in sign up/sign in policy is attempting to get this value and failing.
Is it possible to get the built-in policies to ignore this attribute on users who don't have this attribute set, or will I need to create a custom policy to handle this scenario with a default value?
For context, the HoldingId is not required for existing users (application needs to be backwards compatible). This is also my first venture into B2C, so I'm still learning many of these concepts.

Azure AD B2C user name recovery

I am using username for the identity provider for local account.
When an user forget their username, is there a out-of-box policy that handle the username recovery? Or I have to implement it my own?
If I implement my own, as sign-in policy doesn't have UI customization that I will not be able to add a link for "For get your username" to redirect the user to my code to retrieve their username. Is there a way adding links on the Sign-In page?
There is no out of the box policy for forgotten username. It seems a nice feature though. But I anyway enforce usage of e-mail as username. And frankly, the way to implement this is a bit of a tricky.
You can first get (and confirm) users e-mail address which is registered with the AAD B2C. You have to send him/her an e-mail with a code to make sure that he/she owns the e-mail. Once you get e-mail confirmation, you can query the Graph API for the list of users and search for the provided e-mail.
As for providing link - you can have fully customized "Sign-in or sign-up" policy, where you can put the link. You need to use the special sign-in or sign-up policy, because currently it is the only one that allows for full user experience customisation.

Azure AD B2C sign up policy additional emails

Is it possible to get Azure AD B2C to store alternate emails so we can help recover the account? I am using a signup policy that is based on a local account. I am not using username, I'm using "email" as the identifier.
Even though I specify the local account type as email and also specify a signup claim of email, it only let's me put in one email. I can see how that might make sense.
I tried just storing an additional email in one of the existing graph fields, but it said that was read only.
Along those lines, is it possible to have more than one email listed in the signInName array?
TIA

Resources