Azure Active Directory B2C custom error page is ignored - azure-active-directory

We have a custom Azure AD B2C Sign-in/Sign-up policy in place (SAML-based, the default policy doesn't do what we need).
We're able to customize the page UI as expected, via a content definition like:
<ContentDefinition Id="api.localaccountsignin">
<LoadUri>https://example.com/SAMLSignIn.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Local account sign in page</Item>
</Metadata>
</ContentDefinition>
But attempting to customize the error page, via:
<ContentDefinition Id="api.error">
<LoadUri>https://example.com/SAMLErrorPage.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:globalexception:1.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Error page</Item>
</Metadata>
</ContentDefinition>
changes nothing. The SAMLSignIn.html page is still used (albeit with the contents of whatever signin error occurred). This happens whether we test with invalid user names, bad passwords, whatever.
Even setting
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
in the associated <ValidationTechnicalProfile> doesn't force the error.
The user journey as seen in ApplicationInsights shows only a Web.TPEngine.Providers.BadArgumentRetryNeededException; no other errors or exceptions are logged.
How can we cause a custom error page to be used on login failure (for whatever reason)?
The documentation, such as it is, seems to imply we're doing the right thing (as does How to Create a Custom Error Page in Azure AD B2C | Custom Policies). I can't find any suggestion that we need to specify custom error handling in the UserJourney, nor any means by which we could do so if we wanted.

To summarize:
You are using local account sign-in with SAML issuer. This makes sign-in process happen on Azure AD B2C sign-in page. The error messages you see are just regular validation error messages. This all happens on the sign-in page, not the error page. Error content is only used by the engine when an unhandled exception breaks the execution of the user journey. Which is not the case with a regular sign-in.
Your option to customize validation errors are limited to using pure CSS on the sign-in page.
A really complex customization is demonstrated here
The document describing UI customization in general, is here
And UI customization using custom policy here
At your best effort you will come with some nice error messages like these:

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 AD B2C: Persisting a default value for a claim during local sign up

In my application I'm trying to use a custom user attribute, extension_Role, that should be persisted to the user during sign up.
I'd like one class of user, say "Customer" to sign-up via a mobile application and not need to provide the Role field, just default it to "Customer" behind the scenes. A second class of user will sign-up using a web app, and I'd like them to be able to select the role from a drop-down, say "Support", "Admin", etc... My plan is to provide two versions of SignUpOrSignin.xml to handle this.
Using the sample policy files Microsoft provide in the starter pack I've defined my custom ClaimType (with no UserInputType) in TrustFrameworkBase.xml and configured the client and object IDs. I've also modified the AAD-UserWriteUsingLogonEmail TechnicalProfile to persist the claim.
I'm stuck with actually persisting a default value. I've tried adding:
<OutputClaim ClaimTypeReferenceId="extension_Role" AlwaysUseDefaultValue="true" DefaultValue="Customer" />
to SignUpOrSignin.xml, however when I run the flow, I get a 500 error once I click on sign up. I think this is because it is expecting that the extension_Role field should be filled in by the user.
The only way I've been able to persist extension_Role is by adding it to the LocalAccountSignUpWithLogonEmail TechnicalProfile in TrustFrameworkBase.xml. For example:
<OutputClaim ClaimTypeReferenceId="extension_Role" DefaultValue="Customer"/>
However since this in the base file, it is shared by all login flows, which would prevent me from setting different values for different sign up flows.
What is the correct way to model this kind of dual sign-up flow?
You must specify the UserInputType when you collect information from the user by using a self-asserted technical profile. See reference here. It is why you get 500 error.
Please note that the Claim you set in SignUpOrSignin.xml (with <OutputClaim ClaimTypeReferenceId="extension_Role" AlwaysUseDefaultValue="true" DefaultValue="Customer" />) will be only returned after your sign-up at that time. The custom attribute won't be stored into Azure AD. That means when you want to query the custom attribute later, you won't find it.
So you have to set the value of extension_Role in Base policy file rather than SignUpOrSignin.xml.
In this scene, you should define two TechnicalProfiles for LocalAccountSignUpWithLogonEmail and one accepts user input, and the other one sets DefaultValue for your custom claim.
Then reference them separately from your two SignUpOrSignin.xml.

Custom error messages or error page in Azure AD

Is there a way to configure custom error messages or maybe even a custom error page in Azure Active Directory to display when something goes wrong during sign in instead of the "Sorry, but we’re having trouble signing you in." text and error details?
I was not able to find any documentation on this but after further digging I found that there is a errorUrl parameter in the application (app registered in the AAD and used for sign in) manifest. My initial thought was that in case of an error MS/AAD would redirect to this url with the error codes but as far as I have tested this errorUrl url does not seem to be used at all.
What is the errorUrl parameter meant for and is there realy no way to specify/configure custom error messages?
No, there is no way to specify custom error messages or error pages.
In certain flows, in certain cases, the error message is passed back to your application (instead of being displayed in the Azure AD sign-in page) where you can deal with it as you see fit. (I don't believe there is any standard guidance on which error cases result in an error returned back to the app.)
If you want to custom error page, you can use custom policy in Azure AD B2C. For more details, please refer to the article

Is Kentor.AuthServices logging out correctly?

I'm implementing a Service Provider proof-of-concept for SAML/SSO authentication using Kentor.AuthServices. The use case is a kiosk style application on which numerous different users may be authenticating one after another as they sign up for our service.
The problem I'm having is as follows: after logging out the user is unauthenticated as expected (User.Identity.IsAuthenticated == false). But when the next user goes to log in, the previously logged out user is re-authenticated without having to enter credentials. Is that expected behavior? If so, is there a way to prevent the behavior (other than manually dumping cookies)?
What is most likely happening is that you are indeed terminating the local session on the SP. But when you try to log in again, the Idp still has an active session and automatically reauthenticates with that one.
To work around that you need to use Single Logout. AuthServices has support for that as of 0.17.0. To enable it, you need to have a service certificate configured (logout messages need to be signed). And of course your Idp must support it. Check for Logout endpoints in the Idp metadata.

What is the 'sign-on url' in a Windows Azure Active Directory application?

I have configured my first application in Windows Azure Active Directory and everything works fine: I can login using accounts in my directory.
However, I'm not entirely clear on all the concepts yet, especially the sign-on url. The tooltip says:
The URL where users can sign in and use your app. You can change this later.
But users sign in somewhere on login.windows.net and furthermore, it doesn't matter what I enter here, authentication keeps working. So what is this 'sign-on url'?
If you visit http://aka.ms/myapps, you'll find a long list of applications that have access to your account. If you click on these apps, you should be redirected to a home page where the sign-in process could be initialized. However, if the app doesn't declare a signInUrl in its manifest, you'll get an error that says the app is misconfigured.
something went wrong...
You cannot access this application because it has been misconfigured. Contact your IT department and include the following information:
Undefined Sign-On URL for application "BlahBlahBlah"
In the new Azure portal UI, the "SIGN-ON URL" is now called "Home page URL", which you can find under Branding in the app registration configuration.
I can see why this may be confusing. I think you can look at this as the URL where the whole sign-in process starts (i.e. your app's URL, which, if they're not logged in, will sends them to login.windows.net).
Also, even if for now you might be able to enter anything and authentication still works, I'd try to make it point to the right place just in case things change in the future.
It appears to me that It has significance with respect to wsFederation realm value when user sign out and redirected to Active directory sign in page.
When you add your application to azure ad, it gives you client id and key. When you use that in MVC webappp, you will see that there is an entry like below in web.config:
<system.identityModel.services>
<federationConfiguration>
<cookieHandler requireSsl="true" />
<wsFederation passiveRedirectEnabled="true" issuer="https://login.windows.net/{some guid}/wsfed" realm="https://localhost:44304/" requireHttps="true" />
</federationConfiguration>
</system.identityModel.services>
Copy the value of user to sign-on url.

Resources