Refactor IAuthenticationHandler/Result
This commit is contained in:
parent
f9e0439ef1
commit
271faf11bb
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public class AuthenticateResult
|
||||
{
|
||||
private AuthenticateResult() { }
|
||||
protected AuthenticateResult() { }
|
||||
|
||||
/// <summary>
|
||||
/// If a ticket was produced, authenticate was successful.
|
||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <summary>
|
||||
/// The authentication ticket.
|
||||
/// </summary>
|
||||
public AuthenticationTicket Ticket { get; private set; }
|
||||
public AuthenticationTicket Ticket { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the claims-principal with authenticated user identities.
|
||||
|
|
@ -36,18 +36,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <summary>
|
||||
/// Holds failure information from the authentication.
|
||||
/// </summary>
|
||||
public Exception Failure { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that stage of authentication was directly handled by user intervention and no
|
||||
/// further processing should be attempted.
|
||||
/// </summary>
|
||||
public bool Handled { get; private set; }
|
||||
public Exception Failure { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was no information returned for this authentication scheme.
|
||||
/// </summary>
|
||||
public bool Nothing { get; private set; }
|
||||
public bool None { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that authentication was successful.
|
||||
|
|
@ -63,23 +57,13 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return new AuthenticateResult() { Ticket = ticket };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that stage of authentication was directly handled by user intervention and no
|
||||
/// further processing should be attempted.
|
||||
/// </summary>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult Handle()
|
||||
{
|
||||
return new AuthenticateResult() { Handled = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was no information returned for this authentication scheme.
|
||||
/// </summary>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult None()
|
||||
public static AuthenticateResult NoResult()
|
||||
{
|
||||
return new AuthenticateResult() { Nothing = true };
|
||||
return new AuthenticateResult() { None = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
context.ForbidAsync(scheme, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Forbid.
|
||||
/// Extension method for Forbid using the <see cref="AuthenticationOptions.DefaultForbidScheme"/> scheme..
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <returns>The task.</returns>
|
||||
|
|
@ -142,6 +142,21 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignOut using the <see cref="AuthenticationOptions.DefaultSignOutScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignOutAsync(this HttpContext context) => context.SignOutAsync(scheme: null, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignOut using the <see cref="AuthenticationOptions.DefaultSignOutScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignOutAsync(this HttpContext context, AuthenticationProperties properties) => context.SignOutAsync(scheme: null, properties: properties);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignOut.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// 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.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
|
|
@ -39,20 +38,5 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task ForbidAsync(AuthenticationProperties properties);
|
||||
|
||||
/// <summary>
|
||||
/// Handle sign in.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> user.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties);
|
||||
|
||||
/// <summary>
|
||||
/// Signout behavior.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignOutAsync(AuthenticationProperties properties);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public interface IAuthenticationRequestHandler : IAuthenticationHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if request processing should stop.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// 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.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to determine if a handler supports SignIn.
|
||||
/// </summary>
|
||||
public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Handle sign in.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> user.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// 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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to determine if a handler supports SignOut.
|
||||
/// </summary>
|
||||
public interface IAuthenticationSignOutHandler : IAuthenticationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Signout behavior.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignOutAsync(AuthenticationProperties properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,4 +18,4 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <returns>The transformed principal.</returns>
|
||||
Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -36,6 +35,8 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
|
||||
private IDictionary<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal);
|
||||
private List<AuthenticationScheme> _requestHandlers = new List<AuthenticationScheme>();
|
||||
private List<AuthenticationScheme> _signOutHandlers = new List<AuthenticationScheme>();
|
||||
private List<AuthenticationScheme> _signInHandlers = new List<AuthenticationScheme>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.
|
||||
|
|
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync()
|
||||
public virtual Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultAuthenticateScheme != null)
|
||||
{
|
||||
|
|
@ -59,20 +60,16 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultChallengeScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// Otherwise, this will fallback to <see cref="GetDefaultAuthenticateSchemeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync()
|
||||
public virtual Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultChallengeScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultChallengeScheme);
|
||||
}
|
||||
if (_map.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_map.Values.First());
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
return GetDefaultAuthenticateSchemeAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -81,7 +78,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Otherwise, this will fallback to <see cref="GetDefaultChallengeSchemeAsync"/> .
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ForbidAsync(HttpContext, string, AuthenticationProperties)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultForbidSchemeAsync()
|
||||
public virtual Task<AuthenticationScheme> GetDefaultForbidSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultForbidScheme != null)
|
||||
{
|
||||
|
|
@ -93,34 +90,40 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignInScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// If only a single sign in handler scheme exists, that will be used, if more than one exists,
|
||||
/// this will fallback to <see cref="GetDefaultAuthenticateSchemeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultSignInSchemeAsync()
|
||||
public virtual Task<AuthenticationScheme> GetDefaultSignInSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultSignInScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultSignInScheme);
|
||||
}
|
||||
if (_map.Count == 1)
|
||||
if (_signInHandlers.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_map.Values.First());
|
||||
return Task.FromResult(_signInHandlers[0]);
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
return GetDefaultAuthenticateSchemeAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignOutScheme"/>.
|
||||
/// Otherwise, this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> .
|
||||
/// If only a single sign out handler scheme exists, that will be used, if more than one exists,
|
||||
/// this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> if that supoorts sign out.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync()
|
||||
public virtual Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultSignOutScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultSignOutScheme);
|
||||
}
|
||||
if (_signOutHandlers.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_signOutHandlers[0]);
|
||||
}
|
||||
return GetDefaultSignInSchemeAsync();
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +132,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme.</param>
|
||||
/// <returns>The scheme or null if not found.</returns>
|
||||
public Task<AuthenticationScheme> GetSchemeAsync(string name)
|
||||
public virtual Task<AuthenticationScheme> GetSchemeAsync(string name)
|
||||
{
|
||||
if (_map.ContainsKey(name))
|
||||
{
|
||||
|
|
@ -142,7 +145,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Returns the schemes in priority order for request handling.
|
||||
/// </summary>
|
||||
/// <returns>The schemes in priority order for request handling</returns>
|
||||
public Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync()
|
||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync()
|
||||
{
|
||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_requestHandlers);
|
||||
}
|
||||
|
|
@ -151,7 +154,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Registers a scheme for use by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The scheme.</param>
|
||||
public void AddScheme(AuthenticationScheme scheme)
|
||||
public virtual void AddScheme(AuthenticationScheme scheme)
|
||||
{
|
||||
if (_map.ContainsKey(scheme.Name))
|
||||
{
|
||||
|
|
@ -167,6 +170,14 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
{
|
||||
_requestHandlers.Add(scheme);
|
||||
}
|
||||
if (typeof(IAuthenticationSignInHandler).IsAssignableFrom(scheme.HandlerType))
|
||||
{
|
||||
_signInHandlers.Add(scheme);
|
||||
}
|
||||
if (typeof(IAuthenticationSignOutHandler).IsAssignableFrom(scheme.HandlerType))
|
||||
{
|
||||
_signOutHandlers.Add(scheme);
|
||||
}
|
||||
_map[scheme.Name] = scheme;
|
||||
}
|
||||
}
|
||||
|
|
@ -175,7 +186,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Removes a scheme, preventing it from being used by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme being removed.</param>
|
||||
public void RemoveScheme(string name)
|
||||
public virtual void RemoveScheme(string name)
|
||||
{
|
||||
if (!_map.ContainsKey(name))
|
||||
{
|
||||
|
|
@ -186,15 +197,15 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
if (_map.ContainsKey(name))
|
||||
{
|
||||
var scheme = _map[name];
|
||||
_requestHandlers.Remove(_requestHandlers.Where(s => s.Name == name).FirstOrDefault());
|
||||
_requestHandlers.Remove(scheme);
|
||||
_signInHandlers.Remove(scheme);
|
||||
_signOutHandlers.Remove(scheme);
|
||||
_map.Remove(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
||||
{
|
||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values);
|
||||
}
|
||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
||||
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values);
|
||||
}
|
||||
}
|
||||
|
|
@ -155,10 +155,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme) as IAuthenticationSignInHandler;
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}");
|
||||
throw new InvalidOperationException($"No IAuthenticationSignInHandler is configured to handle sign in for the scheme: {scheme}");
|
||||
}
|
||||
|
||||
await handler.SignInAsync(principal, properties);
|
||||
|
|
@ -173,15 +173,20 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <returns>A task.</returns>
|
||||
public virtual async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||
{
|
||||
if (string.IsNullOrEmpty(scheme))
|
||||
if (scheme == null)
|
||||
{
|
||||
throw new ArgumentException(nameof(scheme));
|
||||
var defaultScheme = await Schemes.GetDefaultSignOutSchemeAsync();
|
||||
scheme = defaultScheme?.Name;
|
||||
if (scheme == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignOutScheme found.");
|
||||
}
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme) as IAuthenticationSignOutHandler;
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}");
|
||||
throw new InvalidOperationException($"No IAuthenticationSignOutHandler is configured to handle sign out for the scheme: {scheme}");
|
||||
}
|
||||
|
||||
await handler.SignOutAsync(properties);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
// 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.
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<Handler>("signin", "whatever");
|
||||
o.AddScheme<SignInHandler>("signin", "whatever");
|
||||
o.AddScheme<Handler>("foobly", "whatever");
|
||||
o.DefaultSignInScheme = "signin";
|
||||
}).BuildServiceProvider();
|
||||
|
|
@ -49,7 +50,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<Handler>("single", "whatever");
|
||||
o.AddScheme<SignInHandler>("single", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
|
||||
var provider = services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
|
|
@ -60,14 +61,32 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
Assert.Equal("single", (await provider.GetDefaultSignOutSchemeAsync()).Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DefaultSchemesFallbackToAuthenticateScheme()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.DefaultAuthenticateScheme = "B";
|
||||
o.AddScheme<Handler>("A", "whatever");
|
||||
o.AddScheme<SignInHandler>("B", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
|
||||
var provider = services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
Assert.Equal("B", (await provider.GetDefaultForbidSchemeAsync()).Name);
|
||||
Assert.Equal("B", (await provider.GetDefaultAuthenticateSchemeAsync()).Name);
|
||||
Assert.Equal("B", (await provider.GetDefaultChallengeSchemeAsync()).Name);
|
||||
Assert.Equal("B", (await provider.GetDefaultSignInSchemeAsync()).Name);
|
||||
Assert.Equal("B", (await provider.GetDefaultSignOutSchemeAsync()).Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DefaultSchemesAreSet()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<Handler>("A", "whatever");
|
||||
o.AddScheme<Handler>("B", "whatever");
|
||||
o.AddScheme<Handler>("C", "whatever");
|
||||
o.AddScheme<SignInHandler>("A", "whatever");
|
||||
o.AddScheme<SignInHandler>("B", "whatever");
|
||||
o.AddScheme<SignInHandler>("C", "whatever");
|
||||
o.DefaultChallengeScheme = "A";
|
||||
o.DefaultForbidScheme = "B";
|
||||
o.DefaultSignInScheme = "C";
|
||||
|
|
@ -83,6 +102,38 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
Assert.Equal("A", (await provider.GetDefaultSignOutSchemeAsync()).Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SignInSignOutDefaultsToOnlyOne()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<Handler>("basic", "whatever");
|
||||
o.AddScheme<SignOutHandler>("signout", "whatever");
|
||||
o.AddScheme<SignInHandler>("signin", "whatever");
|
||||
o.DefaultAuthenticateScheme = "basic";
|
||||
}).BuildServiceProvider();
|
||||
|
||||
var provider = services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
Assert.Equal("basic", (await provider.GetDefaultForbidSchemeAsync()).Name);
|
||||
Assert.Equal("basic", (await provider.GetDefaultAuthenticateSchemeAsync()).Name);
|
||||
Assert.Equal("basic", (await provider.GetDefaultChallengeSchemeAsync()).Name);
|
||||
Assert.Equal("signin", (await provider.GetDefaultSignInSchemeAsync()).Name);
|
||||
Assert.Equal("signin", (await provider.GetDefaultSignOutSchemeAsync()).Name); // Defaults to single sign in scheme
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SignOutWillDefaultsToSignInThatDoesNotSignOut()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<Handler>("signin", "whatever");
|
||||
o.DefaultSignInScheme = "signin";
|
||||
}).BuildServiceProvider();
|
||||
|
||||
var provider = services.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
Assert.NotNull(await provider.GetDefaultSignOutSchemeAsync());
|
||||
}
|
||||
|
||||
private class Handler : IAuthenticationHandler
|
||||
{
|
||||
public Task<AuthenticateResult> AuthenticateAsync()
|
||||
|
|
@ -104,7 +155,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class SignInHandler : Handler, IAuthenticationSignInHandler
|
||||
{
|
||||
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -116,5 +170,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
private class SignOutHandler : Handler, IAuthenticationSignOutHandler
|
||||
{
|
||||
public Task SignOutAsync(AuthenticationProperties properties)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
// 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 AuthenticationServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task CanOnlySignInIfSupported()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<UberHandler>("uber", "whatever");
|
||||
o.AddScheme<BaseHandler>("base", "whatever");
|
||||
o.AddScheme<SignInHandler>("signin", "whatever");
|
||||
o.AddScheme<SignOutHandler>("signout", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.SignInAsync("uber", new ClaimsPrincipal(), null);
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync("base", new ClaimsPrincipal(), null));
|
||||
await context.SignInAsync("signin", new ClaimsPrincipal(), null);
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync("signout", new ClaimsPrincipal(), null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanOnlySignOutIfSupported()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<UberHandler>("uber", "whatever");
|
||||
o.AddScheme<BaseHandler>("base", "whatever");
|
||||
o.AddScheme<SignInHandler>("signin", "whatever");
|
||||
o.AddScheme<SignOutHandler>("signout", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.SignOutAsync("uber");
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync("base"));
|
||||
await context.SignOutAsync("signout");
|
||||
await context.SignOutAsync("signin");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ServicesWithDefaultIAuthenticationHandlerMethodsTest()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<BaseHandler>("base", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
await context.ChallengeAsync();
|
||||
await context.ForbidAsync();
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ServicesWithDefaultUberMethodsTest()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<UberHandler>("base", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
await context.ChallengeAsync();
|
||||
await context.ForbidAsync();
|
||||
await context.SignOutAsync();
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ServicesWithDefaultSignInMethodsTest()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<SignInHandler>("base", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
await context.ChallengeAsync();
|
||||
await context.ForbidAsync();
|
||||
await context.SignOutAsync();
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ServicesWithDefaultSignOutMethodsTest()
|
||||
{
|
||||
var services = new ServiceCollection().AddOptions().AddAuthenticationCore(o =>
|
||||
{
|
||||
o.AddScheme<SignOutHandler>("base", "whatever");
|
||||
}).BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = services;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
await context.ChallengeAsync();
|
||||
await context.ForbidAsync();
|
||||
await context.SignOutAsync();
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
|
||||
private class BaseHandler : IAuthenticationHandler
|
||||
{
|
||||
public Task<AuthenticateResult> AuthenticateAsync()
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ForbidAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
private class SignInHandler : IAuthenticationSignInHandler
|
||||
{
|
||||
public Task<AuthenticateResult> AuthenticateAsync()
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ForbidAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignOutAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class SignOutHandler : IAuthenticationSignOutHandler
|
||||
{
|
||||
public Task<AuthenticateResult> AuthenticateAsync()
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ForbidAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignOutAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
private class UberHandler : IAuthenticationHandler, IAuthenticationRequestHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler
|
||||
{
|
||||
public Task<AuthenticateResult> AuthenticateAsync()
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ForbidAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<bool> HandleRequestAsync()
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SignOutAsync(AuthenticationProperties properties)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue