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(); }
/// <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(); }
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)); }
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)); }
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)); }
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 })); }
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."); } }
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)); }
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)); }
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); }
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);
private List <SecurityKey> GetTrustedKeys(AssertionModel assertion) => GetAllTrustedCertificates(assertion) .Select(c => (SecurityKey) new X509SecurityKey(c)) .ToList();
private IEnumerable <X509Certificate2> GetAllTrustedCertificates(AssertionModel model) => model.Certificates .Select(GetCertificateFromString) .Where(c => c != null) .ToList();