Switch to Options Initializer

This commit is contained in:
Hao Kung 2017-05-17 14:05:27 -07:00
parent bdd4d21996
commit 1f5a27e20a
35 changed files with 434 additions and 325 deletions

View File

@ -75,7 +75,6 @@ namespace SocialSample
// https://console.developers.google.com/project
services.AddOAuthAuthentication("Google-AccessToken", o =>
{
o.DisplayName = "Google-AccessToken";
o.ClientId = Configuration["google:clientid"];
o.ClientSecret = Configuration["google:clientsecret"];
o.CallbackPath = new PathString("/signin-google-token");
@ -137,7 +136,6 @@ namespace SocialSample
// https://apps.dev.microsoft.com/
services.AddOAuthAuthentication("Microsoft-AccessToken", o =>
{
o.DisplayName = "MicrosoftAccount-AccessToken";
o.ClientId = Configuration["microsoftaccount:clientid"];
o.ClientSecret = Configuration["microsoftaccount:clientsecret"];
o.CallbackPath = new PathString("/signin-microsoft-token");
@ -160,7 +158,6 @@ namespace SocialSample
// https://github.com/settings/applications/
services.AddOAuthAuthentication("GitHub-AccessToken", o =>
{
o.DisplayName = "Github-AccessToken";
o.ClientId = Configuration["github-token:clientid"];
o.ClientSecret = Configuration["github-token:clientsecret"];
o.CallbackPath = new PathString("/signin-github-token");
@ -178,7 +175,6 @@ namespace SocialSample
// https://github.com/settings/applications/
services.AddOAuthAuthentication("GitHub", o =>
{
o.DisplayName = "Github";
o.ClientId = Configuration["github:clientid"];
o.ClientSecret = Configuration["github:clientsecret"];
o.CallbackPath = new PathString("/signin-github");

View File

@ -59,39 +59,6 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <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

View File

@ -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;
}
}
}
}

View File

@ -4,6 +4,7 @@
using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Cookies
{
@ -71,7 +72,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
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; }
@ -129,9 +130,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <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; }

View File

@ -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
{
@ -15,7 +19,10 @@ namespace Microsoft.Extensions.DependencyInjection
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);
}
}
}

View File

@ -26,7 +26,7 @@ namespace Microsoft.Extensions.DependencyInjection
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);
}
}
}

View File

@ -9,7 +9,6 @@ using System.Text;
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;
@ -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)

View File

@ -26,7 +26,7 @@ namespace Microsoft.Extensions.DependencyInjection
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);
}
}
}

View File

@ -9,7 +9,6 @@ using System.Security.Claims;
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;
@ -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(

View File

@ -3,6 +3,7 @@
using System;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
@ -26,6 +27,7 @@ namespace Microsoft.Extensions.DependencyInjection
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);
}
}

View File

@ -40,49 +40,6 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
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>

View File

@ -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 });
}
}
}
}
}

View File

@ -26,7 +26,7 @@ namespace Microsoft.Extensions.DependencyInjection
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);
}
}
}

View File

@ -7,7 +7,6 @@ using System.Security.Claims;
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;
@ -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)

View File

@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
foreach (var action in Options.ClaimActions)
{
action.Run(userData, Identity, Options.ClaimsIssuer);
action.Run(userData, Identity, Options.ClaimsIssuer ?? Scheme.Name);
}
}
}

View File

@ -3,13 +3,24 @@
using System;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder
namespace Microsoft.Extensions.DependencyInjection
{
public static class OAuthExtensions
{
public static IServiceCollection AddOAuthAuthentication(this IServiceCollection services, string authenticationScheme, Action<OAuthOptions> configureOptions) =>
services.AddScheme<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, authenticationScheme, configureOptions);
public static IServiceCollection AddOAuthAuthentication(this IServiceCollection services, string authenticationScheme, Action<OAuthOptions> configureOptions)
{
return services.AddScheme<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, authenticationScheme, configureOptions);
}
public static IServiceCollection AddOAuthAuthentication<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, Action<TOptions> configureOptions)
where TOptions : OAuthOptions, new()
where THandler : OAuthHandler<TOptions>
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<TOptions>, OAuthInitializer<TOptions, THandler>>());
return services.AddRemoteScheme<TOptions, THandler>(authenticationScheme, authenticationScheme, configureOptions);
}
}
}

View File

@ -10,7 +10,6 @@ using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -33,30 +32,10 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
set { base.Events = value; }
}
public OAuthHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, dataProtection, logger, encoder, clock)
public OAuthHandler(IOptionsSnapshot<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
protected override void InitializeOptions()
{
base.InitializeOptions();
if (Options.Backchannel == null)
{
Options.Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler());
Options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OAuth handler");
Options.Backchannel.Timeout = Options.BackchannelTimeout;
Options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
if (Options.StateDataFormat == null)
{
var dataProtector = DataProtection.CreateProtector(
GetType().FullName, Scheme.Name, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
}
/// <summary>
/// Creates a new instance of the events instance.
/// </summary>
@ -119,7 +98,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
return AuthenticateResult.Fail("Failed to retrieve access token.");
}
var identity = new ClaimsIdentity(Options.ClaimsIssuer);
var identity = new ClaimsIdentity(ClaimsIssuer);
if (Options.SaveTokens)
{

View File

@ -0,0 +1,45 @@
// 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.Net.Http;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Used to setup defaults for the OAuthOptions.
/// </summary>
public class OAuthInitializer<TOptions, THandler> : IInitializeOptions<TOptions>
where TOptions : OAuthOptions, new()
where THandler : OAuthHandler<TOptions>
{
private readonly IDataProtectionProvider _dp;
public OAuthInitializer(IDataProtectionProvider dataProtection)
{
_dp = dataProtection;
}
public void Initialize(string name, TOptions options)
{
options.DataProtectionProvider = options.DataProtectionProvider ?? _dp;
if (options.Backchannel == null)
{
options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OAuth handler");
options.Backchannel.Timeout = options.BackchannelTimeout;
options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
if (options.StateDataFormat == null)
{
var dataProtector = options.DataProtectionProvider.CreateProtector(
typeof(THandler).FullName, name, "v1");
options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
@ -26,7 +27,8 @@ namespace Microsoft.Extensions.DependencyInjection
public static IServiceCollection AddOpenIdConnectAuthentication(this IServiceCollection services, string authenticationScheme, Action<OpenIdConnectOptions> configureOptions)
{
return services.AddScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, authenticationScheme, configureOptions);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<OpenIdConnectOptions>, OpenIdConnectInitializer>());
return services.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, authenticationScheme, configureOptions);
}
}
}

View File

@ -13,12 +13,10 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Net.Http.Headers;
@ -57,8 +55,8 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
protected HtmlEncoder HtmlEncoder { get; }
public OpenIdConnectHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<OpenIdConnectOptions> options, ILoggerFactory logger, HtmlEncoder htmlEncoder, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, dataProtection, logger, encoder, clock)
public OpenIdConnectHandler(IOptionsSnapshot<OpenIdConnectOptions> options, ILoggerFactory logger, HtmlEncoder htmlEncoder, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
HtmlEncoder = htmlEncoder;
}
@ -75,76 +73,6 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new OpenIdConnectEvents());
protected override void InitializeOptions()
{
base.InitializeOptions();
if (string.IsNullOrEmpty(Options.SignOutScheme))
{
Options.SignOutScheme = SignInScheme;
}
if (Options.StateDataFormat == null)
{
var dataProtector = DataProtection.CreateProtector(
GetType().FullName, Scheme.Name, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (Options.StringDataFormat == null)
{
var dataProtector = DataProtection.CreateProtector(
GetType().FullName,
typeof(string).FullName,
Scheme.Name,
"v1");
Options.StringDataFormat = new SecureDataFormat<string>(new StringSerializer(), dataProtector);
}
if (string.IsNullOrEmpty(Options.TokenValidationParameters.ValidAudience) && !string.IsNullOrEmpty(Options.ClientId))
{
Options.TokenValidationParameters.ValidAudience = Options.ClientId;
}
if (Options.Backchannel == null)
{
Options.Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler());
Options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OpenIdConnect handler");
Options.Backchannel.Timeout = Options.BackchannelTimeout;
Options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
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.");
}
Options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(Options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(Backchannel) { RequireHttps = Options.RequireHttpsMetadata });
}
}
}
public override Task<bool> HandleRequestAsync()
{
if (Options.RemoteSignOutPath.HasValue && Options.RemoteSignOutPath == Request.Path)
@ -749,7 +677,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
var identity = (ClaimsIdentity)ticket.Principal.Identity;
foreach (var action in Options.ClaimActions)
{
action.Run(null, identity, Options.ClaimsIssuer);
action.Run(null, identity, ClaimsIssuer);
}
}
@ -902,7 +830,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
foreach (var action in Options.ClaimActions)
{
action.Run(user, identity, Options.ClaimsIssuer);
action.Run(user, identity, ClaimsIssuer);
}
return AuthenticateResult.Success(ticket);
@ -1301,18 +1229,5 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
description,
errorUri));
}
private class StringSerializer : IDataSerializer<string>
{
public string Deserialize(byte[] data)
{
return Encoding.UTF8.GetString(data);
}
public byte[] Serialize(string model)
{
return Encoding.UTF8.GetBytes(model);
}
}
}
}

View File

@ -0,0 +1,114 @@
// 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 System.Text;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
/// <summary>
/// Used to setup defaults for all <see cref="OpenIdConnectOptions"/>.
/// </summary>
public class OpenIdConnectInitializer : IInitializeOptions<OpenIdConnectOptions>
{
private readonly IDataProtectionProvider _dp;
public OpenIdConnectInitializer(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, OpenIdConnectOptions 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(OpenIdConnectHandler).FullName, name, "v1");
options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (options.StringDataFormat == null)
{
var dataProtector = options.DataProtectionProvider.CreateProtector(
typeof(OpenIdConnectHandler).FullName,
typeof(string).FullName,
name,
"v1");
options.StringDataFormat = new SecureDataFormat<string>(new StringSerializer(), dataProtector);
}
if (string.IsNullOrEmpty(options.TokenValidationParameters.ValidAudience) && !string.IsNullOrEmpty(options.ClientId))
{
options.TokenValidationParameters.ValidAudience = options.ClientId;
}
if (options.Backchannel == null)
{
options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OpenIdConnect handler");
options.Backchannel.Timeout = options.BackchannelTimeout;
options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
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.");
}
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata });
}
}
}
private class StringSerializer : IDataSerializer<string>
{
public string Deserialize(byte[] data)
{
return Encoding.UTF8.GetString(data);
}
public byte[] Serialize(string model)
{
return Encoding.UTF8.GetBytes(model);
}
}
}
}

View File

@ -39,7 +39,6 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// </remarks>
public OpenIdConnectOptions()
{
DisplayName = OpenIdConnectDefaults.Caption;
CallbackPath = new PathString("/signin-oidc");
SignedOutCallbackPath = new PathString("/signout-callback-oidc");
RemoteSignOutPath = new PathString("/signout-oidc");

View File

@ -3,6 +3,7 @@
using System;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
@ -26,7 +27,8 @@ namespace Microsoft.Extensions.DependencyInjection
public static IServiceCollection AddTwitterAuthentication(this IServiceCollection services, string authenticationScheme, Action<TwitterOptions> configureOptions)
{
return services.AddScheme<TwitterOptions, TwitterHandler>(authenticationScheme, authenticationScheme, configureOptions);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<TwitterOptions>, TwitterInitializer>());
return services.AddRemoteScheme<TwitterOptions, TwitterHandler>(authenticationScheme, authenticationScheme, configureOptions);
}
}
}

View File

@ -40,36 +40,12 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
set { base.Events = value; }
}
public TwitterHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<TwitterOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
: base(sharedOptions, options, dataProtection, logger, encoder, clock)
public TwitterHandler(IOptionsSnapshot<TwitterOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new TwitterEvents());
protected override void InitializeOptions()
{
base.InitializeOptions();
if (Options.StateDataFormat == null)
{
var dataProtector = DataProtection.CreateProtector(
GetType().FullName, Scheme.Name, "v1");
Options.StateDataFormat = new SecureDataFormat<RequestToken>(
new RequestTokenSerializer(),
dataProtector);
}
if (Options.Backchannel == null)
{
Options.Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler());
Options.Backchannel.Timeout = Options.BackchannelTimeout;
Options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
Options.Backchannel.DefaultRequestHeaders.Accept.ParseAdd("*/*");
Options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core Twitter handler");
Options.Backchannel.DefaultRequestHeaders.ExpectContinue = false;
}
}
protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync()
{
AuthenticationProperties properties = null;
@ -116,12 +92,12 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim(ClaimTypes.Name, accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim("urn:twitter:userid", accessToken.UserId, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim("urn:twitter:screenname", accessToken.ScreenName, ClaimValueTypes.String, Options.ClaimsIssuer)
new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, ClaimValueTypes.String, ClaimsIssuer),
new Claim(ClaimTypes.Name, accessToken.ScreenName, ClaimValueTypes.String, ClaimsIssuer),
new Claim("urn:twitter:userid", accessToken.UserId, ClaimValueTypes.String, ClaimsIssuer),
new Claim("urn:twitter:screenname", accessToken.ScreenName, ClaimValueTypes.String, ClaimsIssuer)
},
Options.ClaimsIssuer);
ClaimsIssuer);
JObject user = null;
if (Options.RetrieveUserDetails)
@ -145,7 +121,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
{
foreach (var action in Options.ClaimActions)
{
action.Run(user, identity, Options.ClaimsIssuer);
action.Run(user, identity, ClaimsIssuer);
}
var context = new TwitterCreatingTicketContext(Context, Scheme, Options, properties, token.UserId, token.ScreenName, token.Token, token.TokenSecret, user)

View File

@ -0,0 +1,51 @@
// 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.Net.Http;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Twitter
{
/// <summary>
/// Used to setup defaults for all <see cref="TwitterOptions"/>.
/// </summary>
public class TwitterInitializer : IInitializeOptions<TwitterOptions>
{
private readonly IDataProtectionProvider _dp;
public TwitterInitializer(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, TwitterOptions options)
{
options.DataProtectionProvider = options.DataProtectionProvider ?? _dp;
if (options.StateDataFormat == null)
{
var dataProtector = options.DataProtectionProvider.CreateProtector(
typeof(TwitterHandler).FullName, name, "v1");
options.StateDataFormat = new SecureDataFormat<RequestToken>(
new RequestTokenSerializer(),
dataProtector);
}
if (options.Backchannel == null)
{
options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler());
options.Backchannel.Timeout = options.BackchannelTimeout;
options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
options.Backchannel.DefaultRequestHeaders.Accept.ParseAdd("*/*");
options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core Twitter handler");
options.Backchannel.DefaultRequestHeaders.ExpectContinue = false;
}
}
}
}

View File

@ -48,6 +48,8 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary>
protected virtual object Events { get; set; }
protected virtual string ClaimsIssuer => Options.ClaimsIssuer ?? Scheme.Name;
protected string CurrentUri
{
get
@ -85,18 +87,6 @@ namespace Microsoft.AspNetCore.Authentication
Context = context;
Options = OptionsSnapshot.Get(Scheme.Name) ?? new TOptions();
if (!Options.Initialized)
{
lock (Options.InitializeLock)
{
if (!Options.Initialized)
{
InitializeOptions();
Options.Initialized = true;
}
}
}
Options.Validate();
await InitializeEventsAsync();
@ -122,16 +112,6 @@ namespace Microsoft.AspNetCore.Authentication
/// <returns>A new instance of the events instance.</returns>
protected virtual Task<object> CreateEventsAsync() => Task.FromResult(new object());
/// <summary>
/// Initializes the options, will be called only once by <see cref="InitializeAsync(AuthenticationScheme, HttpContext)"/>.
/// </summary>
protected virtual void InitializeOptions()
{
// REVIEW: is there a better place for this default?
Options.DisplayName = Options.DisplayName ?? Scheme.Name;
Options.ClaimsIssuer = Options.ClaimsIssuer ?? Scheme.Name;
}
/// <summary>
/// Called after options/events have been initialized for the handler to finish initializing itself.
/// </summary>

View File

@ -2,9 +2,18 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication
{
public class InitializeAuthenticationSchemeOptions<TOptions> : InitializeOptions<TOptions>
where TOptions : AuthenticationSchemeOptions
{
public InitializeAuthenticationSchemeOptions(string name)
: base(name, options => options.ClaimsIssuer = options.ClaimsIssuer ?? name)
{ }
}
/// <summary>
/// Contains the options used by the <see cref="AuthenticationHandler{T}"/>.
/// </summary>
@ -17,11 +26,6 @@ namespace Microsoft.AspNetCore.Authentication
{
}
/// <summary>
/// Gets or sets the display name for the authentication provider.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Gets or sets the issuer that should be used for any claims that are created
/// </summary>
@ -36,15 +40,5 @@ namespace Microsoft.AspNetCore.Authentication
/// If set, will be used as the service type to get the Events instance instead of the property.
/// </summary>
public Type EventsType { get; set; }
/// <summary>
/// Used to ensure that the options are only initialized once.
/// </summary>
public bool Initialized { get; set; }
/// <summary>
/// Used to prevent concurrent access during intialization.
/// </summary>
public object InitializeLock { get; } = new object();
}
}

View File

@ -74,5 +74,30 @@ namespace Microsoft.Extensions.DependencyInjection
where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions>
=> services.AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureScheme: null, configureOptions: configureOptions);
public static IServiceCollection AddRemoteScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, string displayName, Action<TOptions> configureOptions)
where TOptions : RemoteAuthenticationOptions, new()
where THandler : RemoteAuthenticationHandler<TOptions>
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IInitializeOptions<TOptions>, EnsureSignInScheme<TOptions>>());
return services.AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureScheme: null, configureOptions: configureOptions);
}
// Used to ensure that there's always a default data protection provider
private class EnsureSignInScheme<TOptions> : IInitializeOptions<TOptions> where TOptions : RemoteAuthenticationOptions
{
private readonly AuthenticationOptions _authOptions;
public EnsureSignInScheme(IOptions<AuthenticationOptions> authOptions)
{
_authOptions = authOptions.Value;
}
public void Initialize(string name, TOptions options)
{
options.SignInScheme = options.SignInScheme ?? _authOptions.DefaultSignInScheme;
}
}
}
}

View File

@ -5,9 +5,7 @@ using System;
using System.Security.Cryptography;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -25,10 +23,6 @@ namespace Microsoft.AspNetCore.Authentication
protected string SignInScheme => Options.SignInScheme;
protected IDataProtectionProvider DataProtection { get; set; }
private readonly AuthenticationOptions _authOptions;
/// <summary>
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
/// If it is not provided a default instance is supplied which does nothing when the methods are called.
@ -39,17 +33,9 @@ namespace Microsoft.AspNetCore.Authentication
set { base.Events = value; }
}
protected RemoteAuthenticationHandler(IOptions<AuthenticationOptions> sharedOptions, IOptionsSnapshot<TOptions> options, IDataProtectionProvider dataProtection, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
protected RemoteAuthenticationHandler(IOptionsSnapshot<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
_authOptions = sharedOptions.Value;
DataProtection = dataProtection;
}
protected override Task InitializeHandlerAsync()
{
DataProtection = Options.DataProtectionProvider ?? DataProtection;
return TaskCache.CompletedTask;
}
protected override Task<object> CreateEventsAsync()
@ -57,16 +43,6 @@ namespace Microsoft.AspNetCore.Authentication
return Task.FromResult<object>(new RemoteAuthenticationEvents());
}
protected override void InitializeOptions()
{
base.InitializeOptions();
if (Options.SignInScheme == null)
{
Options.SignInScheme = _authOptions.DefaultSignInScheme;
}
}
public virtual Task<bool> ShouldHandleRequestAsync()
{
return Task.FromResult(Options.CallbackPath == Request.Path);

View File

@ -50,7 +50,6 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
{"Facebook:BackchannelTimeout", "0.0:0:30"},
//{"Facebook:CallbackPath", "/callbackpath"}, // PathString doesn't convert
{"Facebook:ClaimsIssuer", "<issuer>"},
{"Facebook:DisplayName", "<display>"},
{"Facebook:RemoteAuthenticationTimeout", "0.0:0:30"},
{"Facebook:SaveTokens", "true"},
{"Facebook:SendAppSecretProof", "true"},
@ -73,7 +72,6 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
Assert.Equal("<issuer>", options.ClaimsIssuer);
Assert.Equal("<id>", options.ClientId);
Assert.Equal("<secret>", options.ClientSecret);
Assert.Equal("<display>", options.DisplayName);
Assert.Equal(new TimeSpan(0, 0, 0, 30), options.RemoteAuthenticationTimeout);
Assert.True(options.SaveTokens);
Assert.True(options.SendAppSecretProof);

View File

@ -49,7 +49,6 @@ namespace Microsoft.AspNetCore.Authentication.Google
{"Google:BackchannelTimeout", "0.0:0:30"},
//{"Google:CallbackPath", "/callbackpath"}, // PathString doesn't convert
{"Google:ClaimsIssuer", "<issuer>"},
{"Google:DisplayName", "<display>"},
{"Google:RemoteAuthenticationTimeout", "0.0:0:30"},
{"Google:SaveTokens", "true"},
{"Google:SendAppSecretProof", "true"},
@ -70,7 +69,6 @@ namespace Microsoft.AspNetCore.Authentication.Google
Assert.Equal("<issuer>", options.ClaimsIssuer);
Assert.Equal("<id>", options.ClientId);
Assert.Equal("<secret>", options.ClientSecret);
Assert.Equal("<display>", options.DisplayName);
Assert.Equal(new TimeSpan(0, 0, 0, 30), options.RemoteAuthenticationTimeout);
Assert.True(options.SaveTokens);
Assert.Equal("<signIn>", options.SignInScheme);

View File

@ -48,11 +48,10 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{"Bearer:BackchannelTimeout", "0.0:0:30"},
{"Bearer:Challenge", "<challenge>"},
{"Bearer:ClaimsIssuer", "<issuer>"},
{"Bearer:DisplayName", "<display>"},
{"Bearer:IncludeErrorDetails", "true"},
{"Bearer:MetadataAddress", "<metadata>"},
{"Bearer:RefreshOnIssuerKeyNotFound", "true"},
{"Bearer:RequireHttpsMetadata", "true"},
{"Bearer:RequireHttpsMetadata", "false"},
{"Bearer:SaveToken", "true"},
};
var configurationBuilder = new ConfigurationBuilder();
@ -67,11 +66,10 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
Assert.Equal("<authority>", options.Authority);
Assert.Equal("<challenge>", options.Challenge);
Assert.Equal("<issuer>", options.ClaimsIssuer);
Assert.Equal("<display>", options.DisplayName);
Assert.True(options.IncludeErrorDetails);
Assert.Equal("<metadata>", options.MetadataAddress);
Assert.True(options.RefreshOnIssuerKeyNotFound);
Assert.True(options.RequireHttpsMetadata);
Assert.False(options.RequireHttpsMetadata);
Assert.True(options.SaveToken);
}

View File

@ -50,7 +50,6 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
{"Microsoft:BackchannelTimeout", "0.0:0:30"},
//{"Microsoft:CallbackPath", "/callbackpath"}, // PathString doesn't convert
{"Microsoft:ClaimsIssuer", "<issuer>"},
{"Microsoft:DisplayName", "<display>"},
{"Microsoft:RemoteAuthenticationTimeout", "0.0:0:30"},
{"Microsoft:SaveTokens", "true"},
{"Microsoft:SendAppSecretProof", "true"},
@ -71,7 +70,6 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
Assert.Equal("<issuer>", options.ClaimsIssuer);
Assert.Equal("<id>", options.ClientId);
Assert.Equal("<secret>", options.ClientSecret);
Assert.Equal("<display>", options.DisplayName);
Assert.Equal(new TimeSpan(0, 0, 0, 30), options.RemoteAuthenticationTimeout);
Assert.True(options.SaveTokens);
Assert.Equal("<signIn>", options.SignInScheme);

View File

@ -36,6 +36,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
{"OpenIdConnect:ClientId", "<id>"},
{"OpenIdConnect:ClientSecret", "<secret>"},
{"OpenIdConnect:RequireHttpsMetadata", "false"},
{"OpenIdConnect:Authority", "<auth>"}
};
var configurationBuilder = new ConfigurationBuilder();
@ -48,6 +49,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.Equal("<id>", options.ClientId);
Assert.Equal("<secret>", options.ClientSecret);
Assert.Equal("<auth>", options.Authority);
Assert.False(options.RequireHttpsMetadata);
}

View File

@ -42,7 +42,6 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
{"Twitter:BackchannelTimeout", "0.0:0:30"},
//{"Twitter:CallbackPath", "/callbackpath"}, // PathString doesn't convert
{"Twitter:ClaimsIssuer", "<issuer>"},
{"Twitter:DisplayName", "<display>"},
{"Twitter:RemoteAuthenticationTimeout", "0.0:0:30"},
{"Twitter:SaveTokens", "true"},
{"Twitter:SendAppSecretProof", "true"},
@ -60,7 +59,6 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
Assert.Equal("<issuer>", options.ClaimsIssuer);
Assert.Equal("<key>", options.ConsumerKey);
Assert.Equal("<secret>", options.ConsumerSecret);
Assert.Equal("<display>", options.DisplayName);
Assert.Equal(new TimeSpan(0, 0, 0, 30), options.RemoteAuthenticationTimeout);
Assert.True(options.SaveTokens);
Assert.Equal("<signIn>", options.SignInScheme);