We want to allow our endusers to login to our website using an Azure B2C AD account. I have only been able to find examples of how to add federated authentication for Sitecore accounts
I have added this configuration:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<owin.initialize>
<processor type="Feature.Authentication.RegisterOwinAuthPipeline, Feature.Authentication"
patch:before="processor[@type='Sitecore.Owin.Pipelines.Initialize.StageMarker, Sitecore.Owin' and @method='Authenticate']"/>
</owin.initialize>
</pipelines>
Code for auth-route:
public virtual void Process(PipelineArgs args)
{
RouteTable.Routes.MapRoute("AuthRoute", "auth/sso/{action}", new
{
controller = "Sso"
});
SsoLogger.Info("RegisterAuthRoute - Registered route: auth/sso/{action}");
RouteTable.Routes.MapRoute("LoginContentRoute", "api/content/{action}", new
{
controller = "Content"
});
SsoLogger.Info("LoginContentRoute - Registered route: api/login/{action}");
}
And the pipeline that registers my Owin setup:
public class RegisterOwinAuthPipeline : InitializeProcessor
{
private readonly string _ssoAuthenticationRootPath = SsoConfiguration.Routes.RootPath;
private readonly string _aadInstance = SsoConfiguration.AadInstance;
private readonly string _tenant = SsoConfiguration.Tenant;
private readonly ISsoConfigurationRepository _ssoConfigurationRepository;
public RegisterOwinAuthPipeline()
{
_ssoConfigurationRepository = ServiceLocator.ServiceProvider.GetService<ISsoConfigurationRepository>();
}
public override void Process(InitializeArgs args)
{
ConfigureAuth(args.App);
}
public void ConfigureAuth(IAppBuilder app)
{
app.Map(_ssoAuthenticationRootPath, ConfigureSsoAuthentication);
SsoLogger.Info("Owin Startup configuration done. AadInstance=" + _aadInstance + " and Tenant=" + _tenant);
}
private void ConfigureSsoAuthentication(IAppBuilder app)
{
// After successful sign-in in SSO, the redirect back to this web site will use the cookie authentication middleware to contain the obtained id_token.
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieName = SsoConfiguration.SsoCookieName,
CookiePath = _ssoAuthenticationRootPath, // Scope cookies to the authentication root path in order to avoid having the cookie included in every normal request.
TicketDataFormat = new TicketDataFormat(new MachineKeyProtector()) // In order to be able to decrypt the authentication ticket stored in the cookie later on, we use protection based on the machine key.
});
List<B2CConfig> ssoSettings = _ssoConfigurationRepository.GetAllSettings();
foreach (var config in ssoSettings)
{
app.UseOpenIdConnectAuthentication(CreateOptionsFromSiteConfig(config));
}
}
private OpenIdConnectAuthenticationOptions CreateOptionsFromSiteConfig(B2CConfig config)
{
OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions();
// For each policy, give OWIN the policy-specific metadata address, and
// set the authentication type to the id of the policy
options.MetadataAddress = string.Format(_aadInstance, _tenant, config.Policy);
options.AuthenticationType = config.Policy;
options.RedirectUri = config.AzureReplyUri;
options.PostLogoutRedirectUri = config.RedirectAfterLogoutUri;
options.Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = AuthenticationFailed,
RedirectToIdentityProvider = notification =>
{
return Task.FromResult(notification.ProtocolMessage.UiLocales = config.UiLocale ?? string.Empty);
},
SecurityTokenValidated = notification =>
{
notification.AuthenticationTicket.Identity.AddClaim(new Claim("idp", "azureb2cad"));
return Task.FromResult(0);
}
};
// These are standard OpenID Connect parameters, with values pulled from web.config
options.ClientId = config.ClientId;
//http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
options.Scope = "openid";
//http://openid.net/specs/openid-connect-core-1_0.html#Authentication
options.ResponseType = "id_token";
return options;
}
/// <summary>
/// Catch any failures received by the authentication middleware and handle appropriately
/// ref - https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory-b2c/active-directory-b2c-devquickstarts-web-dotnet-susi.md
/// </summary>
/// <param name="notification"></param>
/// <returns></returns>
private Task AuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
SsoLogger.Warn("User triggered reset password");
notification.Response.Redirect(SsoConfiguration.Routes.ResetPassword);
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
SsoLogger.Warn("AuthenticationFailed", notification.Exception);
notification.Response.Redirect(SsoConfiguration.Routes.LoginError);
}
return Task.FromResult(0);
}
}
However, I am seeing these errors in the error-log, after my enduser logs in:
25072 16:04:18 ERROR Unable to find "idp" claim in the identity. Make sure that "Sitecore.Owin.Authentication.Services.SetIdpClaimTransform" or analogue is used in claim transformations of all identity providers.
Exception: System.InvalidOperationException
Message: Unable to find "idp" claim in the identity. Make sure that "Sitecore.Owin.Authentication.Services.SetIdpClaimTransform" or analogue is used in claim transformations of all identity providers.
Source: Sitecore.Owin.Authentication
at Sitecore.Owin.Authentication.Pipelines.CookieAuthentication.ValidateIdentity.CheckIdentityProvider.Process(ValidateIdentityArgs args)
at (Object , Object )
What am I missing? How do I add the "idp" claim to my users? I already tried to add it in my Azure policy ("Identity provider claim).