/// <summary> /// Retrieves a populated <see cref="OpenIdConnectConfiguration"/> given an address and an <see cref="IDocumentRetriever"/>. /// </summary> /// <param name="address">address of the discovery document.</param> /// <param name="retriever">the <see cref="IDocumentRetriever"/> to use to read the discovery document</param> /// <param name="cancel"><see cref="CancellationToken"/>.</param> /// <returns>A populated <see cref="OpenIdConnectConfiguration"/> instance.</returns> public static async Task <OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { throw LogHelper.LogArgumentNullException(nameof(address)); } if (retriever == null) { throw LogHelper.LogArgumentNullException(nameof(retriever)); } string doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); LogHelper.LogVerbose(LogMessages.IDX21811, doc); OpenIdConnectConfiguration openIdConnectConfiguration = JsonConvert.DeserializeObject <OpenIdConnectConfiguration>(doc); if (!string.IsNullOrEmpty(openIdConnectConfiguration.JwksUri)) { LogHelper.LogVerbose(LogMessages.IDX21812, openIdConnectConfiguration.JwksUri); string keys = await retriever.GetDocumentAsync(openIdConnectConfiguration.JwksUri, cancel).ConfigureAwait(false); LogHelper.LogVerbose(LogMessages.IDX21813, openIdConnectConfiguration.JwksUri); openIdConnectConfiguration.JsonWebKeySet = JsonConvert.DeserializeObject <JsonWebKeySet>(keys); foreach (SecurityKey key in openIdConnectConfiguration.JsonWebKeySet.GetSigningKeys()) { openIdConnectConfiguration.SigningKeys.Add(key); } } return(openIdConnectConfiguration); }
/// <summary> /// Retrieves a populated <see cref="OpenIdConnectConfiguration"/> given an address and an <see cref="IDocumentRetriever"/>. /// </summary> /// <param name="address">address of the discovery document.</param> /// <param name="retriever">the <see cref="IDocumentRetriever"/> to use to read the discovery document</param> /// <param name="cancel"><see cref="CancellationToken"/>.</param> /// <returns>A populated <see cref="OpenIdConnectConfiguration"/> instance.</returns> public static async Task <OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException("address"); } if (retriever == null) { throw new ArgumentNullException("retriever"); } string doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); OpenIdConnectConfiguration openIdConnectConfiguration = new OpenIdConnectConfiguration(doc); if (!string.IsNullOrEmpty(openIdConnectConfiguration.JwksUri)) { string keys = await retriever.GetDocumentAsync(openIdConnectConfiguration.JwksUri, cancel).ConfigureAwait(false); openIdConnectConfiguration.JsonWebKeySet = new JsonWebKeySet(keys); foreach (SecurityToken token in openIdConnectConfiguration.JsonWebKeySet.GetSigningTokens()) { openIdConnectConfiguration.SigningTokens.Add(token); } } return(openIdConnectConfiguration); }
private async Task <MetadataBase> GetAsync(FederationPartyConfiguration context, IDocumentRetriever retriever, CancellationToken cancel) { this._metadataSerialiser.Validator.SetFederationPartyId(context.FederationPartyId); if (string.IsNullOrWhiteSpace(context.MetadataAddress)) { throw new ArgumentNullException("address"); } if (retriever == null) { throw new ArgumentNullException("retriever"); } var str = await retriever.GetDocumentAsync(context.MetadataAddress, cancel); var document = str; str = null; using (XmlReader reader = XmlReader.Create(new StringReader(document), this._safeSettings)) { var federationConfiguration = this._metadataSerialiser.Deserialise(reader); if (this.MetadataReceivedCallback != null) { this.MetadataReceivedCallback(federationConfiguration); } return(federationConfiguration); } }
/// <summary> /// Retrieves a populated <see cref="OpenIdConnectConfiguration"/> given an address and an <see cref="IDocumentRetriever"/>. /// </summary> /// <param name="address">address of the jwks uri.</param> /// <param name="retriever">the <see cref="IDocumentRetriever"/> to use to read the jwks</param> /// <param name="cancel"><see cref="CancellationToken"/>.</param> /// <returns>A populated <see cref="OpenIdConnectConfiguration"/> instance.</returns> public static async Task <OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { throw LogHelper.LogArgumentNullException(nameof(address)); } if (retriever == null) { throw LogHelper.LogArgumentNullException(nameof(retriever)); } var doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); LogHelper.LogVerbose("IDX21811: Deserializing the string: '{0}' obtained from metadata endpoint into openIdConnectConfiguration object.", doc); var jwks = new JsonWebKeySet(doc); var openIdConnectConfiguration = new OpenIdConnectConfiguration() { JsonWebKeySet = jwks, JwksUri = address, }; foreach (var securityKey in jwks.GetSigningKeys()) { openIdConnectConfiguration.SigningKeys.Add(securityKey); } return(openIdConnectConfiguration); }
/// <summary>Retrieves a populated configuration given an address and an <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/>.</summary> /// <param name="address">Address of the discovery document.</param> /// <param name="retriever">The <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/> to use to read the discovery document.</param> /// <param name="cancel">A cancellation token that can be used by other objects or threads to receive notice of cancellation. <see cref="T:System.Threading.CancellationToken"/>.</param> /// <returns> /// A <see cref="Task{IssuerMetadata}"/> that, when completed, returns <see cref="IssuerMetadata"/> from the configuration. /// </returns> /// <exception cref="ArgumentNullException">address - Azure AD Issuer metadata address URL is required /// or retriever - No metadata document retriever is provided.</exception> public async Task <IssuerMetadata> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { string doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); IssuerMetadata issuerMetadata = JsonConvert.DeserializeObject <IssuerMetadata>(doc); return(issuerMetadata); }
/// <summary> /// Retrieves a populated <see cref="WsFederationConfiguration"/> given an address and an <see cref="IDocumentRetriever"/>. /// </summary> /// <param name="address">address of the metadata document.</param> /// <param name="retriever">the <see cref="IDocumentRetriever"/> to use to read the metadata document</param> /// <param name="cancel"><see cref="CancellationToken"/>.</param> /// <returns>A populated <see cref="WsFederationConfiguration"/> instance.</returns> public static async Task <WsFederationConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { LogHelper.Throw(string.Format(CultureInfo.InvariantCulture, LogMessages.IDX10000, GetType() + ": address"), typeof(ArgumentNullException), EventLevel.Verbose); } if (retriever == null) { LogHelper.Throw(string.Format(CultureInfo.InvariantCulture, LogMessages.IDX10000, GetType() + ": retriever"), typeof(ArgumentNullException), EventLevel.Verbose); } WsFederationConfiguration configuration = new WsFederationConfiguration(); string document = await retriever.GetDocumentAsync(address, cancel); using (XmlReader metaDataReader = XmlReader.Create(new StringReader(document), SafeSettings)) { var serializer = new MetadataSerializer { CertificateValidationMode = X509CertificateValidationMode.None }; MetadataBase metadataBase = serializer.ReadMetadata(metaDataReader); var entityDescriptor = (EntityDescriptor)metadataBase; if (!string.IsNullOrWhiteSpace(entityDescriptor.EntityId.Id)) { configuration.Issuer = entityDescriptor.EntityId.Id; } SecurityTokenServiceDescriptor stsd = entityDescriptor.RoleDescriptors.OfType <SecurityTokenServiceDescriptor>().First(); if (stsd != null) { configuration.TokenEndpoint = stsd.PassiveRequestorEndpoints.First().Uri.AbsoluteUri; foreach (KeyDescriptor keyDescriptor in stsd.Keys) { if (keyDescriptor.KeyInfo != null && (keyDescriptor.Use == KeyType.Signing || keyDescriptor.Use == KeyType.Unspecified)) { IdentityModelEventSource.Logger.WriteVerbose(LogMessages.IDX10807); foreach (SecurityKeyIdentifierClause clause in keyDescriptor.KeyInfo) { X509RawDataKeyIdentifierClause x509Clause = clause as X509RawDataKeyIdentifierClause; if (x509Clause != null) { var key = new X509SecurityKey(new X509Certificate2(x509Clause.GetX509RawData())); configuration.SigningKeys.Add(key); } } } } } } return(configuration); }
/// <summary> /// Retrieves the configuration document and deserializes it /// </summary> /// <param name="address">Url where the document is to be downloaded from</param> /// <param name="retriever">Engine that retrieves the document. Injected by ASP.NET Core at runtime</param> /// <param name="cancellationToken">Async process cancellation token</param> /// <returns>Deserialized issuer metadata</returns> public async Task <IssuerMetadata> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever)); } return(JsonConvert.DeserializeObject <IssuerMetadata>(await retriever.GetDocumentAsync(address, cancellationToken))); }
/// <summary> /// Retrieves the OAuth2 introspection configuration from the specified address. /// </summary> /// <param name="address">The address of the discovery document.</param> /// <param name="retriever">The object used to retrieve the discovery document.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <returns>An <see cref="OAuthIntrospectionConfiguration"/> instance.</returns> public async Task <OAuthIntrospectionConfiguration> GetConfigurationAsync( [NotNull] string address, [NotNull] IDocumentRetriever retriever, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(address)) { throw new ArgumentException("The address cannot be null or empty.", nameof(address)); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever)); } return(new OAuthIntrospectionConfiguration(await retriever.GetDocumentAsync(address, cancellationToken))); }
private void GetDocument(string address, IDocumentRetriever docRetriever, ExpectedException ee) { try { string doc = docRetriever.GetDocumentAsync(address, CancellationToken.None).Result; ee.ProcessNoException(); } catch (AggregateException ex) { ex.Handle((x) => { ee.ProcessException(x); return(true); }); } }
public Task <string> GetDocumentAsync(string address, CancellationToken cancel) { if (string.Equals("primary", address)) { return(Task.FromResult(_primaryDocument)); } if (string.Equals("secondary", address) && !string.IsNullOrWhiteSpace(_secondaryDocument)) { return(Task.FromResult(_secondaryDocument)); } if (_fallback != null) { return(_fallback.GetDocumentAsync(address, cancel)); } throw new IOException("Document not found: " + address); }
/// <summary>Retrieves a populated configuration given an address and an <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/>.</summary> /// <param name="address">Address of the discovery document.</param> /// <param name="retriever">The <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/> to use to read the discovery document.</param> /// <param name="cancel">A cancellation token that can be used by other objects or threads to receive notice of cancellation. <see cref="T:System.Threading.CancellationToken"/>.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">address - Azure AD Issuer metadata address url is required /// or /// retriever - No metadata document retriever is provided</exception> public async Task <IssuerMetadata> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrEmpty(address)) { throw new ArgumentNullException(nameof(address), $"Azure AD Issuer metadata address url is required"); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever), $"No metadata document retriever is provided"); } var doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); return(JsonSerializer.Deserialize <IssuerMetadata>(doc)); }
public async Task <IDictionary <string, string[]> > GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { var res = await retriever.GetDocumentAsync(address, cancel); var obj = Newtonsoft.Json.JsonConvert.DeserializeObject <JObject>(res); if (obj != null && obj.HasValues && obj["keys"] != null) { var keys = obj.SelectToken("keys").Value <JArray>(); var endorsements = keys.Where(key => key["endorsements"] != null).Select(key => Tuple.Create(key.SelectToken("kid").Value <string>(), key.SelectToken("endorsements").Values <string>())); return(endorsements.Distinct(new EndorsementsComparer()).ToDictionary(item => item.Item1, item => item.Item2.ToArray())); } else { return(new Dictionary <string, string[]>()); } }
private static async Task <WsFederationConfiguration> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { var document = await retriever.GetDocumentAsync(address, cancel); var configuration = new WsFederationConfiguration(); using (var sr = new StringReader(document)) using (var xr = XmlReader.Create(sr, _settings)) { var serializer = new MetadataSerializer { CertificateValidationMode = X509CertificateValidationMode.None }; var entityDescriptor = serializer.ReadMetadata(xr) as EntityDescriptor; if (entityDescriptor != null) { configuration.Issuer = entityDescriptor.EntityId.Id; var idpssod = entityDescriptor.RoleDescriptors.OfType <IdentityProviderSingleSignOnDescriptor>().FirstOrDefault(); if (idpssod != null) { var redirectBinding = idpssod.SingleSignOnServices.FirstOrDefault(ssos => ssos.Binding == ProtocolBindings.HttpRedirect); if (redirectBinding != null) { configuration.TokenEndpoint = redirectBinding.Location.OriginalString; } var keys = idpssod.Keys .Where(key => key.KeyInfo != null && (key.Use == KeyType.Signing || key.Use == KeyType.Unspecified)) .SelectMany(key => key.KeyInfo.OfType <X509RawDataKeyIdentifierClause>()) .Select(clause => new X509SecurityKey(new X509Certificate2(clause.GetX509RawData()))); foreach (var key in keys) { configuration.SigningKeys.Add(key); } } } } return(configuration); }
/// <summary> /// Retrieves a populated configuration given an address and a document retriever. /// </summary> /// <param name="address">Address of the discovery document.</param> /// <param name="retriever">The document retriever to use to read the discovery document.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects /// or threads to receive notice of cancellation.</param> /// <returns>A task that represents the work queued to execute.</returns> /// <remarks>If the activities are successfully sent, the task result contains /// a populated configuration.</remarks> public async Task <IDictionary <string, HashSet <string> > > GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancellationToken) { if (address == null) { throw new ArgumentNullException(nameof(address)); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever)); } var jsonDocument = await retriever.GetDocumentAsync(address, cancellationToken).ConfigureAwait(false); var configurationRoot = JObject.Parse(jsonDocument); var keys = configurationRoot["keys"]?.Value <JArray>(); if (keys == null) { return(new Dictionary <string, HashSet <string> >(0)); } var results = new Dictionary <string, HashSet <string> >(keys.Count); foreach (var key in keys) { var keyId = key[AuthenticationConstants.KeyIdHeader]?.Value <string>(); if (keyId != null && !results.ContainsKey(keyId)) { var endorsementsToken = key["endorsements"]; if (endorsementsToken != null) { results.Add(keyId, new HashSet <string>(endorsementsToken.Values <string>())); } } } return(results); }
/// <summary> /// Retrieves a populated <see cref="WsFederationConfiguration"/> given an address and an <see cref="IDocumentRetriever"/>. /// </summary> /// <param name="address">address of the metadata document.</param> /// <param name="retriever">the <see cref="IDocumentRetriever"/> to use to read the metadata document</param> /// <param name="cancel"><see cref="CancellationToken"/>.</param> /// <returns>A populated <see cref="WsFederationConfiguration"/> instance.</returns> /// <exception cref="ArgumentNullException">if <paramref name="address"/> is null or empty.</exception> /// <exception cref="ArgumentNullException">if <paramref name="retriever"/> is null.</exception> public static async Task <WsFederationConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrEmpty(address)) { throw LogArgumentNullException(nameof(address)); } if (retriever == null) { throw LogArgumentNullException(nameof(retriever)); } string document = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); using (var metaDataReader = XmlReader.Create(new StringReader(document), SafeSettings)) { return((new WsFederationMetadataSerializer()).ReadMetadata(metaDataReader)); } }
/// <summary>Retrieves a populated configuration given an address and an <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/>.</summary> /// <param name="address">Address of the discovery document.</param> /// <param name="retriever">The <see cref="T:Microsoft.IdentityModel.Protocols.IDocumentRetriever"/> to use to read the discovery document.</param> /// <param name="cancel">A cancellation token that can be used by other objects or threads to receive notice of cancellation. <see cref="T:System.Threading.CancellationToken"/>.</param> /// <returns> /// A <see cref="Task{IssuerMetadata}"/> that, when completed, returns <see cref="IssuerMetadata"/> from the configuration. /// </returns> /// <exception cref="ArgumentNullException">address - Azure AD Issuer metadata address URL is required /// or retriever - No metadata document retriever is provided.</exception> public async Task <IssuerMetadata> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrEmpty(address)) { throw new ArgumentNullException(nameof(address), IDWebErrorMessage.IssuerMetadataUrlIsRequired); } if (retriever == null) { throw new ArgumentNullException(nameof(retriever), IDWebErrorMessage.NoMetadataDocumentRetrieverProvided); } var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; string doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); return(JsonSerializer.Deserialize <IssuerMetadata>(doc, options) !); // Note: The analyzer says Deserialize can return null, but the method comment says it just throws exceptions. }
private async Task <MetadataBase> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException("address"); } if (retriever == null) { throw new ArgumentNullException("retriever"); } var str = await retriever.GetDocumentAsync(address, cancel); var document = str; str = null; using (XmlReader reader = XmlReader.Create(new StringReader(document), this._safeSettings)) { var federationConfiguration = this._metadataSerialiser.Deserialise(reader); return(federationConfiguration); } }
public async Task <OpenIdConnectConfiguration> GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { if (string.IsNullOrWhiteSpace(address)) { throw LogHelper.LogArgumentNullException(nameof(address)); } if (retriever == null) { throw LogHelper.LogArgumentNullException(nameof(retriever)); } string jwks = ""; try { jwks = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false); } catch (System.Exception ex) { System.Console.WriteLine("Error: {0}", ex); } // If the keyset comes from Vault, it'll be under the data element in the response blob. // If it's from the auth service, it'll be a normal keyset. var keysetWrapper = JsonConvert.DeserializeObject <JsonWebKeySetWrapper>(jwks); var keyset = keysetWrapper?.Keys ?? JsonConvert.DeserializeObject <JsonWebKeySet>(jwks); var openIdConnectConfiguration = new OpenIdConnectConfiguration { JsonWebKeySet = keyset }; foreach (var signingKey in openIdConnectConfiguration.JsonWebKeySet.GetSigningKeys()) { openIdConnectConfiguration.SigningKeys.Add(signingKey); } return(openIdConnectConfiguration); }
/// <summary> /// Invoked to post configure a TOptions instance. /// </summary> /// <param name="name">The name of the options instance being configured.</param> /// <param name="options">The options instance to configure.</param> /// <exception cref="InvalidOperationException"> /// Service Provider certificate could not be found. /// or /// Multiple Service Provider certificates were found, must only provide one. /// or /// The certificate for this service providerhas no private key. /// or /// The MetadataAddress must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false. /// </exception> public void PostConfigure(string name, Saml2Options options) { options.DataProtectionProvider = options.DataProtectionProvider ?? _dp; if (string.IsNullOrEmpty(options.SignOutScheme)) { options.SignOutScheme = options.SignInScheme; } if (options.StateDataFormat == null) { var dataProtector = options.DataProtectionProvider.CreateProtector( typeof(Saml2Handler).FullName, name, "v1"); options.StateDataFormat = new PropertiesDataFormat(dataProtector); } var request = _httpContextAccessor.HttpContext.Request; if (options.ServiceProvider.AssertionConsumerServices != null) { foreach (var assertionConsumerService in options.ServiceProvider.AssertionConsumerServices) { if (string.IsNullOrEmpty(assertionConsumerService.Location)) { assertionConsumerService.Location = request.Scheme + "://" + request.Host.Value + options.CallbackPath; } else { Uri uriAppUrlResult; bool appProductionURLresult = Uri.TryCreate(assertionConsumerService.Location, UriKind.Absolute, out uriAppUrlResult) && (uriAppUrlResult.Scheme == Uri.UriSchemeHttp || uriAppUrlResult.Scheme == Uri.UriSchemeHttps); if (!appProductionURLresult) { throw new InvalidOperationException("AssertionConsumerService is not a valid URL."); } } } } if (options.ServiceProvider.SingleLogoutServices != null) { foreach (var singleLogoutService in options.ServiceProvider.SingleLogoutServices) { if (string.IsNullOrEmpty(singleLogoutService.Location)) { singleLogoutService.Location = request.Scheme + "://" + request.Host.Value + options.SignOutPath; } else { Uri uriAppUrlResult; bool appProductionURLresult = Uri.TryCreate(singleLogoutService.Location, UriKind.Absolute, out uriAppUrlResult) && (uriAppUrlResult.Scheme == Uri.UriSchemeHttp || uriAppUrlResult.Scheme == Uri.UriSchemeHttps); if (!appProductionURLresult) { throw new InvalidOperationException("SingleLogoutService is not a valid URL."); } } } } if (options.ServiceProvider.X509Certificate2 != null) { options.hasCertificate = true; } if (options.Backchannel == null) { options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler()); options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("ASP.NET SamlCore handler"); options.Backchannel.Timeout = options.BackchannelTimeout; options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB } if (string.IsNullOrEmpty(options.TokenValidationParameters.ValidAudience)) { options.TokenValidationParameters.ValidAudience = options.ServiceProvider.EntityId; } if (options.ConfigurationManager == null) { if (options.Configuration != null) { options.ConfigurationManager = new StaticConfigurationManager <Saml2Configuration>(options.Configuration); } else if (!string.IsNullOrEmpty(options.MetadataAddress)) { Uri uriResult; bool result = Uri.TryCreate(options.MetadataAddress, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); if (result) { if (options.RequireHttpsMetadata && !options.MetadataAddress.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("The MetadataAddress must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false."); } options.ConfigurationManager = new ConfigurationManager <Saml2Configuration>(options.MetadataAddress, new Saml2ConfigurationRetriever(), new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata }); } else { _idoc.GetDocumentAsync(options.MetadataAddress, default(CancellationToken)); options.ConfigurationManager = new ConfigurationManager <Saml2Configuration>(options.MetadataAddress, new Saml2ConfigurationRetriever(), _idoc); } } } if (options.CreateMetadataFile) { //delete the metadata.xml if exists string[] xmlList = Directory.GetFiles(options.DefaultMetadataFolderLocation, "*.xml"); foreach (string f in xmlList) { if (f == options.DefaultMetadataFolderLocation + "\\" + options.DefaultMetadataFileName + ".xml") { File.Delete(f); } } var xmlTemplate = options.ToXmlMetadata(); //create xml document from string XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlTemplate); xmlDoc.PreserveWhitespace = true; xmlDoc.Save(options.DefaultMetadataFolderLocation + "\\" + options.DefaultMetadataFileName + ".xml"); } }
/// <summary> /// Invoked to post configure a TOptions instance. /// </summary> /// <param name="name">The name of the options instance being configured.</param> /// <param name="options">The options instance to configure.</param> /// <exception cref="InvalidOperationException"> /// Service Provider certificate could not be found. /// or /// Multiple Service Provider certificates were found, must only provide one. /// or /// The certificate for this service providerhas no private key. /// or /// The MetadataAddress must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false. /// </exception> public void PostConfigure(string name, Saml2Options options) { options.DataProtectionProvider = options.DataProtectionProvider ?? _dp; if (string.IsNullOrEmpty(options.SignOutScheme)) { options.SignOutScheme = options.SignInScheme; } if (options.StateDataFormat == null) { var dataProtector = options.DataProtectionProvider.CreateProtector( typeof(Saml2Handler).FullName, name, "v1"); options.StateDataFormat = new PropertiesDataFormat(dataProtector); } var request = _httpContextAccessor.HttpContext.Request; if (options.ServiceProvider.AssertionConsumerServices != null) { foreach (var assertionConsumerService in options.ServiceProvider.AssertionConsumerServices) { if (string.IsNullOrEmpty(assertionConsumerService.Location)) { assertionConsumerService.Location = request.Scheme + "://" + request.Host.Value + options.CallbackPath; } else { Uri uriAppUrlResult; bool appProductionURLresult = Uri.TryCreate(assertionConsumerService.Location, UriKind.Absolute, out uriAppUrlResult) && (uriAppUrlResult.Scheme == Uri.UriSchemeHttp || uriAppUrlResult.Scheme == Uri.UriSchemeHttps); if (!appProductionURLresult) { throw new InvalidOperationException("AssertionConsumerService is not a valid URL."); } } } } if (options.ServiceProvider.SingleLogoutServices != null) { foreach (var singleLogoutService in options.ServiceProvider.SingleLogoutServices) { if (string.IsNullOrEmpty(singleLogoutService.Location)) { singleLogoutService.Location = request.Scheme + "://" + request.Host.Value + options.SignOutPath; } else { Uri uriAppUrlResult; bool appProductionURLresult = Uri.TryCreate(singleLogoutService.Location, UriKind.Absolute, out uriAppUrlResult) && (uriAppUrlResult.Scheme == Uri.UriSchemeHttp || uriAppUrlResult.Scheme == Uri.UriSchemeHttps); if (!appProductionURLresult) { throw new InvalidOperationException("SingleLogoutService is not a valid URL."); } } } } if (options.ServiceProvider.X509Certificate2 != null) { options.hasCertificate = true; } if (options.Backchannel == null) { options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler()); options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("ASP.NET SamlCore handler"); options.Backchannel.Timeout = options.BackchannelTimeout; options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB } if (string.IsNullOrEmpty(options.TokenValidationParameters.ValidAudience)) { options.TokenValidationParameters.ValidAudience = options.ServiceProvider.EntityId; } if (options.ConfigurationManager == null) { if (options.Configuration != null) { options.ConfigurationManager = new StaticConfigurationManager <Saml2Configuration>(options.Configuration); } else if (!string.IsNullOrEmpty(options.MetadataAddress)) { Uri uriResult; bool result = Uri.TryCreate(options.MetadataAddress, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); if (result) { if (options.RequireHttpsMetadata && !options.MetadataAddress.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("The MetadataAddress must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false."); } options.ConfigurationManager = new ConfigurationManager <Saml2Configuration>(options.MetadataAddress, new Saml2ConfigurationRetriever(), new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata }); } else { _idoc.GetDocumentAsync(options.MetadataAddress, default(CancellationToken)); options.ConfigurationManager = new ConfigurationManager <Saml2Configuration>(options.MetadataAddress, new Saml2ConfigurationRetriever(), _idoc); } } } if (options.CreateMetadataFile) { //delete the metadata.xml if exists string[] xmlList = Directory.GetFiles(options.DefaultMetadataFolderLocation, "*.xml"); foreach (string f in xmlList) { if (f == options.DefaultMetadataFolderLocation + "\\" + options.DefaultMetadataFileName + ".xml") { File.Delete(f); } } //overwrite or create metadata.xml if set to true IndexedEndpointType[] AssertionConsumerService = options.ServiceProvider.AssertionConsumerServices; EndpointType[] SingleLogoutServices = options.ServiceProvider.SingleLogoutServices; Metadata.KeyDescriptorType[] KeyDescriptor = null; if (options.hasCertificate) { KeyDescriptor = new Metadata.KeyDescriptorType[] { new Metadata.KeyDescriptorType() { useSpecified = true, use = KeyTypes.signing, KeyInfo = new Metadata.KeyInfoType() { ItemsElementName = new [] { Metadata.ItemsChoiceType2.X509Data }, Items = new Metadata.X509DataType[] { new Metadata.X509DataType() { Items = new object[] { options.ServiceProvider.X509Certificate2.GetRawCertData() }, ItemsElementName = new [] { Metadata.ItemsChoiceType.X509Certificate } } } } }, new Metadata.KeyDescriptorType() { useSpecified = true, use = KeyTypes.encryption, KeyInfo = new Metadata.KeyInfoType() { ItemsElementName = new [] { Metadata.ItemsChoiceType2.X509Data }, Items = new Metadata.X509DataType[] { new Metadata.X509DataType() { Items = new object[] { options.ServiceProvider.X509Certificate2.GetRawCertData() }, ItemsElementName = new [] { Metadata.ItemsChoiceType.X509Certificate } } } } } }; } var entityDescriptor = new EntityDescriptorType() { entityID = options.ServiceProvider.EntityId, Items = new object[] { new SPSSODescriptorType() { NameIDFormat = new [] { Saml2Constants.NameIDFormats.Email }, protocolSupportEnumeration = new [] { Saml2Constants.Namespaces.Protocol }, AuthnRequestsSignedSpecified = true, AuthnRequestsSigned = options.hasCertificate, WantAssertionsSignedSpecified = true, WantAssertionsSigned = options.WantAssertionsSigned, KeyDescriptor = KeyDescriptor, SingleLogoutService = SingleLogoutServices, AssertionConsumerService = AssertionConsumerService, AttributeConsumingService = new AttributeConsumingServiceType[] { new AttributeConsumingServiceType { ServiceName = new localizedNameType[] { new localizedNameType() { Value = options.ServiceProvider.ServiceName, lang = options.ServiceProvider.Language } }, ServiceDescription = new localizedNameType[] { new localizedNameType() { Value = options.ServiceProvider.ServiceDescription, lang = options.ServiceProvider.Language } }, index = 0, isDefault = true, isDefaultSpecified = true, RequestedAttribute = new RequestedAttributeType[] //this doesnt work with ADFS { new RequestedAttributeType { isRequired = true, isRequiredSpecified = true, NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", FriendlyName = "Name" }, new RequestedAttributeType { isRequired = true, isRequiredSpecified = true, NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", FriendlyName = "E-Mail-Adresses" }, new RequestedAttributeType { isRequired = true, isRequiredSpecified = true, NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", Name = "nameid:persistent", FriendlyName = "mail" } } } }, Organization = new OrganizationType() { OrganizationDisplayName = new localizedNameType[] { new localizedNameType { lang = options.ServiceProvider.Language, Value = options.ServiceProvider.OrganizationDisplayName }, }, OrganizationName = new localizedNameType[] { new localizedNameType { lang = options.ServiceProvider.Language, Value = options.ServiceProvider.OrganizationName }, }, OrganizationURL = new localizedURIType[] { new localizedURIType { lang = options.ServiceProvider.Language, Value = options.ServiceProvider.OrganizationURL }, }, }, }, }, ContactPerson = new ContactType[] { new ContactType() { Company = options.ServiceProvider.ContactPerson.Company, GivenName = options.ServiceProvider.ContactPerson.GivenName, EmailAddress = options.ServiceProvider.ContactPerson.EmailAddress, contactType = options.ServiceProvider.ContactPerson.contactType, TelephoneNumber = options.ServiceProvider.ContactPerson.TelephoneNumber } } }; //generate the sp metadata xml file string xmlTemplate = string.Empty; XmlSerializer xmlSerializer = new XmlSerializer(typeof(EntityDescriptorType)); using (MemoryStream memStm = new MemoryStream()) { xmlSerializer.Serialize(memStm, entityDescriptor); memStm.Position = 0; xmlTemplate = new StreamReader(memStm).ReadToEnd(); } //create xml document from string XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlTemplate); xmlDoc.PreserveWhitespace = true; xmlDoc.Save(options.DefaultMetadataFolderLocation + "\\" + options.DefaultMetadataFileName + ".xml"); } }
private async Task <OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(address)) { throw LogHelper.LogArgumentNullException(nameof(address)); } if (retriever == null) { throw LogHelper.LogArgumentNullException(nameof(retriever)); } var cacheObject = await _jdtRedisCacheProvider.TryGetStringValue(address, CancellationToken.None); var str1 = cacheObject.IsValid ? cacheObject.Response : string.Empty; if (string.IsNullOrEmpty(str1)) { str1 = await retriever.GetDocumentAsync(address, cancellationToken).ConfigureAwait(false); await _jdtRedisCacheProvider.SetString(address, str1, cancellationToken); } var contractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }; var settings = new JsonSerializerSettings { ContractResolver = contractResolver }; var openIdConnectConfiguration = JsonConvert.DeserializeObject <OpenIdConnectConfiguration>(str1, settings); if (openIdConnectConfiguration == null) { throw new InvalidOperationException("Unable to deserialize the OpenIdConnectConfiguration"); } if (string.IsNullOrEmpty(openIdConnectConfiguration.JwksUri)) { return(openIdConnectConfiguration); } _logger.Verbose("IDX21812: Retrieving json web keys from: '{JkwsUri}'", (object)openIdConnectConfiguration.JwksUri); var jsonCacheObject = await _jdtRedisCacheProvider.TryGetStringValue( openIdConnectConfiguration.JwksUri, cancellationToken); var str2 = jsonCacheObject.IsValid ? jsonCacheObject.Response : string.Empty; if (string.IsNullOrEmpty(str2)) { str2 = await retriever.GetDocumentAsync(openIdConnectConfiguration.JwksUri, cancellationToken) .ConfigureAwait(false); await _jdtRedisCacheProvider.SetString( openIdConnectConfiguration.JwksUri, str2, cancellationToken); } _logger.Verbose("IDX21813: Deserializing json web keys: '{JwksUri}'", (object)openIdConnectConfiguration.JwksUri); openIdConnectConfiguration.JsonWebKeySet = JsonConvert.DeserializeObject <JsonWebKeySet>(str2); foreach (var signingKey in openIdConnectConfiguration.JsonWebKeySet .GetSigningKeys()) { openIdConnectConfiguration.SigningKeys.Add(signingKey); } return(openIdConnectConfiguration); }