/// <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();
            }
        }
Example #12
0
        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.
            }
        }
Example #13
0
        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();
            }
        }
Example #15
0
        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();
        }
Example #26
0
 /// <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;
 }
Example #27
0
        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();
        }
Example #30
0
        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();
        }