public void IdentityProvider_CreateAuthenticateRequest_BasicInfo() { var options = Options.FromConfiguration; var idp = options.IdentityProviders.Default; var urls = StubFactory.CreateSaml2Urls(); var subject = idp.CreateAuthenticateRequest(urls); var expected = new Saml2AuthenticationRequest() { AssertionConsumerServiceUrl = urls.AssertionConsumerServiceUrl, DestinationUrl = idp.SingleSignOnServiceUrl, Issuer = options.SPOptions.EntityId, AttributeConsumingServiceIndex = 0, NameIdPolicy = new Saml2NameIdPolicy(true, NameIdFormat.EntityIdentifier), RequestedAuthnContext = new Saml2RequestedAuthnContext( new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"), AuthnContextComparisonType.Minimum) }; subject.Should().BeEquivalentTo(expected, opt => opt .Excluding(au => au.Id) .Excluding(au => au.SigningAlgorithm) .Excluding(au => au.RelayState)); subject.RelayState.Should().HaveLength(24); }
public void SPOptionsExtensions_CreateMetadata_WithServiceCertificateConfigured() { var options = StubFactory.CreateOptions(); options.SPOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert2 }); var metadata = options.SPOptions.CreateMetadata(StubFactory.CreateSaml2Urls()); var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single(); spMetadata.Should().NotBeNull(); spMetadata.Keys.Count.Should().Be(1); spMetadata.Keys.Single().Use.Should().Be(KeyType.Unspecified); // When there is a service certificate, expose SLO endpoints. var sloRedirect = spMetadata.SingleLogoutServices.Single( slo => slo.Binding == Saml2Binding.HttpRedirectUri); sloRedirect.Location.Should().Be("http://localhost/Saml2/Logout"); sloRedirect.ResponseLocation.Should().BeNull(); var sloPost = spMetadata.SingleLogoutServices.Single( slo => slo.Binding == Saml2Binding.HttpPostUri); sloPost.Location.Should().Be("http://localhost/Saml2/Logout"); sloPost.ResponseLocation.Should().BeNull(); }
public void IdentityProvider_MetadataLoadedConfiguredFromCode() { var spOptions = StubFactory.CreateSPOptions(); spOptions.ServiceCertificates.Add(new ServiceCertificate() { Certificate = SignedXmlHelper.TestCert }); var subject = new IdentityProvider( new EntityId("http://other.entityid.example.com"), spOptions) { MetadataLocation = "http://localhost:13428/idpMetadataOtherEntityId", AllowUnsolicitedAuthnResponse = true }; subject.AllowUnsolicitedAuthnResponse.Should().BeTrue(); subject.Binding.Should().Be(Saml2BindingType.HttpRedirect); subject.EntityId.Id.Should().Be("http://other.entityid.example.com"); // If a metadatalocation is set, metadata loading is automatically enabled. subject.LoadMetadata.Should().BeTrue(); subject.MetadataLocation.Should().Be("http://localhost:13428/idpMetadataOtherEntityId"); subject.MetadataValidUntil.Should().BeCloseTo( DateTime.UtcNow.Add(MetadataRefreshScheduler.DefaultMetadataCacheDuration.ToTimeSpan()), precision: 100); subject.SingleSignOnServiceUrl.Should().Be("http://wrong.entityid.example.com/acs"); subject.WantAuthnRequestsSigned.Should().Be(true, "WantAuthnRequestsSigned should have been loaded from metadata"); Action a = () => subject.CreateAuthenticateRequest(StubFactory.CreateSaml2Urls()); a.Should().NotThrow(); }
public void SPOptionsExtensions_CreateMetadata_IncludesContactPersons() { var spOptions = StubFactory.CreateSPOptions(); var subject = spOptions.CreateMetadata(StubFactory.CreateSaml2Urls()).Contacts; subject.Should().Contain(spOptions.Contacts); }
public void SPOptionsExtensions_CreateMetadata_IncludesOrganization() { var subject = StubFactory .CreateSPOptions() .CreateMetadata(StubFactory.CreateSaml2Urls()) .Organization; subject.Should().NotBeNull(); subject.Names.First().Name.Should().Be("Sustainsys.Saml2"); }
public void IdentityProvider_CreateAuthenticateRequest_IncludesSigningCertificate_IfIdpWants() { var options = Options.FromConfiguration; var spOptions = options.SPOptions; var subject = options.IdentityProviders[new EntityId("https://idp2.example.com")]; var urls = StubFactory.CreateSaml2Urls(); var actual = subject.CreateAuthenticateRequest(urls).SigningCertificate; (actual?.Thumbprint).Should().Be(SignedXmlHelper.TestCert2.Thumbprint); }
public void IdentityProvider_CreateAuthenticateRequest_ThrowsOnMissingSigningCertificate() { var options = StubFactory.CreateOptions(); var spOptions = options.SPOptions; spOptions.AuthenticateRequestSigningBehavior = SigningBehavior.Always; var idp = options.IdentityProviders.Default; var urls = StubFactory.CreateSaml2Urls(); idp.Invoking(i => i.CreateAuthenticateRequest(urls)) .Should().Throw <ConfigurationErrorsException>() .WithMessage($"Idp \"https://idp.example.com\" is configured for signed AuthenticateRequests*"); }
public void IdentityProvider_CreateAuthenticateRequest_DestinationInXml() { string idpUri = "https://idp.example.com:443/"; var subject = new IdentityProvider( new EntityId(idpUri), Options.FromConfiguration.SPOptions) { SingleSignOnServiceUrl = new Uri(idpUri) }; var r = subject.CreateAuthenticateRequest(StubFactory.CreateSaml2Urls()); r.ToXElement().Attribute("Destination").Should().NotBeNull() .And.Subject.Value.Should().Be(idpUri); }
public void IdentityProvider_CreateAuthenticateRequest_DestinationInXml() { // %41 is A, which doesn't need to be encoded. Ensure it is kept in original format. string idpUri = "http://idp.example.com/x=%41"; var subject = new IdentityProvider( new EntityId(idpUri), Options.FromConfiguration.SPOptions) { SingleSignOnServiceUrl = new Uri(idpUri) }; var r = subject.CreateAuthenticateRequest(StubFactory.CreateSaml2Urls()); r.ToXElement().Attribute("Destination").Should().NotBeNull() .And.Subject.Value.Should().Be(idpUri); }
public void IdentityProvider_CreateAuthenticateRequest_IncludesSigningCertificate_ForConfigAlways() { var options = StubFactory.CreateOptions(); var spOptions = options.SPOptions; spOptions.AuthenticateRequestSigningBehavior = SigningBehavior.Always; spOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert }); var idp = options.IdentityProviders.Default; var urls = StubFactory.CreateSaml2Urls(); var subject = idp.CreateAuthenticateRequest(urls); subject.SigningCertificate.Thumbprint.Should().Be(SignedXmlHelper.TestCert.Thumbprint); }
public void SPOptionsExtensions_CreateMetadata_WithServiceCertificateConfiguredAndPostLogoutEnabled() { var options = StubFactory.CreateOptions(); options.SPOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert2 }); options.SPOptions.Compatibility.EnableLogoutOverPost = true; var metadata = options.SPOptions.CreateMetadata(StubFactory.CreateSaml2Urls()); var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single(); var sloPost = spMetadata.SingleLogoutServices.Single( slo => slo.Binding == Saml2Binding.HttpPostUri); sloPost.Location.Should().Be("http://localhost/Saml2/Logout"); sloPost.ResponseLocation.Should().BeNull(); }
public void SPOptionsExtensions_CreateMetadata_MultipleServiceCertificate() { var options = StubFactory.CreateOptions(); options.SPOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert2, Use = CertificateUse.Encryption }); options.SPOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert2, Use = CertificateUse.Signing }); var metadata = options.SPOptions.CreateMetadata(StubFactory.CreateSaml2Urls()); var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single(); spMetadata.Should().NotBeNull(); spMetadata.Keys.Count.Should().Be(2); spMetadata.Keys.Where(k => k.Use == KeyType.Encryption).Count().Should().Be(1); spMetadata.Keys.Where(k => k.Use == KeyType.Signing).Count().Should().Be(1); }
public void SPOptionsExtensions_CreateMetadata_IncludeAttributeConsumingService() { var spOptions = StubFactory.CreateSPOptions(); var urls = StubFactory.CreateSaml2Urls(); var attributeConsumingService = new AttributeConsumingService("Name"); spOptions.AttributeConsumingServices.Clear(); spOptions.AttributeConsumingServices.Add(attributeConsumingService); attributeConsumingService.RequestedAttributes.Add(new RequestedAttribute("AttributeName")); var subject = spOptions .CreateMetadata(urls) .RoleDescriptors .Cast <ExtendedServiceProviderSingleSignOnDescriptor>() .First(); subject.AttributeConsumingServices.First().Should().BeSameAs(attributeConsumingService); }
public void SPOptionsExtensions_CreateMetadata_IncludeDiscoveryServiceResponse() { var spOptions = StubFactory.CreateSPOptions(); var urls = StubFactory.CreateSaml2Urls(); spOptions.DiscoveryServiceUrl = new Uri("http://ds.example.com"); var subject = spOptions.CreateMetadata(urls).RoleDescriptors .Single().As <SpSsoDescriptor>() .DiscoveryResponses.Values.Single(); var expected = new DiscoveryResponse { Binding = Saml2Binding.DiscoveryResponseUri, Index = 0, IsDefault = true, Location = urls.SignInUrl }; subject.Should().BeEquivalentTo(expected); }
public void IdentityProvider_CreateAuthenticateRequest_SigningBehaviorNever_OverridesIdpWantsRequestsSigned() { var options = StubFactory.CreateOptions(); var spOptions = options.SPOptions; spOptions.AuthenticateRequestSigningBehavior = SigningBehavior.Never; spOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert }); var subject = new IdentityProvider(new EntityId("http://idp.example.com"), spOptions) { WantAuthnRequestsSigned = true }; var urls = StubFactory.CreateSaml2Urls(); var actual = subject.CreateAuthenticateRequest(urls).SigningCertificate; actual.Should().BeNull(); }
public void SPOptionsExtensions_CreateMetadata_IncludeAttributeConsumingService() { var spOptions = StubFactory.CreateSPOptions(); var urls = StubFactory.CreateSaml2Urls(); var attributeConsumingService = new AttributeConsumingService(); attributeConsumingService.ServiceNames.Add( new LocalizedName("Name", "en")); spOptions.AttributeConsumingServices.Clear(); spOptions.AttributeConsumingServices.Add(attributeConsumingService); attributeConsumingService.RequestedAttributes.Add(new RequestedAttribute("AttributeName")); var subject = spOptions .CreateMetadata(urls) .RoleDescriptors .Cast <SpSsoDescriptor>() .First(); subject.AttributeConsumingServices.Values.First().Should().BeSameAs(attributeConsumingService); }
public void IdentityProvider_CreateAuthenticateRequest_NoAttributeIndex() { var options = StubFactory.CreateOptions(); var idp = options.IdentityProviders.Default; var urls = StubFactory.CreateSaml2Urls(); options.SPOptions.AttributeConsumingServices.Clear(); var subject = idp.CreateAuthenticateRequest(urls); var expected = new Saml2AuthenticationRequest() { AssertionConsumerServiceUrl = urls.AssertionConsumerServiceUrl, DestinationUrl = idp.SingleSignOnServiceUrl, Issuer = options.SPOptions.EntityId, AttributeConsumingServiceIndex = null }; subject.Should().BeEquivalentTo(expected, opt => opt .Excluding(au => au.Id) .Excluding(au => au.SigningAlgorithm) .Excluding(au => au.RelayState)); }
public void SPOPtionsExtensions_CreateMetadata_RequiredFields() { var metadata = StubFactory.CreateSPOptions().CreateMetadata(StubFactory.CreateSaml2Urls()); metadata.CacheDuration.Should().Be(new XsdDuration(seconds: 42)); metadata.EntityId.Id.Should().Be("https://github.com/Sustainsys/Saml2"); var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single(); spMetadata.Should().NotBeNull(); spMetadata.Keys.Count.Should().Be(0); var acs = spMetadata.AssertionConsumerServices.First().Value; acs.Index.Should().Be(0); acs.IsDefault.Should().HaveValue(); acs.Binding.ToString().Should().Be("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); acs.Location.ToString().Should().Be("http://localhost/Saml2/Acs"); // No service certificate configured, so no SLO endpoint should be // exposed in metadata. spMetadata.SingleLogoutServices.Should().BeEmpty(); }