Is it possible to cancel or forcibly expire an AAD B2C invite link? - azure-ad-b2c

I have an app that uses AAD B2C user management. Users can send invite links via email. The invite link has an expiry of 7 days according to the JWT config. We store the invitation as application data.
Because registration is handled within the policy it has no visibility of invitation state. However, I want to give existing users the ability to cancel an invite, thereby preventing the invitee from completing the policy and signing up.
Similarly, the policy only checks for email conflicts after the form has been submitted, despite already being served with the invited email. Is it possible to have the policy check the validity of the invited email before it serves the form?
<!--Sample: Set input the ReadOnlyEmail claim type to prefilled the email address-->
<InputClaim ClaimTypeReferenceId="readOnlyEmail" />
So my point is: what do I need to do to get the policy to validate the invite link before it gets served? I haven't found anything via Google so apologies if this is trivial.

What you could do is add an extension attribute to B2C that could be set via Graph API e.g. a PS script.
This would be set by the user on the invitee's B2C directory entry. This would be used when they wanted to invalidate an invite.
The policy would then check this attribute.
If set to false i.e. reject, then the policy would error out.

Related

Can't reset B2C account password create via the Graph API

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.

How to Disable verification code emails when the user is not registered in Azure AD B2C

Azure B2C Password-less sign-in with email verification sends the verification code to every email address (Even if no user is not registered in directory) .after entering OTP(Non-Registered user) B2C validated the code and says “E-mail address verified. You can now continue”.
Now when the users click “Continue” they get the error “An account could not be found for the provided user ID.” .This is where we got sure about non-registered user.
I found this solution but not getting results after updating my current policy.
I am including my updated extension file here .
Or if it has another approach on How to Disable verification code emails when the user is not registered in Azure AD B2C.
Change
<ClaimsExchange Id="SignIn-WithEmail" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress-SignIn" />
To
<ClaimsExchange Id="SignIn-WithEmail" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress-AcctExists" />
Now your user journey will call your technical profile which uses the emailVerificationControl display control which contains the logic to only send the email OTP if the account exists.
I have tried this policy (Link attached), and it works perfectly fine.
https://github.com/azure-ad-b2c/samples/tree/master/policies/pwd-reset-email-exists
The right approach is not to spam users by sending verifications emails to those who are not registered, and also not telling users that email is incorrect or the account doesn't exist because, that way attackers will find out if that is an incorrect email, and to prevent Brute-force attack on your login page.
So, therefore, you use can that policy to disable verification code emails, and also turn off the Raise Error flag (RaiseErrorIfClaimsPrincipalDoesNotExist=false):

How to pre-create users with shared mail for password reset via Graph API

How is it possible to pre-create users programmatically (via Graph-API) and have a same mail address configured for them to be used along with the password reset user flow?
I figured that the signInNames mail or StrongAuthenticationUserDetails mail attribute are being used with the standard flow. BUT, signInNames are unique and StrongAuthenticationUserDetails (Authentication contact info: Email) is not editable via Graph API as of now.
Any idea how to accomplish the scenario above without developing our own password reset flow?
I assume the scenario is creating user by invitation, where customer changes their password after first login.
Here is the sample for doing that
https://github.com/azure-ad-b2c/samples/tree/master/policies/invite
If you want to use the user flows,
You can create a user account as mentioned below, and then set the password reset user flow link to them. But then you will need to ask your customers to update profile as well, so that you know more about them.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet?tabs=applications#create-consumer-user-accounts

Azure B2C with pre-invited users

I maintain an app where we use Azure AD B2C to authenticate.
The flow is this:
Users are invited by email
They click a link to sign up using a B2C signin/signup flow
They fill in their info, including email address
They are redirected to our app
Now, what bothers me is that the users have to enter in their email address, even though we already know it. We just invited them using their email address.
It has been suggested that we could send people to a password reset page instead. But that doesn't seem ideal either, since they then have to verify their email address, even though we just verified it. After all, they started the flow by getting an email.
In many cases the users mis-type their email address when they are asked for it. That creates a lot of new issues, because we now have two different email addresses for the same users.
Similar question already answered # How to pass email suggestion to Azure AD B2C SignUp page. Answer https://stackoverflow.com/a/56503578/341185 describes how to send invitations.
Alternate approach using Javascript in custom policies
You can use custom policies along with Javascript to show email of the user in email address text box.
Approach:
While sending invitation link, send an extra query parameter like &email_hint=azureb2ccustomer#b2clogin.com and follow below steps to show this email_hint value in email address text box
Steps:
Enabling Javascript in custom policies https://learn.microsoft.com/en-us/azure/active-directory-b2c/javascript-samples
Change page contract to allow custom policies to run javascript https://learn.microsoft.com/en-us/azure/active-directory-b2c/page-contract
Update SignupOrSignin user journey to directly take to SignUp page https://stackoverflow.com/a/56503494/341185
Update your blob HTML page to read query parameters and put the value inside email textbox
var urlParams = new URLSearchParams(window.location.search);
document.getElementById("email").value = urlParams.get('email_hint');
Click here for example request
Add your comments if you still require any other kind of approach than described above to fit into your business model.
If you want to use custom policies, you can use the flow for password reset that has:
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=JWT
This puts the email address in a JWT so the user does not have to enter it.

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.

Resources