Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Switch to services.Initialize<TOptions> #1206

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,39 +59,6 @@ protected override Task InitializeHandlerAsync()
/// <returns>A new instance of the events instance.</returns>
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new CookieAuthenticationEvents());

protected override void InitializeOptions()
{
base.InitializeOptions();

if (String.IsNullOrEmpty(Options.CookieName))
{
Options.CookieName = CookieAuthenticationDefaults.CookiePrefix + Scheme.Name;
}
if (Options.TicketDataFormat == null)
{
var provider = Options.DataProtectionProvider ?? Context.RequestServices.GetRequiredService<IDataProtectionProvider>();
// Note: the purpose for the data protector must remain fixed for interop to work.
var dataProtector = provider.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", Scheme.Name, "v2");
Options.TicketDataFormat = new TicketDataFormat(dataProtector);
}
if (Options.CookieManager == null)
{
Options.CookieManager = new ChunkingCookieManager();
}
if (!Options.LoginPath.HasValue)
{
Options.LoginPath = CookieAuthenticationDefaults.LoginPath;
}
if (!Options.LogoutPath.HasValue)
{
Options.LogoutPath = CookieAuthenticationDefaults.LogoutPath;
}
if (!Options.AccessDeniedPath.HasValue)
{
Options.AccessDeniedPath = CookieAuthenticationDefaults.AccessDeniedPath;
}
}

private Task<AuthenticateResult> EnsureCookieTicket()
{
// We only need to read the ticket once
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;

namespace Microsoft.AspNetCore.Authentication.Cookies
{
/// <summary>
/// Used to setup defaults for all <see cref="CookieAuthenticationOptions"/>.
/// </summary>
public class CookieAuthenticationInitializer : IInitializeOptions<CookieAuthenticationOptions>
{
private readonly IDataProtectionProvider _dp;

public CookieAuthenticationInitializer(IDataProtectionProvider dataProtection)
{
_dp = dataProtection;
}

/// <summary>
/// Invoked to initialize a TOptions instance.
/// </summary>
/// <param name="name">The name of the options instance being initialized.</param>
/// <param name="options">The options instance to initialize.</param>
public void Initialize(string name, CookieAuthenticationOptions options)
{
options.DataProtectionProvider = options.DataProtectionProvider ?? _dp;

if (String.IsNullOrEmpty(options.CookieName))
{
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + name;
}
if (options.TicketDataFormat == null)
{
// Note: the purpose for the data protector must remain fixed for interop to work.
var dataProtector = options.DataProtectionProvider.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", name, "v2");
options.TicketDataFormat = new TicketDataFormat(dataProtector);
}
if (options.CookieManager == null)
{
options.CookieManager = new ChunkingCookieManager();
}
if (!options.LoginPath.HasValue)
{
options.LoginPath = CookieAuthenticationDefaults.LoginPath;
}
if (!options.LogoutPath.HasValue)
{
options.LogoutPath = CookieAuthenticationDefaults.LogoutPath;
}
if (!options.AccessDeniedPath.HasValue)
{
options.AccessDeniedPath = CookieAuthenticationDefaults.AccessDeniedPath;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace Microsoft.AspNetCore.Authentication.Cookies
{
Expand Down Expand Up @@ -71,7 +72,7 @@ public string CookieName
public CookieSecurePolicy CookieSecure { get; set; }

/// <summary>
/// If set this will be used by the CookieAuthenticationMiddleware for data protection.
/// If set this will be used by the CookieAuthenticationHandler for data protection.
/// </summary>
public IDataProtectionProvider DataProtectionProvider { get; set; }

Expand Down Expand Up @@ -129,9 +130,7 @@ public string CookieName

/// <summary>
/// The TicketDataFormat is used to protect and unprotect the identity and other properties which are stored in the
/// cookie value. If it is not provided a default data handler is created using the data protection service contained
/// in the IApplicationBuilder.Properties. The default data protection service is based on machine key when running on ASP.NET,
/// and on DPAPI when running in a different process.
/// cookie value. If not provided one will be created using <see cref="DataProtectionProvider"/>.
/// </summary>
public ISecureDataFormat<AuthenticationTicket> TicketDataFormat { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

using System;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.AspNetCore.Authentication;

namespace Microsoft.Extensions.DependencyInjection
{
Expand All @@ -15,7 +19,10 @@ public static class CookieExtensions
public static IServiceCollection AddCookieAuthentication(this IServiceCollection services, Action<CookieAuthenticationOptions> configureOptions) =>
services.AddCookieAuthentication(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions);

public static IServiceCollection AddCookieAuthentication(this IServiceCollection services, string authenticationScheme, Action<CookieAuthenticationOptions> configureOptions) =>
services.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(authenticationScheme, configureOptions);
public static IServiceCollection AddCookieAuthentication(this IServiceCollection services, string authenticationScheme, Action<CookieAuthenticationOptions> configureOptions)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<CookieAuthenticationOptions>, CookieAuthenticationInitializer>());
return services.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(authenticationScheme, configureOptions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static IServiceCollection AddFacebookAuthentication(this IServiceCollecti

public static IServiceCollection AddFacebookAuthentication(this IServiceCollection services, string authenticationScheme, Action<FacebookOptions> configureOptions)
{
return services.AddScheme<FacebookOptions, FacebookHandler>(authenticationScheme, authenticationScheme, configureOptions);
return services.AddOAuthAuthentication<FacebookOptions, FacebookHandler>(authenticationScheme, configureOptions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand All @@ -19,8 +18,8 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
{
internal class FacebookHandler : OAuthHandler<FacebookOptions>
{
public FacebookHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<FacebookOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, logger, encoder, dataProtection, clock)
public FacebookHandler(IOptionsSnapshot<FacebookOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }

protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static IServiceCollection AddGoogleAuthentication(this IServiceCollection

public static IServiceCollection AddGoogleAuthentication(this IServiceCollection services, string authenticationScheme, Action<GoogleOptions> configureOptions)
{
return services.AddScheme<GoogleOptions, GoogleHandler>(authenticationScheme, authenticationScheme, configureOptions);
return services.AddOAuthAuthentication<GoogleOptions, GoogleHandler>(authenticationScheme, configureOptions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand All @@ -19,8 +18,8 @@ namespace Microsoft.AspNetCore.Authentication.Google
{
internal class GoogleHandler : OAuthHandler<GoogleOptions>
{
public GoogleHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<GoogleOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, logger, encoder, dataProtection, clock)
public GoogleHandler(IOptionsSnapshot<GoogleOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }

protected override async Task<AuthenticationTicket> CreateTicketAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace Microsoft.Extensions.DependencyInjection
Expand All @@ -26,6 +27,7 @@ public static IServiceCollection AddJwtBearerAuthentication(this IServiceCollect

public static IServiceCollection AddJwtBearerAuthentication(this IServiceCollection services, string authenticationScheme, Action<JwtBearerOptions> configureOptions)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<JwtBearerOptions>, JwtBearerInitializer>());
return services.AddScheme<JwtBearerOptions, JwtBearerHandler>(authenticationScheme, configureOptions);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,49 +40,6 @@ public JwtBearerHandler(IOptionsSnapshot<JwtBearerOptions> options, ILoggerFacto

protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new JwtBearerEvents());

protected override void InitializeOptions()
{
base.InitializeOptions();

if (string.IsNullOrEmpty(Options.TokenValidationParameters.ValidAudience) && !string.IsNullOrEmpty(Options.Audience))
{
Options.TokenValidationParameters.ValidAudience = Options.Audience;
}

if (Options.ConfigurationManager == null)
{
if (Options.Configuration != null)
{
Options.ConfigurationManager = new StaticConfigurationManager<OpenIdConnectConfiguration>(Options.Configuration);
}
else if (!(string.IsNullOrEmpty(Options.MetadataAddress) && string.IsNullOrEmpty(Options.Authority)))
{
if (string.IsNullOrEmpty(Options.MetadataAddress) && !string.IsNullOrEmpty(Options.Authority))
{
Options.MetadataAddress = Options.Authority;
if (!Options.MetadataAddress.EndsWith("/", StringComparison.Ordinal))
{
Options.MetadataAddress += "/";
}

Options.MetadataAddress += ".well-known/openid-configuration";
}

if (Options.RequireHttpsMetadata && !Options.MetadataAddress.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The MetadataAddress or Authority must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false.");
}

var httpClient = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler());
httpClient.Timeout = Options.BackchannelTimeout;
httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB

Options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(Options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(httpClient) { RequireHttps = Options.RequireHttpsMetadata });
}
}
}

/// <summary>
/// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Net.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
/// <summary>
/// Used to setup defaults for all <see cref="JwtBearerOptions"/>.
/// </summary>
public class JwtBearerInitializer : IInitializeOptions<JwtBearerOptions>
{
/// <summary>
/// Invoked to initialize a JwtBearerOptions instance.
/// </summary>
/// <param name="name">The name of the options instance being initialized.</param>
/// <param name="options">The options instance to initialize.</param>
public void Initialize(string name, JwtBearerOptions options)
{
if (string.IsNullOrEmpty(options.TokenValidationParameters.ValidAudience) && !string.IsNullOrEmpty(options.Audience))
{
options.TokenValidationParameters.ValidAudience = options.Audience;
}

if (options.ConfigurationManager == null)
{
if (options.Configuration != null)
{
options.ConfigurationManager = new StaticConfigurationManager<OpenIdConnectConfiguration>(options.Configuration);
}
else if (!(string.IsNullOrEmpty(options.MetadataAddress) && string.IsNullOrEmpty(options.Authority)))
{
if (string.IsNullOrEmpty(options.MetadataAddress) && !string.IsNullOrEmpty(options.Authority))
{
options.MetadataAddress = options.Authority;
if (!options.MetadataAddress.EndsWith("/", StringComparison.Ordinal))
{
options.MetadataAddress += "/";
}

options.MetadataAddress += ".well-known/openid-configuration";
}

if (options.RequireHttpsMetadata && !options.MetadataAddress.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The MetadataAddress or Authority must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false.");
}

var httpClient = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
httpClient.Timeout = options.BackchannelTimeout;
httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB

options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(httpClient) { RequireHttps = options.RequireHttpsMetadata });
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static IServiceCollection AddMicrosoftAccountAuthentication(this IService

public static IServiceCollection AddMicrosoftAccountAuthentication(this IServiceCollection services, string authenticationScheme, Action<MicrosoftAccountOptions> configureOptions)
{
return services.AddScheme<MicrosoftAccountOptions, MicrosoftAccountHandler>(authenticationScheme, authenticationScheme, configureOptions);
return services.AddOAuthAuthentication<MicrosoftAccountOptions, MicrosoftAccountHandler>(authenticationScheme, configureOptions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
Expand All @@ -16,8 +15,8 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
internal class MicrosoftAccountHandler : OAuthHandler<MicrosoftAccountOptions>
{
public MicrosoftAccountHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<MicrosoftAccountOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, logger, encoder, dataProtection, clock)
public MicrosoftAccountHandler(IOptionsSnapshot<MicrosoftAccountOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }

protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public void RunClaimActions(JObject userData)

foreach (var action in Options.ClaimActions)
{
action.Run(userData, Identity, Options.ClaimsIssuer);
action.Run(userData, Identity, Options.ClaimsIssuer ?? Scheme.Name);
}
}
}
Expand Down
Loading