From df5c6730f772775bfc9c14fbff050a1a56d9fef6 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 14 Jun 2017 12:57:45 -0700 Subject: [PATCH] Add new default schemes + tests (#870) --- .../AuthenticationOptions.cs | 23 ++++ .../IAuthenticationSchemeProvider.cs | 16 +++ .../AuthenticationSchemeProvider.cs | 30 +++++ .../AuthenticationSchemeProviderTests.cs | 120 ++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationSchemeProviderTests.cs diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index 08df75a2ad..9e1df2b455 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -47,6 +47,19 @@ namespace Microsoft.AspNetCore.Authentication SchemeMap[name] = builder; } + /// + /// Adds an . + /// + /// The responsible for the scheme. + /// The name of the scheme being added. + /// The display name for the scheme. + public void AddScheme(string name, string displayName) where THandler : IAuthenticationHandler + => AddScheme(name, b => + { + b.DisplayName = displayName; + b.HandlerType = typeof(THandler); + }); + /// /// Used by as the default scheme by . /// @@ -57,9 +70,19 @@ namespace Microsoft.AspNetCore.Authentication /// public string DefaultSignInScheme { get; set; } + /// + /// Used by as the default scheme by . + /// + public string DefaultSignOutScheme { get; set; } + /// /// Used by as the default scheme by . /// public string DefaultChallengeScheme { get; set; } + + /// + /// Used by as the default scheme by . + /// + public string DefaultForbidScheme { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs index 5fa08c977a..675cf52cf9 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs @@ -41,6 +41,14 @@ namespace Microsoft.AspNetCore.Authentication /// The scheme that will be used by default for . Task GetDefaultChallengeSchemeAsync(); + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, this will fallback to . + /// + /// The scheme that will be used by default for . + Task GetDefaultForbidSchemeAsync(); + /// /// Returns the scheme that will be used by default for . /// This is typically specified via . @@ -49,6 +57,14 @@ namespace Microsoft.AspNetCore.Authentication /// The scheme that will be used by default for . Task GetDefaultSignInSchemeAsync(); + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, this will fallback to . + /// + /// The scheme that will be used by default for . + Task GetDefaultSignOutSchemeAsync(); + /// /// Registers a scheme for use by . /// diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index 2ce3801b5b..e56247e18c 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -75,6 +75,21 @@ namespace Microsoft.AspNetCore.Authentication return Task.FromResult(null); } + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, this will fallback to . + /// + /// The scheme that will be used by default for . + public Task GetDefaultForbidSchemeAsync() + { + if (_options.DefaultForbidScheme != null) + { + return GetSchemeAsync(_options.DefaultForbidScheme); + } + return GetDefaultChallengeSchemeAsync(); + } + /// /// Returns the scheme that will be used by default for . /// This is typically specified via . @@ -94,6 +109,21 @@ namespace Microsoft.AspNetCore.Authentication return Task.FromResult(null); } + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, this will fallback to . + /// + /// The scheme that will be used by default for . + public Task GetDefaultSignOutSchemeAsync() + { + if (_options.DefaultSignOutScheme != null) + { + return GetSchemeAsync(_options.DefaultSignOutScheme); + } + return GetDefaultSignInSchemeAsync(); + } + /// /// Returns the matching the name, or null. /// diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationSchemeProviderTests.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationSchemeProviderTests.cs new file mode 100644 index 0000000000..3810f8335f --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationSchemeProviderTests.cs @@ -0,0 +1,120 @@ +// 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.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationSchemeProviderTests + { + [Fact] + public async Task DefaultSignOutFallsbackToSignIn() + { + var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o => + { + o.AddScheme("signin", "whatever"); + o.AddScheme("foobly", "whatever"); + o.DefaultSignInScheme = "signin"; + }).BuildServiceProvider(); + + var provider = services.GetRequiredService(); + var scheme = await provider.GetDefaultSignOutSchemeAsync(); + Assert.NotNull(scheme); + Assert.Equal("signin", scheme.Name); + } + + [Fact] + public async Task DefaultForbidFallsbackToChallenge() + { + var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o => + { + o.AddScheme("challenge", "whatever"); + o.AddScheme("foobly", "whatever"); + o.DefaultChallengeScheme = "challenge"; + }).BuildServiceProvider(); + + var provider = services.GetRequiredService(); + var scheme = await provider.GetDefaultForbidSchemeAsync(); + Assert.NotNull(scheme); + Assert.Equal("challenge", scheme.Name); + } + + [Fact] + public async Task DefaultSchemesFallbackToOnlyScheme() + { + var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o => + { + o.AddScheme("single", "whatever"); + }).BuildServiceProvider(); + + var provider = services.GetRequiredService(); + Assert.Equal("single", (await provider.GetDefaultForbidSchemeAsync()).Name); + Assert.Equal("single", (await provider.GetDefaultAuthenticateSchemeAsync()).Name); + Assert.Equal("single", (await provider.GetDefaultChallengeSchemeAsync()).Name); + Assert.Equal("single", (await provider.GetDefaultSignInSchemeAsync()).Name); + Assert.Equal("single", (await provider.GetDefaultSignOutSchemeAsync()).Name); + } + + [Fact] + public async Task DefaultSchemesAreSet() + { + var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o => + { + o.AddScheme("A", "whatever"); + o.AddScheme("B", "whatever"); + o.AddScheme("C", "whatever"); + o.DefaultChallengeScheme = "A"; + o.DefaultForbidScheme = "B"; + o.DefaultSignInScheme = "C"; + o.DefaultSignOutScheme = "A"; + o.DefaultAuthenticateScheme = "C"; + }).BuildServiceProvider(); + + var provider = services.GetRequiredService(); + Assert.Equal("B", (await provider.GetDefaultForbidSchemeAsync()).Name); + Assert.Equal("C", (await provider.GetDefaultAuthenticateSchemeAsync()).Name); + Assert.Equal("A", (await provider.GetDefaultChallengeSchemeAsync()).Name); + Assert.Equal("C", (await provider.GetDefaultSignInSchemeAsync()).Name); + Assert.Equal("A", (await provider.GetDefaultSignOutSchemeAsync()).Name); + } + + private class Handler : IAuthenticationHandler + { + public Task AuthenticateAsync() + { + throw new NotImplementedException(); + } + + public Task ChallengeAsync(AuthenticationProperties properties) + { + throw new NotImplementedException(); + } + + public Task ForbidAsync(AuthenticationProperties properties) + { + throw new NotImplementedException(); + } + + public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) + { + throw new NotImplementedException(); + } + + public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) + { + throw new NotImplementedException(); + } + + public Task SignOutAsync(AuthenticationProperties properties) + { + throw new NotImplementedException(); + } + } + + } +}