In my Sitecore 9.1 installation I'm trying to use Federated Authentication and have almost successfully set it up.
When I click the "log in" button on my public website I'm redirected to the OpenIDConnect
site where I'm authenticating. I can see from Chrome Developer Tools that OIDC
performs the postback to Sitecore with the authorization code, so the OIDC
setup and authentication works. Sitecore, on the other hand, fails with Unsuccessful login with external provider
.
In my log file I can see the following error:
4716 12:58:56 ERROR Unable to get and an external login info via Microsoft.Owin.Security.AuthenticationManagerExtensions.GetExternalLoginInfoAsync. Most probably the identity does not have a 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' claim.
According to this KB article this is because the OIDC does not provide a nameidentifier
claim. The OIDC provider I'm using does not send a nameidentifier
claim, so this makes sense.
That article conveniently has a solution (#1). However, that solution doesn't work!
I've added the required transformation
tag, but I'm still getting Unsuccessful login with external provider
!
Here's my complete configuration file:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set">
<sitecore>
<settings>
<setting name="FederatedAuthentication.Enabled">
<patch:attribute name="value">true</patch:attribute>
</setting>
</settings>
<pipelines>
<owin.identityProviders>
<processor type="MySolution.OidcIdentityProvider, MyAssembly" resolve="true" />
</owin.identityProviders>
</pipelines>
<federatedAuthentication type="Sitecore.Owin.Authentication.Configuration.FederatedAuthenticationConfiguration, Sitecore.Owin.Authentication">
<identityProvidersPerSites hint="list:AddIdentityProvidersPerSites">
<mapEntry name="public" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication">
<sites hint="list">
<site>website</site>
</sites>
<identityProviders hint="list:AddIdentityProvider">
<identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='MyOidc']" />
</identityProviders>
<externalUserBuilder type="Sitecore.Owin.Authentication.Services.DefaultExternalUserBuilder, Sitecore.Owin.Authentication">
<param desc="isPersistentUser">false</param>
</externalUserBuilder>
</mapEntry>
</identityProvidersPerSites>
<identityProviders hint="list:AddIdentityProvider">
<identityProvider id="MyOidc" type="Sitecore.Owin.Authentication.Configuration.DefaultIdentityProvider, Sitecore.Owin.Authentication">
<param desc="name">$(id)</param>
<param desc="domainManager" type="Sitecore.Abstractions.BaseDomainManager" resolve="true" />
<caption>Log in with OpenIDConnect</caption>
<icon>sitecore/shell/themes/standard/Custom/24x24/profile.png</icon>
<domain>extranet</domain>
<transformations hint="list:AddTransformation">
<transformation name="Idp Claim" type="Sitecore.Owin.Authentication.Services.SetIdpClaimTransform, Sitecore.Owin.Authentication" />
<transformation name="Name Identifier Claim" type="Sitecore.Owin.Authentication.Services.DefaultTransformation, Sitecore.Owin.Authentication">
<sources hint="raw:AddSource">
<claim name="sub" />
</sources>
<targets hint="raw:AddTarget">
<claim name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" />
</targets>
<keepSource>false</keepSource>
</transformation>
</transformations>
</identityProvider>
</identityProviders>
</federatedAuthentication>
<federatedAuthentication>
<identityProviders>
<identityProvider id="SitecoreIdentityServer">
<enabled>false</enabled>
</identityProvider>
</identityProviders>
</federatedAuthentication>
<sites>
<site name="shell" set:loginPage="/sitecore/login"/>
<site name="admin" set:loginPage="/sitecore/admin/login.aspx"/>
</sites>
</sitecore>
</configuration>
The article said to transform from the following source claim:
<sources hint="raw:AddSource">
<claim name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" />
</sources>
But seeing as I don't have a upn
claim from OIDC either, I want to convert the sub
claim, which is what I set up in the above configuration.
For good measure I also tried manually starting the transformation by attaching to the SecurityTokenValidated
notification in OpenIdConnectAuthenticationOptions
:
protected override void ProcessCore(IdentityProvidersArgs args) {
args.App.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions {
Authority = "https://my.oidc",
ClientId = "myclient",
ClientSecret = "mysecret",
Scope = "openid myscopes",
RedirectUri = "https://mysite/identity/externallogincallback",
AuthenticationType = GetAuthenticationType(),
ResponseType = "code",
SignInAsAuthenticationType = GetAuthenticationType(),
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications {
SecurityTokenValidated = OnSecurityTokenValidated
}
});
}
private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) {
TransformationContext transformationContext = new TransformationContext(FederatedAuthenticationConfiguration, GetIdentityProvider());
context.AuthenticationTicket.Identity.ApplyClaimsTransformations(transformationContext);
return Task.CompletedTask;
}
Though this didn't help either.
The OIDC authentication and redirection obviously works, but why does Sitecore complain that identity does not have a nameidentifier
claim when I've specifically said to transform the sub
claim to nameidentifier
, and how can I make this work?
UPDATE
After doing some more debugging I've come to the conclusion that the transform actually works. When debugging the SecurityTokenValidated
notification and looking at the context.AuthenticationTicket.Identity
object I can see that it now actually has the nameidentifier
claim, as can be evidenced from this screenshot:
The Sitecore log still complains with the same error, though:
4716 12:58:56 ERROR Unable to get and an external login info via Microsoft.Owin.Security.AuthenticationManagerExtensions.GetExternalLoginInfoAsync. Most probably the identity does not have a 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' claim.
So something is obviously wrong, but I still don't know what to do.
sub
claim is returned in calls to/userinfo
when I test with Postmanobjectidentifier
claim?objectidentifier
in the claims returned from/userinfo
or on theid_token
oraccess_token