public bool IsValid(AssertionModel assertionModel)
        {
            try
            {
                if (!_decodedJwtValidator.IsIShareCompliant(CreateTokenValidationArgs(assertionModel)))
                {
                    return(false);
                }

                if (!IsRootCertificateTrusted(CertificateUtilities.FromBase64Der(assertionModel.Certificates.Last())))
                {
                    _logger.LogWarning("SO root certificate is untrusted.");

                    return(false);
                }

                var x509Certificate        = CertificateUtilities.FromBase64Der(assertionModel.Certificates.First());
                var additionalCertificates = assertionModel.Certificates.Skip(1)
                                             .Select(CertificateUtilities.FromBase64Der)
                                             .ToArray();

                return(IsChainValid(x509Certificate, additionalCertificates) && DoesBelongToSchemeOwner(x509Certificate));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Error occurred while validating token response retrieved from Scheme Owner.");

                return(false);
            }
        }
        public void IsValid_ValidAndTrusted_ReturnsTrue()
        {
            var jwtString = CreateJwtString();
            // screwing assertionModel because signing jwtString with SO private key is not an option
            // we won't expose private key to you! :)
            var assertionModel = new AssertionModel(
                new[]
            {
                Constants.TrustedCertificates.PublicKeyBase64Der,
                Constants.TrustedCertificates.RootCaPublicKeyBase64Der
            },
                (JwtSecurityToken) new JwtSecurityTokenHandler().ReadToken(jwtString),
                jwtString);

            _decodedJwtValidatorMock
            .Setup(x => x.IsIShareCompliant(It.IsAny <TokenValidationArgs>()))
            .Returns(true);
            var sut = new SchemeOwnerJwtTokenResponseValidator(
                _decodedJwtValidatorMock.Object,
                new ProductionEnvironmentRootCertificateStorage(),
                _loggerMock.Object,
                new ProductionCaStrategy(),
                _settings);

            var result = sut.IsValid(assertionModel);

            result.Should().BeTrue();
        }
Пример #3
0
        /// <summary>
        /// Constructor for object which is used to encapsulate <see cref="IJwtTokenResponseValidator"/> parameters.
        /// </summary>
        /// <param name="assertionModel">Assertion model which contains JWT contents.</param>
        /// <param name="issuer">Party's EORI which issued the token.</param>
        /// <param name="audience">
        /// Party's EORI to whom token was issued. If not exists, then it won't be validated.
        /// E.x. Some response, like /capabilities can be accessed anonymously, that's why this validation is optional.
        /// </param>
        /// <exception cref="ArgumentNullException">Any of values are null or strings are whitespaces.</exception>
        public TokenValidationArgs(AssertionModel assertionModel, string issuer, string audience = null)
        {
            ValidateArguments(assertionModel, issuer, audience);

            AssertionModel = assertionModel;
            Issuer         = issuer;
            Audience       = audience;
        }
        public void IsIShareCompliant_KeysNotFound_ReturnsFalse()
        {
            var assertionModel = new AssertionModel(new string[0], null, null);
            var args           = new TokenValidationArgs(assertionModel, "issuer", "audience");

            var result = _sut.IsIShareCompliant(args);

            result.Should().BeFalse();
        }
Пример #5
0
        public async Task <ActionResult> Index(HomePageModel model)
        {
            if (ModelState.IsValid)
            {
                var LDAPEndpoint = ConfigurationManager.AppSettings["LDAP.Endpoint"];

                if (String.IsNullOrEmpty(LDAPEndpoint))
                {
                    throw new ConfigurationErrorsException("ConfigurationManager.AppSettings[\"LDAP.Endpoint\"] should not be null.");
                }

                var client = new HttpClient();
                var result = await client.PostAsJsonAsync(LDAPEndpoint, new { Username = model.Username, Password = model.Password });

                if (!result.IsSuccessStatusCode)
                {
                    if (result.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        ModelState.AddModelError("LDAP.Endpoint", "Username or Password not valid.");
                    }
                    else
                    {
                        ModelState.AddModelError("LDAP.Endpoint", "An error has ocurred. Please contact administrator.");
                    }

                    return(View(model));
                }

                var assertionModel = AssertionModel.Create(nameId: model.Username);

                var requestData = Request.ToHttpRequestData(true);

                if (requestData.QueryString["SAMLRequest"].Any())
                {
                    var extractedMessage = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                                           .Unbind(requestData, null);

                    var request = new Saml2AuthenticationRequest(
                        extractedMessage.Data,
                        extractedMessage.RelayState);

                    assertionModel.InResponseTo = request.Id.Value;
                    assertionModel.AssertionConsumerServiceUrl = request.AssertionConsumerServiceUrl.ToString();
                    assertionModel.RelayState      = extractedMessage.RelayState;
                    assertionModel.Audience        = request.Issuer.Id;
                    assertionModel.AuthnRequestXml = extractedMessage.Data.PrettyPrint();

                    var response = assertionModel.ToSaml2Response();

                    return(Saml2Binding.Get(assertionModel.ResponseBinding)
                           .Bind(response).ToActionResult());
                }
            }

            return(View(model));
        }
        public void IsValid_ExceptionOccurs_HandlesAndReturnsFalse()
        {
            _decodedJwtValidatorMock
            .Setup(x => x.IsIShareCompliant(It.IsAny <TokenValidationArgs>()))
            .Returns(true);
            var jwtString      = CreateJwtString();
            var assertionModel = new AssertionModel(null, CreateToken(jwtString), jwtString);

            var result = _sut.IsValid(assertionModel);

            result.Should().BeFalse();
        }
        public ActionResult Index(Guid?idpId)
        {
            var model = new HomePageModel
            {
                AssertionModel = AssertionModel.CreateFromConfiguration(),
            };

            ReadCustomIdpConfig(idpId, model);

            HandleReceivedAuthnReqest(model);

            return(View(model));
        }
Пример #8
0
        public ActionResult Index()
        {
            var model   = AssertionModel.CreateFromConfiguration();
            var request = Saml2AuthenticationRequest.Read(Saml2Binding.Get(Saml2BindingType.HttpRedirect).Unbind(Request));

            if (request != null)
            {
                model.InResponseTo = request.Id;
                model.AssertionConsumerServiceUrl = request.AssertionConsumerServiceUrl.ToString();
            }

            return(View(model));
        }
Пример #9
0
        public ActionResult Index(AssertionModel model)
        {
            if (ModelState.IsValid)
            {
                var response = model.ToSaml2Response();

                var commandResult = Saml2Binding.Get(Saml2BindingType.HttpPost)
                                    .Bind(response);

                return(commandResult.ToActionResult());
            }

            return(View(model));
        }
Пример #10
0
        public ActionResult Index(Guid?idpId)
        {
            var model = new HomePageModel
            {
                AssertionModel = AssertionModel.CreateFromConfiguration(),
            };

            if (idpId.HasValue)
            {
                var fileData = GetCachedConfiguration(idpId.Value);
                if (fileData != null)
                {
                    if (!string.IsNullOrEmpty(fileData.DefaultAssertionConsumerServiceUrl))
                    {
                        // Override default StubIdp Acs with Acs from IdpConfiguration
                        model.AssertionModel.AssertionConsumerServiceUrl = fileData.DefaultAssertionConsumerServiceUrl;
                    }
                    if (!string.IsNullOrEmpty(fileData.DefaultAssertionConsumerServiceUrl))
                    {
                        model.AssertionModel.Audience = fileData.DefaultAudience;
                    }

                    model.CustomDescription     = fileData.IdpDescription;
                    model.AssertionModel.NameId = null;
                    model.HideDetails           = fileData.HideDetails;
                }
            }

            var requestData = Request.ToHttpRequestData(false);

            if (requestData.QueryString["SAMLRequest"].Any())
            {
                var extractedMessage = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                                       .Unbind(requestData, null);

                var request = new Saml2AuthenticationRequest(
                    extractedMessage.Data,
                    extractedMessage.RelayState);

                model.AssertionModel.InResponseTo = request.Id.Value;
                model.AssertionModel.AssertionConsumerServiceUrl = request.AssertionConsumerServiceUrl.ToString();
                model.AssertionModel.RelayState      = extractedMessage.RelayState;
                model.AssertionModel.Audience        = request.Issuer.Id;
                model.AssertionModel.AuthnRequestXml = extractedMessage.Data.PrettyPrint();
            }

            return(View(model));
        }
        public async Task <SecretValidationResult> ValidateAsync(AssertionModel assertion)
        {
            var fail = new SecretValidationResult {
                Success = false
            };

            if (assertion == null)
            {
                _logger.LogInformation("The client assertion is not provided.");
                return(fail);
            }

            if (assertion.Typ == null || !assertion.Typ.Equals("jwt", StringComparison.InvariantCultureIgnoreCase))
            {
                _logger.LogError("Client assertion \"typ\" header is not \"JWT\".");
                return(fail);
            }

            if (assertion.Exp - assertion.Iat != 30)
            {
                _logger.LogError("Client assertion validity should be exactly 30 seconds.");
                return(fail);
            }

            if (!assertion.Certificates.Any())
            {
                _logger.LogInformation("The x5c certificates chain is not provided.");
                return(fail);
            }

            try
            {
                if (!await _certificateValidator.IsValid(DateTime.UtcNow, assertion.Certificates.ToArray()))
                {
                    _logger.LogInformation("Certificate chain is not valid");
                    return(fail);
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Could not load certificate from x5C header.");
                return(fail);
            }

            return(await Task.FromResult(new SecretValidationResult { Success = true }));
        }
Пример #12
0
        private static void ValidateArguments(AssertionModel assertionModel, string issuer, string audience)
        {
            if (assertionModel == null)
            {
                throw new ArgumentNullException(nameof(assertionModel));
            }

            if (string.IsNullOrWhiteSpace(issuer))
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            if (audience != null && string.IsNullOrWhiteSpace(audience))
            {
                throw new ArgumentNullException(nameof(audience), "It cannot be empty or whitespace.");
            }
        }
Пример #13
0
        public ActionResult Index()
        {
            var model = AssertionModel.CreateFromConfiguration();

            var requestData = Request.ToHttpRequestData();

            if (requestData.QueryString["SAMLRequest"].Any())
            {
                var decodedXmlData = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                                     .Unbind(requestData);

                var request = Saml2AuthenticationRequest.Read(decodedXmlData);

                model.InResponseTo = request.Id;
                model.AssertionConsumerServiceUrl = request.AssertionConsumerServiceUrl.ToString();
                model.AuthnRequestXml             = decodedXmlData;
            }

            return(View(model));
        }
Пример #14
0
        public ActionResult Index(Guid?idpId)
        {
            var requestData = Request.ToHttpRequestData();

            if (requestData.QueryString["SAMLRequest"].Any())
            {
                var decodedXmlData = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                                     .Unbind(requestData);

                var request = Saml2AuthenticationRequest.Read(decodedXmlData);

                var model = new AssertionModel();

                model.InResponseTo = request.Id;
                model.AssertionConsumerServiceUrl = request.AssertionConsumerServiceUrl.ToString();
                model.AuthnRequestXml             = decodedXmlData;
                model.NameId = ((ClaimsIdentity)User.Identity).Name;

                var manager = SessionManager.Instance;


                var response = model.ToSaml2Response();

                manager.AddSession(model.NameId, new Session()
                {
                    Id        = Guid.Parse(request.Id.Substring(2)),
                    Ip        = Request.UserHostAddress,
                    UserAgent = Request.UserAgent,
                    LogoutUrl = request.Issuer.Id,
                    Issuer    = response.Issuer.Id
                });

                var commandResult = Saml2Binding.Get(Saml2BindingType.HttpPost)
                                    .Bind(response);

                return(commandResult.ToActionResult());
            }

            throw new InvalidOperationException();
        }
        public void IsValid_JwtSignedUsingSOCertButChainIncomplete_ReturnsFalse()
        {
            // screwing assertionModel because signing jwtString with SO private key is not an option
            // we won't expose private key to you! :)
            var jwtString      = CreateJwtString();
            var assertionModel = new AssertionModel(
                new[]
            {
                Constants.SchemeOwner.PublicKeyBase64Der,
                Constants.TestCertificateAuthority.RootCaPublicKeyBase64Der
            },
                (JwtSecurityToken) new JwtSecurityTokenHandler().ReadToken(jwtString),
                jwtString);

            _decodedJwtValidatorMock
            .Setup(x => x.IsIShareCompliant(It.IsAny <TokenValidationArgs>()))
            .Returns(true);

            var result = _sut.IsValid(assertionModel);

            result.Should().BeFalse();
        }
        public ActionResult Index(Guid?idpId, HomePageModel model)
        {
            if (ModelState.IsValid)
            {
                var response = model.AssertionModel.ToSaml2Response();

                return(Saml2Binding.Get(model.AssertionModel.ResponseBinding)
                       .Bind(response).ToActionResult());
            }

            if (model.AssertionModel == null)
            {
                model.AssertionModel = AssertionModel.CreateFromConfiguration();
            }
            ;

            if (HandleReceivedAuthnReqest(model))
            {
                ReadCustomIdpConfig(idpId, model);
            }

            return(View(model));
        }
Пример #17
0
        public void IsIShareCompliant_AssertionModelContainsDifferentJwtSecurityTokenThanItsString_ReturnsFalse()
        {
            var jwtToken         = CreateValidJwtToken();
            var handler          = new JwtSecurityTokenHandler();
            var jwtSecurityToken = handler.ReadJwtToken(jwtToken);
            var assertionModel   = new AssertionModel(
                new[] { Constants.AbcParty.PublicKeyBase64Der },
                jwtSecurityToken,
                CreateValidJwtToken());
            var args = new TokenValidationArgs(
                assertionModel,
                Constants.SchemeOwner.ClientId,
                Constants.AbcParty.ClientId);

            var result = _sut.IsIShareCompliant(args);

            const string reason =
                "JWT is valid because assertion model contains its public keys which were extracted " +
                "from JwtSecurityToken. Those public keys applies for JwtToken (string). However, " +
                "those public keys were not extracted from the token which is being validated, so " +
                "validation should fail.";

            result.Should().BeFalse(reason);
        }
Пример #18
0
 private TokenValidationArgs CreateValidationArgs(CapabilitiesRequestArgs args, AssertionModel assertionModel)
 {
     return(new TokenValidationArgs(
                assertionModel,
                args.RequestedPartyId,
                args.AccessToken == null ? null : _eori));
 }
 private TokenValidationArgs CreateTokenValidationArgs(AssertionModel assertionModel) =>
 new TokenValidationArgs(assertionModel, Constants.SchemeOwnerEori, _partyId);
Пример #20
0
 private List <SecurityKey> GetTrustedKeys(AssertionModel assertion) =>
 GetAllTrustedCertificates(assertion)
 .Select(c => (SecurityKey) new X509SecurityKey(c))
 .ToList();
Пример #21
0
 private IEnumerable <X509Certificate2> GetAllTrustedCertificates(AssertionModel model) =>
 model.Certificates
 .Select(GetCertificateFromString)
 .Where(c => c != null)
 .ToList();