Exemplo n.º 1
0
        /// <summary>
        /// Creates a Version 1.1 Saml Assertion
        /// </summary>
        /// <param name="issuer">Issuer</param>
        /// <param name="subject">Subject</param>
        /// <param name="attributes">Attributes</param>
        /// <returns>returns a Version 1.1 Saml Assertion</returns>
        private static AssertionType CreateSamlAssertion(string issuer, string recipient, string domain, string subject, Dictionary <string, string> attributes)
        {
            // Here we create some SAML assertion with ID and Issuer name.
            AssertionType assertion = new AssertionType();

            assertion.ID = "_" + Guid.NewGuid().ToString();

            NameIDType issuerForAssertion = new NameIDType();

            issuerForAssertion.Value = issuer.Trim();

            assertion.Issuer  = issuerForAssertion;
            assertion.Version = "2.0";

            assertion.IssueInstant = System.DateTime.UtcNow;

            //Not before, not after conditions
            ConditionsType conditions = new ConditionsType();

            conditions.NotBefore             = DateTime.UtcNow;
            conditions.NotBeforeSpecified    = true;
            conditions.NotOnOrAfter          = DateTime.UtcNow.AddMinutes(5);
            conditions.NotOnOrAfterSpecified = true;

            AudienceRestrictionType audienceRestriction = new AudienceRestrictionType();

            audienceRestriction.Audience = new string[] { domain.Trim() };

            conditions.Items = new ConditionAbstractType[] { audienceRestriction };

            //Name Identifier to be used in Saml Subject
            NameIDType nameIdentifier = new NameIDType();

            nameIdentifier.NameQualifier = domain.Trim();
            nameIdentifier.Value         = subject.Trim();

            SubjectConfirmationType     subjectConfirmation     = new SubjectConfirmationType();
            SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();

            subjectConfirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
            subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
            //
            // Create some SAML subject.
            SubjectType samlSubject = new SubjectType();

            AttributeStatementType attrStatement = new AttributeStatementType();
            AuthnStatementType     authStatement = new AuthnStatementType();

            authStatement.AuthnInstant = DateTime.UtcNow;
            AuthnContextType context = new AuthnContextType();

            context.ItemsElementName   = new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "AuthnContextClassRef" };
            authStatement.AuthnContext = context;

            samlSubject.Items = new object[] { nameIdentifier, subjectConfirmation };

            assertion.Subject = samlSubject;

            IPHostEntry ipEntry =
                Dns.GetHostEntry(System.Environment.MachineName);

            SubjectLocalityType subjectLocality = new SubjectLocalityType();

            subjectLocality.Address = ipEntry.AddressList[0].ToString();

            attrStatement.Items = new AttributeType[attributes.Count];
            int i = 0;

            // Create userName SAML attributes.
            foreach (KeyValuePair <string, string> attribute in attributes)
            {
                AttributeType attr = new AttributeType();
                attr.Name              = attribute.Key;
                attr.NameFormat        = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
                attr.AttributeValue    = new object[] { attribute.Value };
                attrStatement.Items[i] = attr;
                i++;
            }
            assertion.Conditions = conditions;

            assertion.Items = new StatementAbstractType[] { authStatement, attrStatement };

            return(assertion);
        }
Exemplo n.º 2
0
    private void CreateSAMLResponse()
    {
        FormsIdentity id = null;

        if (HttpContext.Current.User != null)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    id = (FormsIdentity)HttpContext.Current.User.Identity;
                }
            }
        }

        DateTime notBefore    = (id != null ? id.Ticket.IssueDate.ToUniversalTime() : DateTime.UtcNow);
        DateTime notOnOrAfter = (id != null ? id.Ticket.Expiration.ToUniversalTime() : DateTime.UtcNow.AddMinutes(30));

        IDProvider config = IDProvider.GetConfig();

        SAMLResponse.Status                  = new StatusType();
        SAMLResponse.Status.StatusCode       = new StatusCodeType();
        SAMLResponse.Status.StatusCode.Value = SAMLUtility.StatusCodes.Success;

        AssertionType assert = new AssertionType();

        assert.ID           = SAMLUtility.GenerateID();
        assert.IssueInstant = DateTime.UtcNow.AddMinutes(10);

        assert.Issuer       = new NameIDType();
        assert.Issuer.Value = config.id;

        SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();

        subjectConfirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
        subjectConfirmation.SubjectConfirmationData              = new SubjectConfirmationDataType();
        subjectConfirmation.SubjectConfirmationData.Recipient    = SAMLRequest.Issuer;
        subjectConfirmation.SubjectConfirmationData.InResponseTo = SAMLRequest.Request.ID;
        subjectConfirmation.SubjectConfirmationData.NotOnOrAfter = notOnOrAfter;

        NameIDType nameID = new NameIDType();

        nameID.Format = SAMLUtility.NameIdentifierFormats.Transient;
        nameID.Value  = (id != null ? id.Name : UtilBO.FormatNameFormsAuthentication(this.__SessionWEB.__UsuarioWEB.Usuario));

        assert.Subject       = new SubjectType();
        assert.Subject.Items = new object[] { subjectConfirmation, nameID };

        assert.Conditions                       = new ConditionsType();
        assert.Conditions.NotBefore             = notBefore;
        assert.Conditions.NotOnOrAfter          = notOnOrAfter;
        assert.Conditions.NotBeforeSpecified    = true;
        assert.Conditions.NotOnOrAfterSpecified = true;

        AudienceRestrictionType audienceRestriction = new AudienceRestrictionType();

        audienceRestriction.Audience = new string[] { SAMLRequest.Issuer };
        assert.Conditions.Items      = new ConditionAbstractType[] { audienceRestriction };

        AuthnStatementType authnStatement = new AuthnStatementType();

        authnStatement.AuthnInstant = DateTime.UtcNow;
        authnStatement.SessionIndex = SAMLUtility.GenerateID();

        authnStatement.AuthnContext       = new AuthnContextType();
        authnStatement.AuthnContext.Items =
            new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" };

        authnStatement.AuthnContext.ItemsElementName =
            new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };

        StatementAbstractType[] statementAbstract = new StatementAbstractType[] { authnStatement };
        assert.Items       = statementAbstract;
        SAMLResponse.Items = new object[] { assert };

        string xmlResponse = SAMLUtility.SerializeToXmlString(SAMLResponse);

        XmlDocument doc = new XmlDocument();

        doc.LoadXml(xmlResponse);
        XmlSignatureUtils.SignDocument(doc, assert.ID);
        SAMLResponse = SAMLUtility.DeserializeFromXmlString <ResponseType>(doc.InnerXml);

        HttpPostBinding binding = new HttpPostBinding(SAMLResponse, HttpUtility.UrlDecode(Request[HttpBindingConstants.RelayState]));

        binding.SendResponse(this.Context, HttpUtility.UrlDecode(SAMLRequest.AssertionConsumerServiceURL), SAMLTypeSSO.signon);
    }
Exemplo n.º 3
0
        /// <summary>
        /// Handles the sign in.
        /// </summary>
        /// <returns></returns>
        /// <exception cref="SecurityTokenException">No token validator was found for the given token.</exception>
        private async Task <HandleRequestResult> HandleSignIn()
        {
            if (Request.Method != HttpMethods.Post)
            {
                return(HandleRequestResult.Fail("Request method must be an HTTP-Post Method"));
            }

            var form = await Request.ReadFormAsync();

            var response   = form[Saml2Constants.Parameters.SamlResponse];
            var relayState = form[Saml2Constants.Parameters.RelayState].ToString()?.DeflateDecompress();

            AuthenticationProperties authenticationProperties = Options.StateDataFormat.Unprotect(relayState);

            try
            {
                if (authenticationProperties == null)
                {
                    if (!Options.AllowUnsolicitedLogins)
                    {
                        return(HandleRequestResult.Fail("Unsolicited logins are not allowed."));
                    }
                }

                if (authenticationProperties.Items.TryGetValue(CorrelationProperty, out string correlationId) &&
                    !ValidateCorrelationId(authenticationProperties))
                {
                    return(HandleRequestResult.Fail("Correlation failed.", authenticationProperties));
                }

                string       base64EncodedSamlResponse = response;
                ResponseType idpSamlResponseToken      = _saml2Service.GetSamlResponseToken(base64EncodedSamlResponse, Saml2Constants.ResponseTypes.AuthnResponse, Options);

                IRequestCookieCollection cookies = Request.Cookies;
                string originalSamlRequestId     = cookies[cookies.Keys.FirstOrDefault(key => key.StartsWith(Options.AuthenticationScheme))];

                _saml2Service.CheckIfReplayAttack(idpSamlResponseToken.InResponseTo, originalSamlRequestId);
                _saml2Service.CheckStatus(idpSamlResponseToken);

                string token = _saml2Service.GetAssertion(idpSamlResponseToken, Options);

                AssertionType assertion     = new AssertionType();
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(AssertionType));
                using (MemoryStream memStm = new MemoryStream(Encoding.UTF8.GetBytes(token)))
                {
                    assertion = (AssertionType)xmlSerializer.Deserialize(memStm);
                }

                if (Options.WantAssertionsSigned)
                {
                    var doc = new XmlDocument
                    {
                        XmlResolver        = null,
                        PreserveWhitespace = true
                    };
                    doc.LoadXml(token);

                    if (!_saml2Service.ValidateX509CertificateSignature(doc, Options))
                    {
                        throw new Exception("Assertion signature is not valid");
                    }
                }

                AuthnStatementType session = new AuthnStatementType();

                if (assertion.Items.Any(x => x.GetType() == typeof(AuthnStatementType)))
                {
                    session = (AuthnStatementType)assertion.Items.FirstOrDefault(x => x.GetType() == typeof(AuthnStatementType));
                }

                if (assertion.Subject.Items.Any(x => x.GetType() == typeof(NameIDType)))
                {
                    Options.NameIDType = (NameIDType)assertion.Subject.Items.FirstOrDefault(x => x.GetType() == typeof(NameIDType));
                }

                if (_configuration == null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
                }

                var             tvp         = Options.TokenValidationParameters.Clone();
                var             validator   = Options.Saml2SecurityTokenHandler;
                ClaimsPrincipal principal   = null;
                SecurityToken   parsedToken = null;

                var issuers = new[] { _configuration.Issuer };
                tvp.ValidateIssuerSigningKey = Options.WantAssertionsSigned;
                tvp.ValidateTokenReplay      = !Options.IsPassive;
                tvp.ValidateIssuer           = true;
                tvp.ValidateAudience         = true;
                tvp.ValidIssuers             = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningKeys        = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat(_configuration.SigningKeys));

                if (!Options.WantAssertionsSigned) // in case they aren't signed
                {
                    tvp.RequireSignedTokens = false;
                }

                if (validator.CanReadToken(token))
                {
                    principal = validator.ValidateToken(token, tvp, out parsedToken);
                }

                if (principal == null)
                {
                    throw new SecurityTokenException("No token validator was found for the given token.");
                }

                if (Options.UseTokenLifetime && parsedToken != null)
                {
                    // Override any session persistence to match the token lifetime.
                    var issued = parsedToken.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        authenticationProperties.IssuedUtc = issued.ToUniversalTime();
                    }
                    var expires = parsedToken.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        authenticationProperties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    authenticationProperties.AllowRefresh = false;
                }

                ClaimsIdentity identity = new ClaimsIdentity(principal.Claims, Scheme.Name);

                session.SessionIndex = !String.IsNullOrEmpty(session.SessionIndex) ? session.SessionIndex : assertion.ID;
                //get the session index from assertion so you can use it to logout later
                identity.AddClaim(new Claim(Saml2ClaimTypes.SessionIndex, session.SessionIndex));
                identity.AddClaim(new Claim(ClaimTypes.Name, principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value));

                string redirectUrl = !string.IsNullOrEmpty(authenticationProperties.RedirectUri) ? authenticationProperties.RedirectUri : Options.CallbackPath.ToString();
                Context.Response.Redirect(redirectUrl, true);
                Context.User = new ClaimsPrincipal(identity);
                await Context.SignInAsync(Options.SignInScheme, Context.User, authenticationProperties);

                return(HandleRequestResult.Success(new AuthenticationTicket(Context.User, authenticationProperties, Scheme.Name)));
            }
            catch (Exception exception)
            {
                return(HandleRequestResult.Fail(exception, authenticationProperties));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a SAML 2.0 Assertion Segment for a Response
        /// Simple implmenetation assuming a list of string key and value pairs
        /// </summary>
        /// <param name="Issuer"></param>
        /// <param name="AssertionExpirationMinutes"></param>
        /// <param name="Audience"></param>
        /// <param name="Subject"></param>
        /// <param name="Recipient"></param>
        /// <param name="Attributes">Dictionary of string key, string value pairs</param>
        /// <returns>Assertion to sign and include in Response</returns>
        private static AssertionType CreateSAML20Assertion(string Issuer,
                                                           int AssertionExpirationMinutes,
                                                           string Audience,
                                                           string Subject,
                                                           string Recipient,
                                                           Dictionary <string, string> Attributes)
        {
            AssertionType NewAssertion = new AssertionType()
            {
                Version      = "2.0",
                IssueInstant = DateTime.Now,//DateTime.UtcNow,
                ID           = "_" + System.Guid.NewGuid().ToString()
            };

            // Create Issuer
            NewAssertion.Issuer = new NameIDType()
            {
                Value = Issuer.Trim()
            };

            // Create Assertion Subject
            SubjectType subject = new SubjectType();
            NameIDType  subjectNameIdentifier = new NameIDType()
            {
                Value = Subject.Trim(), Format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
            };
            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType()
            {
                Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer", SubjectConfirmationData = new SubjectConfirmationDataType()
                {
                    NotOnOrAfter = DateTime.Now.AddMinutes(AssertionExpirationMinutes), Recipient = Recipient
                }
            };                                                                                                                                                                                                                                                                                           //{ NotOnOrAfter = DateTime.UtcNow.AddMinutes(AssertionExpirationMinutes), Recipient = Recipient } };

            subject.Items        = new object[] { subjectNameIdentifier, subjectConfirmation };
            NewAssertion.Subject = subject;

            // Create Assertion Conditions
            ConditionsType conditions = new ConditionsType();

            conditions.NotBefore             = DateTime.Now;                                        //DateTime.UtcNow;
            conditions.NotBeforeSpecified    = true;
            conditions.NotOnOrAfter          = DateTime.Now.AddMinutes(AssertionExpirationMinutes); //DateTime.UtcNow.AddMinutes(AssertionExpirationMinutes);
            conditions.NotOnOrAfterSpecified = true;
            conditions.Items = new ConditionAbstractType[] { new AudienceRestrictionType()
                                                             {
                                                                 Audience = new string[] { Audience.Trim() }
                                                             } };
            NewAssertion.Conditions = conditions;

            // Add AuthnStatement and Attributes as Items
            AuthnStatementType authStatement = new AuthnStatementType()
            {
                AuthnInstant = DateTime.Now, SessionIndex = NewAssertion.ID
            };                                                                                                                           //{ AuthnInstant = DateTime.UtcNow, SessionIndex = NewAssertion.ID };
            AuthnContextType context = new AuthnContextType();

            context.ItemsElementName   = new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" };
            authStatement.AuthnContext = context;

            AttributeStatementType attributeStatement = new AttributeStatementType();

            attributeStatement.Items = new AttributeType[Attributes.Count];
            int i = 0;

            foreach (KeyValuePair <string, string> attribute in Attributes)
            {
                attributeStatement.Items[i] = new AttributeType()
                {
                    Name           = attribute.Key,
                    AttributeValue = new object[] { attribute.Value },
                    NameFormat     = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                };
                i++;
            }

            NewAssertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(NewAssertion);
        }
Exemplo n.º 5
0
        private static AssertionType CreateSamlAssertion(AuthnRequestType samlAuthRequest, string username)
        {
            var assertion = new AssertionType
            {
                Version      = "2.0",
                IssueInstant = DateTime.UtcNow,
                ID           = "_" + Guid.NewGuid(),
                Issuer       = new NameIDType()
                {
                    Value = $"{_context.Request.Scheme}://{_context.Request.Host}{_context.Request.PathBase}"
                }
            };

            //Assertion Subject
            var subject = new SubjectType();
            var subjectNameIdentifier = new NameIDType()
            {
                Value = username, Format = Saml2Constants.NameIdentifierFormats.Unspecified
            };
            var subjectConfirmation = new SubjectConfirmationType()
            {
                Method = Saml2Constants.SubjectConfirmationMethods.HolderOfKey,
                SubjectConfirmationData = new SubjectConfirmationDataType()
                {
                    NotOnOrAfter = DateTime.UtcNow.AddMinutes(ASSERTION_TIMEOUT_IN_MINUTES),
                    Recipient    = samlAuthRequest.AssertionConsumerServiceURL,
                    InResponseTo = samlAuthRequest.ID
                }
            };

            subject.Items     = new object[] { subjectNameIdentifier, subjectConfirmation };
            assertion.Subject = subject;

            //Assertion Conditions
            var conditions = new ConditionsType
            {
                NotBefore             = DateTime.UtcNow,
                NotBeforeSpecified    = true,
                NotOnOrAfter          = DateTime.UtcNow.AddMinutes(ASSERTION_TIMEOUT_IN_MINUTES),
                NotOnOrAfterSpecified = true,
                //TODO: samlAuthRequest.Issuer.Value should be replaced with
                Items = new ConditionAbstractType[] { new AudienceRestrictionType()
                                                      {
                                                          Audience = new string[] { samlAuthRequest.Issuer.Value }
                                                      } }
            };

            assertion.Conditions = conditions;

            //Assertion AuthnStatement
            var authStatement = new AuthnStatementType()
            {
                AuthnInstant = DateTime.UtcNow, SessionIndex = assertion.ID
            };
            var context = new AuthnContextType();

            context.ItemsElementName   = new[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" };
            authStatement.AuthnContext = context;

            //Assertion AttributeStatement
            var attributeStatement = new AttributeStatementType();

            attributeStatement.Items = new AttributeType[]
            {
                //Add as many attributes as you want here, these are the user details that service provider wants, we can customise the attributes required
                // on the basis of service provider that requires this assertion
                new AttributeType {
                    Name = "username", AttributeValue = username, NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                }
            };
            assertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(assertion);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a SAML 2.0 Assertion Segment for a Response
        /// Simple implmenetation assuming a list of string key and value pairs
        /// </summary>
        /// <param name="issuer"></param>
        /// <param name="assertionExpirationMinutes"></param>
        /// <param name="audience"></param>
        /// <param name="subject"></param>
        /// <param name="recipient"></param>
        /// <param name="attributes">Dictionary of string key, string value pairs</param>
        /// <returns>Assertion to sign and include in Response</returns>
        private static AssertionType CreateSaml20Assertion(string issuer,
                                                           int assertionExpirationMinutes,
                                                           string audience,
                                                           string subject,
                                                           string recipient,
                                                           Dictionary <string, string> attributes)
        {
            AssertionType newAssertion = new AssertionType
            {
                Version      = "2.0",
                IssueInstant = DateTime.UtcNow,
                ID           = "_" + Guid.NewGuid(),
                Issuer       = new NameIDType {
                    Value = issuer.Trim()
                }
            };

            // Create Issuer

            // Create Assertion Subject
            SubjectType subjectType           = new SubjectType();
            NameIDType  subjectNameIdentifier = new NameIDType {
                Value = subject.Trim(), Format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
            };
            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType {
                Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer", SubjectConfirmationData = new SubjectConfirmationDataType {
                    NotOnOrAfter = DateTime.UtcNow.AddMinutes(assertionExpirationMinutes), Recipient = recipient
                }
            };

            subjectType.Items    = new object[] { subjectNameIdentifier, subjectConfirmation };
            newAssertion.Subject = subjectType;

            // Create Assertion Conditions
            ConditionsType conditions = new ConditionsType
            {
                NotBefore             = DateTime.UtcNow,
                NotBeforeSpecified    = true,
                NotOnOrAfter          = DateTime.UtcNow.AddMinutes(assertionExpirationMinutes),
                NotOnOrAfterSpecified = true,
                Items = new ConditionAbstractType[] { new AudienceRestrictionType {
                                                          Audience = new[] { audience.Trim() }
                                                      } }
            };

            newAssertion.Conditions = conditions;

            // Add AuthnStatement and Attributes as Items
            AuthnStatementType authStatement = new AuthnStatementType {
                AuthnInstant = DateTime.UtcNow, SessionIndex = newAssertion.ID
            };
            AuthnContextType context = new AuthnContextType
            {
                ItemsElementName = new[] { ItemsChoiceType5.AuthnContextClassRef },
                Items            = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" }
            };

            authStatement.AuthnContext = context;

            AttributeStatementType attributeStatement = new AttributeStatementType
            {
                Items = new object[attributes.Count]
            };
            int i = 0;

            foreach (KeyValuePair <string, string> attribute in attributes)
            {
                attributeStatement.Items[i] = new AttributeType
                {
                    Name           = attribute.Key,
                    AttributeValue = new object[] { attribute.Value },
                    NameFormat     = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                };
                i++;
            }

            newAssertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(newAssertion);
        }
Exemplo n.º 7
0
        public void Deserialize(string samlResponse)
        {
            ResponseType response = new ResponseType();

            try
            {
                using (TextReader sr = new StringReader(samlResponse))
                {
                    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(ResponseType));
                    response = (ResponseType)serializer.Deserialize(sr);

                    this.Version = response.Version;
                    this.UUID    = response.ID;
                    this.SPUID   = response.InResponseTo;
                    this.Issuer  = response.Issuer.Value;

                    switch (response.Status.StatusCode.Value)
                    {
                    case "urn:oasis:names:tc:SAML:2.0:status:Success":
                        this.RequestStatus = SamlRequestStatus.Success;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:Requester":
                        this.RequestStatus = SamlRequestStatus.RequesterError;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:Responder":
                        this.RequestStatus = SamlRequestStatus.ResponderError;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch":
                        this.RequestStatus = SamlRequestStatus.VersionMismatchError;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:AuthnFailed":
                        this.RequestStatus = SamlRequestStatus.AuthnFailed;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue":
                        this.RequestStatus = SamlRequestStatus.InvalidAttrNameOrValue;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy":
                        this.RequestStatus = SamlRequestStatus.InvalidNameIDPolicy;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext":
                        this.RequestStatus = SamlRequestStatus.NoAuthnContext;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP":
                        this.RequestStatus = SamlRequestStatus.NoAvailableIDP;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:NoPassive":
                        this.RequestStatus = SamlRequestStatus.NoPassive;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP":
                        this.RequestStatus = SamlRequestStatus.NoSupportedIDP;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:PartialLogout":
                        this.RequestStatus = SamlRequestStatus.PartialLogout;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded":
                        this.RequestStatus = SamlRequestStatus.ProxyCountExceeded;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:RequestDenied":
                        this.RequestStatus = SamlRequestStatus.RequestDenied;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported":
                        this.RequestStatus = SamlRequestStatus.RequestUnsupported;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated":
                        this.RequestStatus = SamlRequestStatus.RequestVersionDeprecated;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh":
                        this.RequestStatus = SamlRequestStatus.RequestVersionTooHigh;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow":
                        this.RequestStatus = SamlRequestStatus.RequestVersionTooLow;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized":
                        this.RequestStatus = SamlRequestStatus.ResourceNotRecognized;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses":
                        this.RequestStatus = SamlRequestStatus.TooManyResponses;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile":
                        this.RequestStatus = SamlRequestStatus.UnknownAttrProfile;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal":
                        this.RequestStatus = SamlRequestStatus.UnknownPrincipal;
                        break;

                    case "urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding":
                        this.RequestStatus = SamlRequestStatus.UnsupportedBinding;
                        break;

                    default:
                        this.RequestStatus = SamlRequestStatus.GenericError;
                        break;
                    }

                    if (this.RequestStatus == SamlRequestStatus.Success)
                    {
                        foreach (var item in response.Items)
                        {
                            if (item.GetType() == typeof(AssertionType))
                            {
                                AssertionType ass = (AssertionType)item;
                                this.SessionIdExpireDate = (ass.Conditions.NotOnOrAfter != null) ? ass.Conditions.NotOnOrAfter : DateTime.Now.AddMinutes(20);

                                foreach (var subitem in ass.Subject.Items)
                                {
                                    if (subitem.GetType() == typeof(NameIDType))
                                    {
                                        NameIDType nameId = (NameIDType)subitem;
                                        this.SubjectNameId = nameId.Value; //.Replace("SPID-","");
                                    }
                                }

                                foreach (var assItem in ass.Items)
                                {
                                    if (assItem.GetType() == typeof(AuthnStatementType))
                                    {
                                        AuthnStatementType authnStatement = (AuthnStatementType)assItem;
                                        this.SessionId           = authnStatement.SessionIndex;
                                        this.SessionIdExpireDate = (authnStatement.SessionNotOnOrAfterSpecified) ? authnStatement.SessionNotOnOrAfter : this.SessionIdExpireDate;
                                    }

                                    if (assItem.GetType() == typeof(AttributeStatementType))
                                    {
                                        AttributeStatementType statement = (AttributeStatementType)assItem;

                                        foreach (AttributeType attribute in statement.Items)
                                        {
                                            switch (attribute.Name)
                                            {
                                            case "spidCode":
                                                this.User.SpidCode = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "name":
                                                this.User.Name = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "familyName":
                                                this.User.FamilyName = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "gender":
                                                this.User.Gender = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "ivaCode":
                                                this.User.IvaCode = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "companyName":
                                                this.User.CompanyName = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "mobilePhone":
                                                this.User.MobilePhone = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "address":
                                                this.User.Address = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "fiscalNumber":
                                                this.User.FiscalNumber = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "dateOfBirth":
                                                this.User.DateOfBirth = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "placeOfBirth":
                                                this.User.PlaceOfBirth = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "countyOfBirth":
                                                this.User.CountyOfBirth = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "idCard":
                                                this.User.IdCard = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "registeredOffice":
                                                this.User.RegisteredOffice = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "email":
                                                this.User.Email = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "expirationDate":
                                                this.User.ExpirationDate = attribute.AttributeValue[0].ToString();
                                                break;

                                            case "digitalAddress":
                                                this.User.DigitalAddress = attribute.AttributeValue[0].ToString();
                                                break;

                                            default:
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //TODO Log
                throw ex;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private XmlDocument GenerateResponseMetadata(SAMLContext context, string id)
        {
            DateTime      now    = DateTime.UtcNow;
            MemoryStream  stream = new MemoryStream();
            StreamReader  reader;
            XmlTextReader xmlReader;

            ResponseType response = new ResponseType();

            response.ID           = id;
            response.InResponseTo = context.RequestID;
            response.Version      = SAMLConstants.SAML_VERSION;
            response.IssueInstant = now;

            response.Destination   = context.AssertionConsumer;
            response.Consent       = SAMLConstants.CONSENT;
            response.Issuer        = new NameIDType();
            response.Issuer.Value  = thisIssuer;
            response.Issuer.Format = SAMLConstants.ThisIssuerFormat;

            response.Status                  = new StatusType();
            response.Status.StatusCode       = new StatusCodeType();
            response.Status.StatusCode.Value = SAMLConstants.StatusCode.statusCode[context.StatusCode];
            if (context.StatusCode != SAMLConstants.StatusCode.SUCCESS)
            {
                response.Status.StatusCode.StatusCode       = new StatusCodeType();
                response.Status.StatusCode.StatusCode.Value =
                    SAMLConstants.StatusCode.statusCode[context.SubStatusCode];
                response.Status.StatusMessage = context.StatusMessage;
            }

            AssertionType assertion = new AssertionType();

            assertion.ID           = "_" + Guid.NewGuid().ToString();
            assertion.Version      = SAMLConstants.SAML_VERSION;
            assertion.IssueInstant = now;

            assertion.Issuer        = new NameIDType();
            assertion.Issuer.Value  = thisIssuer;
            assertion.Issuer.Format = SAMLConstants.ThisIssuerFormat;

            assertion.Subject = new SubjectType();
            NameIDType nameId = new NameIDType();

            nameId.Format = "urn:oasis:names:tc:SAML:1.1:nameid- format:unspecified";
            //nameId.NameQualifier = "http://C-PEPS.gov.xx";
            nameId.Value = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";

            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();

            subjectConfirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
            subjectConfirmation.SubjectConfirmationData              = new SubjectConfirmationDataType();
            subjectConfirmation.SubjectConfirmationData.Address      = context.SubjectAddress;
            subjectConfirmation.SubjectConfirmationData.InResponseTo = context.RequestID;
            //subjectConfirmation.SubjectConfirmationData.NotBeforeString = "2010-02-03T17:06:18.099Z";
            subjectConfirmation.SubjectConfirmationData.NotOnOrAfterString =
                String.Format("{0:yyyy-MM-ddTHH:mm:ssZ}", now.AddMinutes(validTimeframe));
            subjectConfirmation.SubjectConfirmationData.Recipient = context.Issuer;
            assertion.Subject.Items = new object[] { nameId, subjectConfirmation };

            assertion.Conditions = new ConditionsType();
            assertion.Conditions.NotBeforeString    = String.Format("{0:yyyy-MM-ddTHH:mm:ssZ}", now);
            assertion.Conditions.NotOnOrAfterString =
                String.Format("{0:yyyy-MM-ddTHH:mm:ssZ}", now.AddMinutes(validTimeframe));

            AudienceRestrictionType audience = new AudienceRestrictionType();

            audience.Audience          = new string[] { context.Issuer }; // FIXME
            assertion.Conditions.Items = new ConditionAbstractType[] { audience, new OneTimeUseType() };

            AuthnStatementType authnStatement = new AuthnStatementType();

            authnStatement.AuthnInstant = now;
            authnStatement.AuthnContext = new AuthnContextType();

            List <AttributeElement> attributes = context.GetAttributes();

            object[]      attributesDescription = new AttributeType[attributes.Count];
            AttributeType attr;
            XmlAttribute  statusAttr;
            int           i = 0;

            foreach (AttributeElement element in attributes)
            {
                attr            = new AttributeType();
                attr.Name       = element.AttrName;
                attr.NameFormat = element.NameFormat;
                if (context.StatusCode == SAMLConstants.StatusCode.SUCCESS)
                {
                    if (element.AttrStatus == SAMLConstants.AttributeStatus.AVAILABLE &&
                        element.AttrValue != null)
                    {
                        attr.AttributeValue = new object[] { element.AttrValue }
                    }
                    ;
                    if (element.AttrStatus >= 0)
                    {
                        statusAttr = new XmlDocument().
                                     CreateAttribute(SAMLConstants.ATTRIBUTE_STATUS_STR, SAMLConstants.NS_STORK_ASSER);
                        statusAttr.Value = element.Status;
                        attr.AnyAttr     = new XmlAttribute[] { statusAttr };
                    }
                }
                attributesDescription[i++] = attr;
            }

            AttributeStatementType attributeStatement = new AttributeStatementType();

            attributeStatement.Items = attributesDescription;
            assertion.Items          = new StatementAbstractType[] { authnStatement, attributeStatement };
            response.Items           = new object[] { assertion };

            stream = new MemoryStream();
            Serialize(response, stream);

            reader = new StreamReader(stream);
            stream.Seek(0, SeekOrigin.Begin);
            xmlReader = new XmlTextReader(new StringReader(reader.ReadToEnd()));
            return(Deserialize <XmlDocument>(xmlReader));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Handles the sign in.
        /// </summary>
        /// <returns></returns>
        /// <exception cref="SecurityTokenException">No token validator was found for the given token.</exception>
        private async Task <HandleRequestResult> HandleSignIn()
        {
            if (Request.Method != HttpMethods.Post)
            {
                return(HandleRequestResult.Fail("Request method must be an HTTP-Post Method"));
            }

            var form = await Request.ReadFormAsync();

            var response   = form[Saml2Constants.Parameters.SamlResponse];
            var relayState = form[Saml2Constants.Parameters.RelayState].ToString()?.DeflateDecompress();

            AuthenticationProperties authenticationProperties = Options.StateDataFormat.Unprotect(relayState);

            try
            {
                if (authenticationProperties == null)
                {
                    if (!Options.AllowUnsolicitedLogins)
                    {
                        return(HandleRequestResult.Fail("Unsolicited logins are not allowed."));
                    }
                }

                if (authenticationProperties.Items.TryGetValue(CorrelationProperty, out string correlationId) &&
                    !ValidateCorrelationId(authenticationProperties))
                {
                    return(HandleRequestResult.Fail("Correlation failed.", authenticationProperties));
                }

                string       base64EncodedSamlResponse = response;
                ResponseType idpSamlResponseToken      = _saml2Service.GetSamlResponseToken(base64EncodedSamlResponse, Saml2Constants.ResponseTypes.AuthnResponse, Options);

                // Write To XML Doc `_xmlDoc` Object, This Step Is Critical For The ValidateToken Call Below.
                LoadXmlFromBase64(response);

                IRequestCookieCollection cookies = Request.Cookies;
                string originalSamlRequestId     = cookies[cookies.Keys.FirstOrDefault(key => key.StartsWith(Options.AuthenticationScheme))];

                _saml2Service.CheckIfReplayAttack(idpSamlResponseToken.InResponseTo, originalSamlRequestId);
                _saml2Service.CheckStatus(idpSamlResponseToken);

                string token = _saml2Service.GetAssertion(idpSamlResponseToken, Options);

                AssertionType assertion     = new AssertionType();
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(AssertionType));
                using (MemoryStream memStm = new MemoryStream(Encoding.UTF8.GetBytes(token)))
                {
                    assertion = (AssertionType)xmlSerializer.Deserialize(memStm);
                }

                if (Options.WantAssertionsSigned)
                {
                    var doc = new XmlDocument
                    {
                        XmlResolver        = null,
                        PreserveWhitespace = true
                    };
                    doc.LoadXml(token);

                    if (!_saml2Service.ValidateX509CertificateSignature(doc, Options))
                    {
                        throw new Exception("Assertion signature is not valid");
                    }
                }

                AuthnStatementType session = new AuthnStatementType();

                if (assertion.Items.Any(x => x.GetType() == typeof(AuthnStatementType)))
                {
                    session = (AuthnStatementType)assertion.Items.FirstOrDefault(x => x.GetType() == typeof(AuthnStatementType));
                }

                if (assertion.Subject.Items.Any(x => x.GetType() == typeof(NameIDType)))
                {
                    Options.NameIDType = (NameIDType)assertion.Subject.Items.FirstOrDefault(x => x.GetType() == typeof(NameIDType));
                }

                if (_configuration == null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
                }

                var             tvp         = Options.TokenValidationParameters.Clone();
                var             validator   = Options.Saml2SecurityTokenHandler;
                ClaimsPrincipal principal   = null;
                SecurityToken   parsedToken = null;

                var issuers = new[] { _configuration.Issuer };
                tvp.ValidateIssuerSigningKey = Options.WantAssertionsSigned;
                tvp.ValidateTokenReplay      = !Options.IsPassive;
                tvp.ValidateIssuer           = true;
                tvp.ValidateAudience         = true;
                tvp.ValidIssuers             = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningKeys        = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat(_configuration.SigningKeys));

                if (!Options.WantAssertionsSigned) // in case they aren't signed
                {
                    tvp.RequireSignedTokens = false;
                }

                if (Options.EnablePIILogging)
                {
                    IdentityModelEventSource.ShowPII = true;
                }

                if (validator.CanReadToken(token))
                {
                    // Our Token Is Valid, Now Check Signaures.

                    var doc = new XmlDocument
                    {
                        XmlResolver        = null,
                        PreserveWhitespace = true
                    };
                    doc.LoadXml(token);

                    // Pull Signatures.

                    XmlNodeList XMLSignatures = doc.GetElementsByTagName(Saml2Constants.Parameters.Signature, Saml2Constants.Namespaces.DsNamespace);

                    var signedXmlDoc = new SignedXml(doc);

                    signedXmlDoc.LoadXml((XmlElement)XMLSignatures[0]);

                    KeyInfoX509Data  x509data     = signedXmlDoc.Signature.KeyInfo.OfType <KeyInfoX509Data>().First();
                    X509Certificate2 cert         = (X509Certificate2)x509data.Certificates[0];
                    string           serialNumber = cert.SerialNumber;
                    X509Certificate2 _idpcert     = Options.Configuration.X509Certificate2.Where(c => c.SerialNumber == serialNumber).FirstOrDefault();

                    var _xmlNameSpaceManager = GetNamespaceManager(); // Manager For XPath Queries.

                    // Important: To Check Signatures We Pull The Signature XML Node.

                    // Critically This Check Differers From The ValidateToken Call Below, See Note.

                    XmlNodeList nodeList  = _xmlDoc.SelectNodes(".//ds:Signature", _xmlNameSpaceManager);
                    SignedXml   signedXml = new SignedXml(_xmlDoc);
                    signedXml.LoadXml((XmlElement)nodeList[0]);

                    var check_reference = ValidateSignatureReference(signedXml);
                    var check_signature = signedXml.CheckSignature(cert, true);

                    if (check_reference && check_signature)
                    {
                        // Tech Note: At This Point We've:

                        // 1. Verified The Token.
                        // 2. Verified The Signature Reference.
                        // 3. Verified The Signature For The Entire Document, And The Specific Assertion.

                        // The Final Step Is To Create Our Security Principal Via The ValidateToken() Call.

                        // The Big "Trick" Here Is This Call Is Known To Fail When The XML Source Is Not .NET.

                        // Specifically, The Signature Validation Process Requires The XML Byte Stream To Be Identical,
                        // And Unfortunately Our Token Call Above, Among Other Things, Strips XML Namespaces And Changes Line Feeds.

                        // To Address This We Pass This Call The "Original" XML From The LoadXmlFromBase64() Call Above.
                        try
                        {
                            XmlNodeList nodeListAssertion = _xmlDoc.SelectNodes(".//saml:Assertion", _xmlNameSpaceManager);

                            // This Call Maps Our SAML <saml2:AttributeStatement> Items To Our Identity As Claims.

                            principal = validator.ValidateToken(nodeListAssertion[0].OuterXml, tvp, out parsedToken);
                        }
                        catch (Exception e) { }
                    }
                }

                if (principal == null)
                {
                    throw new SecurityTokenException("No token validator was found for the given token.");
                }

                if (Options.UseTokenLifetime && parsedToken != null)
                {
                    // Override any session persistence to match the token lifetime.
                    var issued = parsedToken.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        authenticationProperties.IssuedUtc = issued.ToUniversalTime();
                    }
                    var expires = parsedToken.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        authenticationProperties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    authenticationProperties.AllowRefresh = false;
                }

                ClaimsIdentity identity = new ClaimsIdentity(principal.Claims, Scheme.Name);

                session.SessionIndex = !String.IsNullOrEmpty(session.SessionIndex) ? session.SessionIndex : assertion.ID;

                //get the session index from assertion so you can use it to logout later
                identity.AddClaim(new Claim(Saml2ClaimTypes.SessionIndex, session.SessionIndex));

                // Create Entry For User.Identity.Name

                if (principal.Claims.Any(c => c.Type == ClaimTypes.NameIdentifier))
                {
                    identity.AddClaim(new Claim(ClaimTypes.Name, principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value));
                }

                string redirectUrl = !string.IsNullOrEmpty(authenticationProperties.RedirectUri) ? authenticationProperties.RedirectUri : Options.CallbackPath.ToString();
                Context.Response.Redirect(redirectUrl, true);
                Context.User = new ClaimsPrincipal(identity);
                await Context.SignInAsync(Options.SignInScheme, Context.User, authenticationProperties);

                return(HandleRequestResult.Success(new AuthenticationTicket(Context.User, authenticationProperties, Scheme.Name)));
            }
            catch (Exception exception)
            {
                return(HandleRequestResult.Fail(exception, authenticationProperties));
            }
        }