We have a custom policy to allow users to delete their accounts, following something similar to https://github.com/azure-ad-b2c/samples/blob/master/policies/delete-my-account/policy/DeleteMyAccount.xml
If we then invoke another custom policy the B2C session is still active. The technical profile below still pulls out the old (deleted) objectId.
<TechnicalProfile Id="SM-AAD">
<DisplayName>Session Mananagement Provider</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.DefaultSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="objectId" />
</PersistedClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectIdFromSession" DefaultValue="true" />
</OutputClaims>
</TechnicalProfile>
I see references to invalidateAllRefreshTokens invalidating the browser session, but then see many discussion saying this is not the case.
If there still not a way to invalidate the session, or call logout from a custom policy.
Thanks
Nigel.
Related
Scenario is that during combined SignIn/SignUp flow I'm using following TechnicalProfile for signing in the user with local account:
Base.xml
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
<DisplayName>Local Account Signin</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="SignUpTarget">SignUpWithLogonEmailExchange</Item>
<Item Key="setting.operatingMode">Email</Item>
<Item Key="ContentDefinitionReferenceId">api.signuporsignin</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
<OutputClaim ClaimTypeReferenceId="password" Required="true" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
Extensions:
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
<Metadata>
<Item Key="setting.forgotPasswordLinkOverride">ForgotPasswordExchange</Item>
</Metadata>
</TechnicalProfile>
Base.xml is taken from one of the starter-packs available on GitHub.
This is working fine and when I'm logged in and go to combined SignUp/SignIn policy again, I'm authenticated automatically without needing to provide any credentials or to select external IdP.
Now, for some other flows (ProfileEdit, PasswordChange) I've slightly modified SelfAsserted-LocalAccountSignin-Email technical profile to not show SignUp/ForgotPassword links.
Technical profile definition:
<TechnicalProfile Id="SelfAsserted-LocalAccountSigninOnly-Email">
<DisplayName>Local Account Signin</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="setting.showSignupLink">False</Item>
<Item Key="setting.forgotPasswordLinkLocation">none</Item>
</Metadata>
<IncludeTechnicalProfile ReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</TechnicalProfile>
As you can see, it includes the SelfAsserted-LocalAccountSignin-Email and just overrides two setting values.
However, now when the user is authenticated after executing combined SignUp/SignIn policy and he goes to my ProfileEdit policy, he is prompted to authenticate again.
This happens only if user was authenticated using local account, as in my case SignUp/SignIn & ProfileEdit/PasswordChange policies are using different (but very similar) SelfAsserted technical profiles. If user was authenticated using any social idp, ProfileEdit/PasswordChange policies work fine without prompting user for reauthentication.
Any ideas how to solve the issue for the local account?
One solution would be to use the same technical profile for combined SignUp/SignIn and ProfileEdit/PasswordChange and then hide links where necessary using JavaScript, however, if possible I would like to minimize changes made by JS.
We need to see the feasibility of synchronization of user credentials
between the Microsoft AD B2C and proprietary database in real time.
If it is feasible do you have any pointers on 'how to'.
What is the hashing algorithm used in the MS AD B2C credentials? is
there a ay to customize it?
Use a REST API call during the Sign Up and Password Reset authentication journey's to send the captured password claim to your API. Your API can then update your DB to keep it in sync.
You can call your REST API and can send any claims captured in the journey using this guide.
In this case, since you are looking to send a password, you must call your REST API as part of a validation technical profile, instead of directly as an orchestration step.
You can send the plaintext password to your API.
Here is an outline of what you need to configure:
In the sign up technical profile, add a call to your REST API as a validation technical profile.
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
...
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
<ValidationTechnicalProfile ReferenceId="REST-SyncPasswordToDB" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
Create the REST API technical profile to send the password to your endpoint:
<TechnicalProfile Id="REST-SyncPasswordToDB">
<DisplayName>REST API call to communicate with Legacy DB</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://myApi.com/api/syncPassword</Item>
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">True</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="email" />
<InputClaim ClaimTypeReferenceId="password" />
</InputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
I am trying to send the password as part of output claims but it never comes up. I tried to create a new extension variable and do a tranformation copy claim but that didnt work either.
I would like to hash the password and store it in external system to work around the issue of not repeating password as thats a security requirement.
If I try to add
<OutputClaim ClaimTypeReferenceId="password" />
as part of
<TechnicalProfile Id="login-NonInteractive">
and the whole login screen stops working.
Please let me know if I am missing something and also on how to hash the password to send it to an external RestAPI Technical profile
REST API that I used
<ClaimsProvider>
<DisplayName>REST API</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="REST-API-ValidatePassword">
<DisplayName>Encrypt the password and validate it against previous passwords</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">https://test********</Item>
<!--<Item Key="ServiceUrl">https://your-azfunc-api.azurewebsites.net/api/EncryptClaims</Item>-->
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">true</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
<InputClaim ClaimTypeReferenceId="password" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="passEncrypted" PartnerClaimType="passEncrypted"/>
<OutputClaim ClaimTypeReferenceId="isPasswordUsed" PartnerClaimType="isPasswordUsed"/>
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
As per this:
"AAD and AAD B2C do not maintain a password history. Currently therefore you can only prevent the last password from being used.
We don’t recommend using external systems to maintain a password history."
Have a look at this sample.
You could perhaps copy the password to an extension attribute and output that but then you are exposing the password.
A better way is to use a REST API that saves the password so everything is done server-side.
You can try doing this by copying password claim when it is available. You just need to remember that copying password to another claim makes it vulnerable to logging etc. You need to do it with proper care.
To have a copied password value you need another claim:
<ClaimType Id="pwd">
<DisplayName>Password</DisplayName>
<DataType>string</DataType>
<AdminHelpText>password</AdminHelpText>
<UserHelpText>password</UserHelpText>
<UserInputType>TextBox</UserInputType>
</ClaimType>
then, a claim transformation:
<ClaimsTransformation Id="CopyPass" TransformationMethod="CopyClaim">
<InputClaims>
<InputClaim ClaimTypeReferenceId="password" TransformationClaimType="inputClaim" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="pwd" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
and that claim transformation added to a proper technical profile:
<TechnicalProfile Id="eSTS-NonInteractive">
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CopyPass" />
</InputClaimsTransformations>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="pwd" />
</OutputClaims>
</TechnicalProfile>
You should be able to use pwd claim value (containing actual password) for whatever you need then.
I am working on integrating Azure AD B2C into an existing shopping cart application, replacing an existing user identity solution.
I have already created a custom policy to implement user registration / sign-up and integrated it into the normal account creation process. However, I am having a problem with integrating registration during the checkout process.
With the old IDP, the checkout process first collects the user's name and email address. After that has been collected, the user is given the option to create an account with that information (if they are not already logged in). In order to avoid confusing double-entry of the email address, I would like to pass the email address that the user already entered to the B2C sign-up policy and have it fill in the email address input on the form.
Is there any way to do this? I don't find anything like this being addressed in the B2C documentation.
You can use a sign up policy with a claims resolver. Send the email in the query parameter. It’ll prepopulate the email into the text box.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/claim-resolver-overview
Based on the documentation linked by #JasSuri, I was able to come up with a solution.
To implement this, you modify the sign-up technical profile. You must add three things:
Add item IncludeClaimResolvingInClaimsHandling with value true to the metadata
Add a DefaultValue attribute to the email input claim with an appropriate claims resolver notation as the value
Add an AlwaysUseDefaultValue attribute to the email input claim with true as the value
I used an Oauth2 key-value claims resolver (which supports arbitrary query string parameters) and a query parameter named register_email.
The resulting technical profile looks like this:
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
<Item Key="language.button_continue">Create</Item>
<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item> <!-- ADD THIS -->
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<!-- ADD DefaultValue AND AlwaysUseDefaultValue ATTRIBUTES BELOW -->
<InputClaim ClaimTypeReferenceId="email"
DefaultValue="{OAUTH-KV:register_email}"
AlwaysUseDefaultValue="true" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
<OutputClaim ClaimTypeReferenceId="newUser" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
I need some advice on Customising Azure B2C.
I've been looking at both portal based customisation and the Identity Experience Framework.
My key requirement is to have full control of the look and feel of the login experience. However, users must not be able sign up as this is handled by a separate business process. I understand that I cannot use a simple SignIn policy as B2C doesn't provide the required level of customisation.
I'm unable to find any solid documentation that describe how/if this is possible.
I've followed this documentation for the Azure B2C Identity Experience Framework. But can't see where I would be able to disable signup.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-get-started-custom
You can disable the sign-up button using the setting.showSignupLink metadata:
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
<DisplayName>Local Account Signin</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="setting.operatingMode">Email</Item>
<Item Key="setting.showSignupLink">false</Item>
<Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
<OutputClaim ClaimTypeReferenceId="password" Required="true" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>