public void RoundTripWsMetadata(EnvelopedSignatureTheoryData theoryData) { var context = TestUtilities.WriteHeader($"{this}.RoundTripWsMetadata", theoryData); try { var settings = new XmlWriterSettings { Encoding = new UTF8Encoding(false) }; var buffer = new MemoryStream(); var esw = new EnvelopedSignatureWriter(XmlWriter.Create(buffer, settings), theoryData.SigningCredentials, theoryData.ReferenceId); theoryData.Action.DynamicInvoke(esw); var metadata = Encoding.UTF8.GetString(buffer.ToArray()); var configuration = new WsFederationConfiguration(); var reader = XmlReader.Create(new StringReader(metadata)); configuration = new WsFederationMetadataSerializer().ReadMetadata(reader); configuration.Signature.Verify(theoryData.SigningCredentials.Key, theoryData.SigningCredentials.Key.CryptoProviderFactory); theoryData.ExpectedException.ProcessNoException(context); } catch (Exception ex) { theoryData.ExpectedException.ProcessException(ex, context); } TestUtilities.AssertFailIfErrors(context); }
public MetadataMiddleware(RequestDelegate next, ILogger <MetadataMiddleware> logger, IKeyMaterialService keyService, IOptions <FederationGatewayOptions> options, WsFederationMetadataSerializer serializer) { if (next == null) { throw new ArgumentNullException(nameof(next)); } if (keyService == null) { throw new ArgumentNullException(nameof(keyService)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (serializer == null) { throw new ArgumentNullException(nameof(serializer)); } _next = next; _logger = logger; _keyService = keyService; _options = options.Value; _serializer = serializer; }
public void WriteMetadata(WsFederationMetadataTheoryData theoryData) { TestUtilities.WriteHeader($"{this}.WriteMetadata", theoryData); var context = new CompareContext($"{this}.WriteMetadata, {theoryData.TestId}"); try { var settings = new XmlWriterSettings(); var builder = new StringBuilder(); if (theoryData.UseNullWriter) { theoryData.Serializer.WriteMetadata(null, theoryData.Configuration); theoryData.ExpectedException.ProcessNoException(context); } else { using (var writer = XmlWriter.Create(builder, settings)) { // add signingCredentials so we can created signed metadata. if (theoryData.Configuration != null) { theoryData.Configuration.SigningCredentials = KeyingMaterial.DefaultX509SigningCreds_2048_RsaSha2_Sha2; } // write configuration content into metadata and sign the metadata var serializer = new WsFederationMetadataSerializer(); serializer.WriteMetadata(writer, theoryData.Configuration); writer.Flush(); var metadata = builder.ToString(); // read the created metadata into a new configuration var reader = XmlReader.Create(new StringReader(metadata)); var configuration = theoryData.Serializer.ReadMetadata(reader); // assign signingcredentials and verify the signature of created metadata configuration.SigningCredentials = theoryData.Configuration.SigningCredentials; if (configuration.SigningCredentials != null) { configuration.Signature.Verify(configuration.SigningCredentials.Key, configuration.SigningCredentials.Key.CryptoProviderFactory); } // remove the signature and do the comparison configuration.Signature = null; theoryData.ExpectedException.ProcessNoException(context); IdentityComparer.AreWsFederationConfigurationsEqual(configuration, theoryData.Configuration, context); } } } catch (Exception ex) { theoryData.ExpectedException.ProcessException(ex, context); } TestUtilities.AssertFailIfErrors(context); }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="configuration"></param> /// <returns></returns> public static void WriteMetadata(this WsFederationMetadataSerializer serializer, XmlWriter writer, WsFederationConfiguration configuration) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (string.IsNullOrEmpty(configuration.Issuer)) { throw XmlUtil.LogWriteException(nameof(configuration.Issuer) + " is null or empty"); } if (string.IsNullOrEmpty(configuration.TokenEndpoint)) { throw XmlUtil.LogWriteException(nameof(configuration.TokenEndpoint) + " is null or empty"); } X509SecurityKey securityKey = configuration.SigningKeys.FirstOrDefault() as X509SecurityKey; var entityDescriptorId = "_" + Guid.NewGuid().ToString(); EnvelopedSignatureWriter envelopeWriter = null; if (securityKey != null) { envelopeWriter = new EnvelopedSignatureWriter( writer, configuration.SigningCredentials, "#" + entityDescriptorId); writer = envelopeWriter; } writer.WriteStartDocument(); // <EntityDescriptor> writer.WriteStartElement(Elements.EntityDescriptor, WsFederationConstants.MetadataNamespace); // @entityID writer.WriteAttributeString(Attributes.EntityId, configuration.Issuer); // @ID writer.WriteAttributeString(Attributes.Id, entityDescriptorId); // if (envelopeWriter != null) // envelopeWriter.WriteSignature(); WriteSecurityTokenServiceTypeRoleDescriptor(configuration, writer); // </EntityDescriptor> writer.WriteEndElement(); writer.WriteEndDocument(); }
public async Task Metadata_CanBeDeserializedAsMetadata() { var response = await _client.GetAsync("/wsfederation/metadata"); var content = await response.Content.ReadAsStreamAsync(); using (var reader = XmlReader.Create(content)) { var serializer = new WsFederationMetadataSerializer(); var configuration = serializer.ReadMetadata(reader); Assert.AreEqual("http://localhost/wsfederation", configuration.TokenEndpoint); } }
/// <summary> /// Executes the result operation of the action method asynchronously. This method is called by MVC to process /// the result of an action method. /// </summary> /// <param name="context">The context in which the result is executed. The context information includes /// information about the action that was executed and request information.</param> /// <returns> /// A task that represents the asynchronous execute operation. /// </returns> public Task ExecuteResultAsync(ActionContext context) { var ser = new WsFederationMetadataSerializer(); using var ms = new MemoryStream(); using XmlWriter writer = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8, false); ser.WriteMetadata(writer, _config); writer.Flush(); context.HttpContext.Response.ContentType = "application/xml"; var metaAsString = Encoding.UTF8.GetString(ms.ToArray()); return(context.HttpContext.Response.WriteAsync(metaAsString)); }
public async Task Metadata_should_return_metadata_document_with_key_rotation() { var configuration = new Dictionary <string, string> { ["IdentityServer:Key:Type"] = "KeysRotation", ["Seed"] = "false" }; var sut = TestUtils.CreateTestServer(configurationOverrides: configuration); using var client = sut.CreateClient(); using var response = await client.GetAsync("/wsfederation/metadata"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); using var reader = XmlReader.Create(await response.Content.ReadAsStreamAsync().ConfigureAwait(false)); var serializer = new WsFederationMetadataSerializer(); var metadata = serializer.ReadMetadata(reader); Assert.NotNull(metadata); }
public async Task <string> GetMetadata(HttpContext context) { var configuration = new WsFederationConfiguration { Issuer = _options.IssuerUri, SigningCredentials = await _keys.GetSigningCredentialsAsync(), TokenEndpoint = context.GetIdentityServerOrigin() + "/wsfederation" }; //For whatever reason, the Digest method isn't specified in the builder extensions for identity server. //Not a good solution to force the user to use the overload that takes SigningCredentials //IdentityServer4/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs //Instead, it should be supported in: // The overload that takes a X509Certificate2 // The overload that looks it up in a cert store // The overload that takes an RsaSecurityKey // AddDeveloperSigningCredential //For now, this is a workaround. if (configuration.SigningCredentials.Digest == null) { _logger.LogInformation($"SigningCredentials does not have a digest specified. Using default digest algorithm of {SecurityAlgorithms.Sha256Digest}"); configuration.SigningCredentials = new SigningCredentials(configuration.SigningCredentials.Key, configuration.SigningCredentials.Algorithm ?? SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest); } configuration.KeyInfos.Add(new KeyInfo(configuration.SigningCredentials.Key)); var serializer = new WsFederationMetadataSerializer(); var sb = new StringBuilder(); var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; using (var writer = XmlWriter.Create(sb, settings)) { serializer.WriteMetadata(writer, configuration); } var metadata = sb.ToString(); return(metadata); }
public static IssuerSigningKeys GetSigningKeys(string metadataEndpoint, TimeSpan backchannelTimeout, HttpMessageHandler backchannelHttpHandler) { using (var metadataRequest = new HttpClient(backchannelHttpHandler, false)) { metadataRequest.Timeout = backchannelTimeout; using (HttpResponseMessage metadataResponse = metadataRequest.GetAsync(metadataEndpoint).Result) { metadataResponse.EnsureSuccessStatusCode(); Stream metadataStream = metadataResponse.Content.ReadAsStreamAsync().Result; using (XmlReader metaDataReader = XmlReader.Create(metadataStream, SafeSettings)) { var serializer = new WsFederationMetadataSerializer(); var wsFederationConfiguration = serializer.ReadMetadata(metaDataReader); return(new IssuerSigningKeys { Issuer = wsFederationConfiguration.Issuer, Keys = wsFederationConfiguration.SigningKeys }); } } } }