/// <summary> /// Creates a Saml2Assertion from a ClaimsIdentity. /// </summary> /// <returns>Saml2Assertion</returns> public static Saml2Assertion ToSaml2Assertion(this ClaimsIdentity identity, EntityId issuer) { if (identity == null) { throw new ArgumentNullException("identity"); } if (issuer == null) { throw new ArgumentNullException("issuer"); } var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer.Id)); assertion.Subject = new Saml2Subject(new Saml2NameIdentifier( identity.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value)); foreach (var claim in identity.Claims.Where(c => c.Type != ClaimTypes.NameIdentifier).GroupBy(c => c.Type)) { assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute(claim.Key, claim.Select(c => c.Value)))); }; assertion.Conditions = new Saml2Conditions() { NotOnOrAfter = DateTime.UtcNow.AddMinutes(2) }; return assertion; }
/// <summary> /// Creates a Saml2Assertion from a ClaimsIdentity. /// </summary> /// <param name="identity">Claims to include in Assertion.</param> /// <param name="issuer">Issuer to include in assertion.</param> /// <param name="audience">Audience to set as audience restriction.</param> /// <returns>Saml2Assertion</returns> public static Saml2Assertion ToSaml2Assertion( this ClaimsIdentity identity, EntityId issuer, Uri audience) { if (identity == null) { throw new ArgumentNullException(nameof(identity)); } if (issuer == null) { throw new ArgumentNullException(nameof(issuer)); } var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer.Id)) { Subject = new Saml2Subject(new Saml2NameIdentifier( identity.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value)), }; assertion.Statements.Add( new Saml2AuthenticationStatement( new Saml2AuthenticationContext( new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"))) { SessionIndex = identity.Claims.SingleOrDefault( c => c.Type == AuthServicesClaimTypes.SessionIndex)?.Value }); var attributeClaims = identity.Claims.Where( c => c.Type != ClaimTypes.NameIdentifier && c.Type != AuthServicesClaimTypes.SessionIndex).GroupBy(c => c.Type); if (attributeClaims.Any()) { assertion.Statements.Add( new Saml2AttributeStatement( attributeClaims.Select( ac => new Saml2Attribute(ac.Key, ac.Select(c => c.Value))))); } assertion.Conditions = new Saml2Conditions() { NotOnOrAfter = DateTime.UtcNow.AddMinutes(2) }; if(audience != null) { assertion.Conditions.AudienceRestrictions.Add( new Saml2AudienceRestriction(audience)); } return assertion; }
private Saml2Response(XmlDocument xml) { xmlDocument = xml; id = new Saml2Id(xml.DocumentElement.Attributes["ID"].Value); var parsedInResponseTo = xml.DocumentElement.Attributes["InResponseTo"].GetValueIfNotNull(); if (parsedInResponseTo != null) { inResponseTo = new Saml2Id(parsedInResponseTo); } issueInstant = DateTime.Parse(xml.DocumentElement.Attributes["IssueInstant"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal); var statusString = xml.DocumentElement["Status", Saml2Namespaces.Saml2PName] ["StatusCode", Saml2Namespaces.Saml2PName].Attributes["Value"].Value; status = StatusCodeHelper.FromString(statusString); statusMessage = xml.DocumentElement["Status", Saml2Namespaces.Saml2PName] ["StatusMessage", Saml2Namespaces.Saml2PName].GetTrimmedTextIfNotNull(); issuer = new EntityId(xmlDocument.DocumentElement["Issuer", Saml2Namespaces.Saml2Name].GetTrimmedTextIfNotNull()); var destinationUrlString = xmlDocument.DocumentElement.Attributes["Destination"].GetValueIfNotNull(); if (destinationUrlString != null) { destinationUrl = new Uri(destinationUrlString); } }
/// <summary> /// Creates a PendingAuthnRequestData /// </summary> /// <param name="idp">The EntityId of the IDP the request was sent to</param> /// <param name="returnUrl">The Url to redirect back to after a succesful login</param> /// <param name="messageId">ID of the SAML message, used to match InResponseTo</param> /// <param name="relayData">Aux data that can be stored across the authentication request.</param> public StoredRequestState(EntityId idp, Uri returnUrl, Saml2Id messageId, object relayData) { Idp = idp; ReturnUrl = returnUrl; MessageId = messageId; RelayData = relayData; }
public void EntityIdEqualityComparerTests_DiffOnDifferent() { var eid1 = new EntityId("whatever"); var eid2 = new EntityId("somethingElse"); EntityIdEqualityComparer.Instance.Equals(eid1, eid2).Should().BeFalse(); }
public void EntityDescriptorExtensions_ToXElement_Nodes() { EntityId entityId = new EntityId("http://dummyentityid.com"); var entityDescriptor = new EntityDescriptor(entityId); var spsso = new ServiceProviderSingleSignOnDescriptor(); string sampleAcsUri = "https://some.uri.example.com/acs"; var acs = new IndexedProtocolEndpoint() { IsDefault = false, Index = 17, Binding = Saml2Binding.HttpPostUri, Location = new Uri(sampleAcsUri) }; spsso.AssertionConsumerServices.Add(1, acs); entityDescriptor.RoleDescriptors.Add(spsso); var rootName = Saml2Namespaces.Saml2Metadata + "EntityDescriptor"; var elementName = Saml2Namespaces.Saml2Metadata + "SPSSODescriptor"; var subject = entityDescriptor.ToXElement(); subject.Name.Should().Be(rootName); subject.Elements().Single().Name.Should().Be(elementName); subject.Attribute("entityId").Value.Should().Be("http://dummyentityid.com"); }
internal IdentityProvider(IdentityProviderElement config, ISPOptions spOptions) { singleSignOnServiceUrl = config.DestinationUrl; EntityId = new EntityId(config.EntityId); binding = config.Binding; AllowUnsolicitedAuthnResponse = config.AllowUnsolicitedAuthnResponse; metadataUrl = config.MetadataUrl; var certificate = config.SigningCertificate.LoadCertificate(); if (certificate != null) { signingKeys.AddConfiguredItem(certificate.PublicKey.Key); } // If configured to load metadata, this will immediately do the load. LoadMetadata = config.LoadMetadata; this.spOptions = spOptions; // Validate if values are only from config. If metadata is loaded, validation // is done on metadata load. if (!LoadMetadata) { Validate(); } }
public IdentityProvider this[EntityId entityId] { get { if(entityId == null) { throw new ArgumentNullException("entityId"); } lock(dictionary) { try { return dictionary[entityId]; } catch (KeyNotFoundException e) { throw new KeyNotFoundException( "No Idp with entity id \"" + entityId.Id + "\" found.", e); } } } set { lock (dictionary) { dictionary[entityId] = value; } } }
public void Saml2ArtifactBinding_Unbind_FromGet() { var issuer = new EntityId("https://idp.example.com"); var artifact = Uri.EscapeDataString( Convert.ToBase64String( Saml2ArtifactBinding.CreateArtifact(issuer, 0x1234))); var relayState = MethodBase.GetCurrentMethod().Name; PrepareArtifactState(relayState, issuer); var r = new HttpRequestData( "GET", new Uri($"http://example.com/path/acs?SAMLart={artifact}&RelayState={relayState}")); StubServer.LastArtifactResolutionSoapActionHeader = null; var result = Saml2Binding.Get(Saml2BindingType.Artifact).Unbind(r, StubFactory.CreateOptions()); var xmlDocument = new XmlDocument() { PreserveWhitespace = true }; xmlDocument.LoadXml("<message> <child-node /> </message>"); var expected = new UnbindResult(xmlDocument.DocumentElement, relayState, TrustLevel.None); result.ShouldBeEquivalentTo(expected); StubServer.LastArtifactResolutionSoapActionHeader.Should().Be( "http://www.oasis-open.org/committees/security"); StubServer.LastArtifactResolutionWasSigned.Should().BeFalse(); }
/// <summary> /// Creates a Saml2Assertion from a ClaimsIdentity. /// </summary> /// <param name="identity">Claims to include in Assertion.</param> /// <param name="issuer">Issuer to include in assertion.</param> /// <param name="audience">Audience to set as audience restriction.</param> /// <returns>Saml2Assertion</returns> public static Saml2Assertion ToSaml2Assertion( this ClaimsIdentity identity, EntityId issuer, Uri audience) { return ToSaml2Assertion(identity, issuer, audience, null, null); }
internal IdentityProvider(IdentityProviderElement config, ISPOptions spOptions) { singleSignOnServiceUrl = config.DestinationUrl; EntityId = new EntityId(config.EntityId); binding = config.Binding; AllowUnsolicitedAuthnResponse = config.AllowUnsolicitedAuthnResponse; metadataUrl = config.MetadataUrl; ShowNameIdPolicy = config.ShowNameIdPolicy; // If configured to load metadata, this will immediately do the load. VerifyCertificate = config.VerifyCertificate; LoadMetadata = config.LoadMetadata; this.spOptions = spOptions; // Certificates from metadata already present, add eventual other certificates // from web.config. var certificate = config.SigningCertificate.LoadCertificate(); if (certificate != null) { signingKeys = new ConfiguredAndLoadedCollection<AsymmetricAlgorithm>(); signingKeys.AddConfiguredItem(certificate.PublicKey.Key); } // Validate if values are only from config. If metadata is loaded, validation // is done on metadata load. if (!LoadMetadata) { Validate(); } }
internal IdentityProvider(IdentityProviderElement config, ISPOptions spOptions) { singleSignOnServiceUrl = config.DestinationUrl; EntityId = new EntityId(config.EntityId); binding = config.Binding; AllowUnsolicitedAuthnResponse = config.AllowUnsolicitedAuthnResponse; metadataUrl = config.MetadataUrl; LoadMetadata = config.LoadMetadata; this.spOptions = spOptions; var certificate = config.SigningCertificate.LoadCertificate(); if (certificate != null) { signingKey = certificate.PublicKey.Key; } try { if (LoadMetadata) { DoLoadMetadata(); } Validate(); } catch (WebException) { // If we had a web exception, the metadata failed. It will // be automatically retried. } }
public static CommandResult CreateResult(EntityId idpEntityId, string returnPath, Uri requestUrl) { IdentityProvider idp; if (idpEntityId != null && idpEntityId.Id != null) { if (!IdentityProvider.ActiveIdentityProviders.TryGetValue(idpEntityId, out idp)) { throw new InvalidOperationException("Unknown idp"); } } else { idp = IdentityProvider.ActiveIdentityProviders.First(); } Uri returnUri = null; if (!string.IsNullOrEmpty(returnPath)) { Uri.TryCreate(requestUrl, returnPath, out returnUri); } var authnRequest = idp.CreateAuthenticateRequest(returnUri); return idp.Bind(authnRequest); }
internal IdentityProvider(IdentityProviderElement config, ISPOptions spOptions) { singleSignOnServiceUrl = config.DestinationUrl; EntityId = new EntityId(config.EntityId); binding = config.Binding; AllowUnsolicitedAuthnResponse = config.AllowUnsolicitedAuthnResponse; metadataLocation = string.IsNullOrEmpty(config.MetadataLocation) ? null : config.MetadataLocation; WantAuthnRequestsSigned = config.WantAuthnRequestsSigned; var certificate = config.SigningCertificate.LoadCertificate(); if (certificate != null) { signingKeys.AddConfiguredKey( new X509RawDataKeyIdentifierClause(certificate)); } // If configured to load metadata, this will immediately do the load. LoadMetadata = config.LoadMetadata; this.spOptions = spOptions; // Validate if values are only from config. If metadata is loaded, validation // is done on metadata load. if (!LoadMetadata) { Validate(); } }
internal IdentityProvider(IdentityProviderElement config, SPOptions spOptions) { singleSignOnServiceUrl = config.SignOnUrl; SingleLogoutServiceUrl = config.LogoutUrl; EntityId = new EntityId(config.EntityId); binding = config.Binding; AllowUnsolicitedAuthnResponse = config.AllowUnsolicitedAuthnResponse; metadataLocation = string.IsNullOrEmpty(config.MetadataLocation) ? null : config.MetadataLocation; WantAuthnRequestsSigned = config.WantAuthnRequestsSigned; DisableOutboundLogoutRequests = config.DisableOutboundLogoutRequests; var certificate = config.SigningCertificate.LoadCertificate(); if (certificate != null) { signingKeys.AddConfiguredKey( new X509RawDataKeyIdentifierClause(certificate)); } foreach (var ars in config.ArtifactResolutionServices) { ArtifactResolutionServiceUrls[ars.Index] = ars.Location; } // If configured to load metadata, this will immediately do the load. this.spOptions = spOptions; LoadMetadata = config.LoadMetadata; // Validate if values are only from config. If metadata is loaded, validation // is done on metadata load. if (!LoadMetadata) { Validate(); } }
public void EntityIdEqualityComparerTests_EqualsNullCheckY() { var eid = new EntityId(); Action a = () => EntityIdEqualityComparer.Instance.Equals(eid, null); a.ShouldThrow<ArgumentNullException>("y"); }
public void EntityIdEqualityComparerTests_EqualsOnSame() { var id = "someEntityId"; var eid1 = new EntityId(id); var eid2 = new EntityId(id); EntityIdEqualityComparer.Instance.Equals(eid1, eid2).Should().BeTrue(); }
public void EntityIdEqualityComparerTests_DiffHashCodeOnDifferent() { var eid1 = new EntityId("whatever"); var eid2 = new EntityId("somethingElse"); EntityIdEqualityComparer.Instance.GetHashCode(eid1) .Should().NotBe(EntityIdEqualityComparer.Instance.GetHashCode(eid2)); }
public void EntityIdEqualityComparerTests_GetHashCodeHandlesNullId() { var entityId = new EntityId(); entityId.Id.Should().BeNull(); Action a = () => EntityIdEqualityComparer.Instance.GetHashCode(entityId); a.ShouldNotThrow(); }
public void EntityIdEqualityComparerTests_SameHashCodeOnSame() { var id = "someEntityID"; var eid1 = new EntityId(id); var eid2 = new EntityId(id); EntityIdEqualityComparer.Instance.GetHashCode(eid1) .Should().Be(EntityIdEqualityComparer.Instance.GetHashCode(eid2)); }
public void IdentityProvider_ConfigFromMetadata() { var entityId = new EntityId("http://localhost:13428/idpMetadata"); var idpFromMetadata = Options.FromConfiguration.IdentityProviders[entityId]; idpFromMetadata.EntityId.Id.Should().Be(entityId.Id); idpFromMetadata.Binding.Should().Be(Saml2BindingType.HttpPost); idpFromMetadata.SingleSignOnServiceUrl.Should().Be(new Uri("http://localhost:13428/acs")); idpFromMetadata.SigningKeys.Single().ShouldBeEquivalentTo(SignedXmlHelper.TestKey); }
public void IdentityProviderDictionary_Add() { var subject = new IdentityProviderDictionary(); var entityId = new EntityId("http://idp.example.com"); var idp = new IdentityProvider(entityId, StubFactory.CreateSPOptions()); subject.Add(idp); subject[entityId].Should().BeSameAs(idp); }
public EntityDescriptor Generate(string wsfedEndpoint) { var tokenServiceDescriptor = GetTokenServiceDescriptor(wsfedEndpoint); var id = new EntityId(_options.IssuerUri); var entity = new EntityDescriptor(id); entity.SigningCredentials = new X509SigningCredentials(_options.SigningCertificate); entity.RoleDescriptors.Add(tokenServiceDescriptor); return entity; }
/// <summary> /// Ctor /// </summary> /// <param name="idp">The EntityId of the IDP the request was sent to</param> /// <param name="returnUrl">The Url to redirect back to after a succesful login</param> /// <param name="messageId">ID of the SAML message, used to match InResponseTo</param> /// <param name="relayData">Aux data that can be stored across the authentication request.</param> public StoredRequestState( EntityId idp, Uri returnUrl, Saml2Id messageId, IDictionary<string,string> relayData) { Idp = idp; ReturnUrl = returnUrl; MessageId = messageId; RelayData = relayData; }
public string Generate() { var tokenServiceDescriptor = GetTokenServiceDescriptor(); var id = new EntityId(ConfigurationRepository.Global.IssuerUri); var entity = new EntityDescriptor(id); entity.SigningCredentials = new X509SigningCredentials(ConfigurationRepository.Keys.SigningCertificate); entity.RoleDescriptors.Add(tokenServiceDescriptor); var ser = new MetadataSerializer(); var sb = new StringBuilder(512); ser.WriteMetadata(XmlWriter.Create(new StringWriter(sb), new XmlWriterSettings { OmitXmlDeclaration = true }), entity); return sb.ToString(); }
/// <summary> /// Create a response with the supplied data. /// </summary> /// <param name="issuer">Issuer of the response.</param> /// <param name="issuerCertificate">The certificate to use when signing /// this response in XML form.</param> /// <param name="destinationUrl">The destination Uri for the message</param> /// <param name="inResponseTo">In response to id</param> /// <param name="claimsIdentities">Claims identities to be included in the /// response. Each identity is translated into a separate assertion.</param> public Saml2Response(EntityId issuer, X509Certificate2 issuerCertificate, Uri destinationUrl, string inResponseTo, params ClaimsIdentity[] claimsIdentities) { this.issuer = issuer; this.claimsIdentities = claimsIdentities; this.issuerCertificate = issuerCertificate; this.destinationUrl = destinationUrl; if (inResponseTo != null) { this.inResponseTo = new Saml2Id(inResponseTo); } id = new Saml2Id("id" + Guid.NewGuid().ToString("N")); status = Saml2StatusCode.Success; }
public void Saml2Response_Ctor_FromData() { var issuer = new EntityId("http://idp.example.com"); var identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.NameIdentifier, "JohnDoe") }); var response = new Saml2Response(issuer, null, null, null, identity); response.Issuer.Should().Be(issuer); response.GetClaims(Options.FromConfiguration) .Single() .ShouldBeEquivalentTo(identity); }
public void Federation_LoadInCommonMetadata() { var options = StubFactory.CreateOptions(); var path = "~/Metadata/InCommonMetadata.xml"; var idpInFederation = new EntityId("https://shibboleth.umassmed.edu/idp/shibboleth"); Action a = () => new Federation(path, true, options); a.ShouldNotThrow(); IdentityProvider idp; options.IdentityProviders.TryGetValue(idpInFederation, out idp) .Should().BeTrue(); }
private string GenerateMetadata(params RoleDescriptor[] roles) { var id = new EntityId(ConfigurationRepository.Global.IssuerUri); var entity = new EntityDescriptor(id); entity.SigningCredentials = new X509SigningCredentials(ConfigurationRepository.Keys.SigningCertificate); foreach (var roleDescriptor in roles) { entity.RoleDescriptors.Add(roleDescriptor); } var ser = new MetadataSerializer(); var sb = new StringBuilder(512); ser.WriteMetadata(XmlWriter.Create(new StringWriter(sb), new XmlWriterSettings { OmitXmlDeclaration = true }), entity); return sb.ToString(); }
public void Federation_LoadSkolfederationMetadata() { // Skolfederation is the Swedish national school federation. To test that // AuthServices handles some real world metadata, the metdata from the // skolfederation federation is used. var options = StubFactory.CreateOptions(); var url = new Uri("http://localhost:13428/SkolfederationMetadata"); var idpInFederation = new EntityId("http://fs.ale.se/adfs/services/trust"); Action a = () => new Federation(url, true, options); a.ShouldNotThrow(); IdentityProvider idp; options.IdentityProviders.TryGetValue(idpInFederation, out idp) .Should().BeTrue(); }