I am building a .Net Core Web App that will be a service provider and use SSO to sign in users via an Identity Provider.
When I load the web app, and click Login
...I get errors....
I have the following in my appsettings.json
file:
"Saml2": {
"zau_idpMetadata": "https://saml.zau.edu/zau_idp/shibboleth ",
"Issuer": "UniversityComms",
"SingleSignOnDestination": "https://saml.zau.edu/zau_idp/profile/SSO",
"SingleLogoutDestination": "https://saml.zau.edu/zau_idp/profile/Logout",
"CertificateValidationMode": "None",
//"CertificateValidationMode": "ChainTrust",
"RevocationMode": "NoCheck"
}
You can see that I have SingleLogoutDestination
defined.
And this is in my program.cs
file:
builder.Services.Configure<Saml2Configuration>(saml2Configuration =>
{
saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);
var entityDescriptor = new EntityDescriptor();
//entityDescriptor.ReadIdPSsoDescriptorFromUrlAsync(httpClientFactory, new Uri(Configuration["Saml2:IdPMetadata"])).GetAwaiter().GetResult();
entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(configuration["Saml2:IdPMetadata"]));
if (entityDescriptor.IdPSsoDescriptor != null)
{
saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
saml2Configuration.SingleLogoutDestination = entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.First().Location;
saml2Configuration.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);
}
else
{
throw new Exception("IdPSsoDescriptor not loaded from metadata.");
}
});
builder.Services.AddSaml2();
var app = builder.Build();
However, when I start the app, and try to login via SSO, I get this error:
System.InvalidOperationException: 'Sequence contains no elements'
Here is the full error:
InvalidOperationException: Sequence contains no elements
System.Linq.ThrowHelper.ThrowNoElementsException()
System.Linq.Enumerable.First<TSource>(IEnumerable<TSource> source)
Program+<>c__DisplayClass0_0.<<Main>$>b__0(Saml2Configuration saml2Configuration) in Program.cs
var entityDescriptor = new EntityDescriptor();
//entityDescriptor.ReadIdPSsoDescriptorFromUrlAsync(httpClientFactory, new Uri(Configuration["Saml2:IdPMetadata"])).GetAwaiter().GetResult();
entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(configuration["Saml2:IdPMetadata"]));
if (entityDescriptor.IdPSsoDescriptor != null)
{
saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
saml2Configuration.SingleLogoutDestination = entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.First().Location;
saml2Configuration.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);
}
else
{
throw new Exception("IdPSsoDescriptor not loaded from metadata.");
}
Microsoft.Extensions.Options.OptionsFactory<TOptions>.Create(string name)
Microsoft.Extensions.Options.UnnamedOptionsManager<TOptions>.get_Value()
UniversityComms.Controllers.AuthController..ctor(IOptions<Saml2Configuration> configAccessor) in AuthController.cs
{
const string relayStateReturnUrl = "ReturnUrl";
private readonly Saml2Configuration config;
public AuthController(IOptions<Saml2Configuration> configAccessor)
{
config = configAccessor.Value;
}
[Route("Login")]
public IActionResult Login(string? returnUrl = null)
{
var binding = new Saml2RedirectBinding();
lambda_method22(Closure , IServiceProvider , object[] )
The code loads the SingleSignOnDestination
and SingleLogoutDestination
from the IdP metadata endpoint zau_idpMetadata
. The IdP metadata probably do not contain at lease one SingleLogoutServices
and therefore it fails on .First()
.
You can comment out the single logout line and load it from config.