Introduce SignInResult/SignOutResult and ControllerBase.SignIn/SignOut
This commit is contained in:
parent
49e0a958c5
commit
f9d24a8521
|
|
@ -101,8 +101,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||
var logger = loggerFactory.CreateLogger<ChallengeResult>();
|
||||
|
||||
logger.ChallengeResultExecuting(AuthenticationSchemes);
|
||||
|
||||
var authentication = context.HttpContext.Authentication;
|
||||
if (AuthenticationSchemes.Count > 0)
|
||||
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
|
||||
{
|
||||
foreach (var scheme in AuthenticationSchemes)
|
||||
{
|
||||
|
|
@ -113,8 +115,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
await authentication.ChallengeAsync(Properties);
|
||||
}
|
||||
|
||||
logger.ChallengeResultExecuting(AuthenticationSchemes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -937,22 +937,13 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public virtual ChallengeResult Challenge()
|
||||
=> new ChallengeResult();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChallengeResult"/> with the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to challenge.</param>
|
||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ChallengeResult Challenge(string authenticationScheme)
|
||||
=> new ChallengeResult(authenticationScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChallengeResult"/> with the specified authentication schemes.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ChallengeResult Challenge(IList<string> authenticationSchemes)
|
||||
public virtual ChallengeResult Challenge(params string[] authenticationSchemes)
|
||||
=> new ChallengeResult(authenticationSchemes);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -965,30 +956,18 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public virtual ChallengeResult Challenge(AuthenticationProperties properties)
|
||||
=> new ChallengeResult(properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChallengeResult"/> with the specified specified authentication scheme and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to challenge.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||
/// challenge.</param>
|
||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ChallengeResult Challenge(string authenticationScheme, AuthenticationProperties properties)
|
||||
=> new ChallengeResult(authenticationScheme, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChallengeResult"/> with the specified specified authentication schemes and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||
/// challenge.</param>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ChallengeResult Challenge(
|
||||
IList<string> authenticationSchemes,
|
||||
AuthenticationProperties properties)
|
||||
AuthenticationProperties properties,
|
||||
params string[] authenticationSchemes)
|
||||
=> new ChallengeResult(authenticationSchemes, properties);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -999,22 +978,13 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public virtual ForbidResult Forbid()
|
||||
=> new ForbidResult();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ForbidResult"/> with the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to challenge.</param>
|
||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ForbidResult Forbid(string authenticationScheme)
|
||||
=> new ForbidResult(authenticationScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ForbidResult"/> with the specified authentication schemes.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ForbidResult Forbid(IList<string> authenticationSchemes)
|
||||
public virtual ForbidResult Forbid(params string[] authenticationSchemes)
|
||||
=> new ForbidResult(authenticationSchemes);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1027,30 +997,63 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public virtual ForbidResult Forbid(AuthenticationProperties properties)
|
||||
=> new ForbidResult(properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication scheme and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to challenge.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||
/// challenge.</param>
|
||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ForbidResult Forbid(string authenticationScheme, AuthenticationProperties properties)
|
||||
=> new ForbidResult(authenticationScheme, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication schemes and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||
/// challenge.</param>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual ForbidResult Forbid(IList<string> authenticationSchemes, AuthenticationProperties properties)
|
||||
public virtual ForbidResult Forbid(AuthenticationProperties properties, params string[] authenticationSchemes)
|
||||
=> new ForbidResult(authenticationSchemes, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SignInResult"/> with the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/> containing the user claims.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme to use for the sign-in operation.</param>
|
||||
/// <returns>The created <see cref="SignInResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual SignInResult SignIn(ClaimsPrincipal principal, string authenticationScheme)
|
||||
=> new SignInResult(authenticationScheme, principal);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SignInResult"/> with the specified specified authentication scheme and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/> containing the user claims.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-in operation.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme to use for the sign-in operation.</param>
|
||||
/// <returns>The created <see cref="SignInResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual SignInResult SignIn(
|
||||
ClaimsPrincipal principal,
|
||||
AuthenticationProperties properties,
|
||||
string authenticationScheme)
|
||||
=> new SignInResult(authenticationScheme, principal, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SignOutResult"/> with the specified authentication schemes.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to use for the sign-out operation.</param>
|
||||
/// <returns>The created <see cref="SignOutResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual SignOutResult SignOut(params string[] authenticationSchemes)
|
||||
=> new SignOutResult(authenticationSchemes);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="SignOutResult"/> with the specified specified authentication schemes and
|
||||
/// <paramref name="properties" />.
|
||||
/// </summary>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-out operation.</param>
|
||||
/// <param name="authenticationSchemes">The authentication scheme to use for the sign-out operation.</param>
|
||||
/// <returns>The created <see cref="SignOutResult"/> for the response.</returns>
|
||||
[NonAction]
|
||||
public virtual SignOutResult SignOut(AuthenticationProperties properties, params string[] authenticationSchemes)
|
||||
=> new SignOutResult(authenticationSchemes, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||
/// <see cref="IValueProvider"/>.
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||
var logger = loggerFactory.CreateLogger<ForbidResult>();
|
||||
|
||||
logger.ForbidResultExecuting(AuthenticationSchemes);
|
||||
|
||||
var authentication = context.HttpContext.Authentication;
|
||||
|
||||
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
|
||||
|
|
@ -114,8 +116,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
await authentication.ForbidAsync(Properties);
|
||||
}
|
||||
|
||||
logger.ForbidResultExecuting(AuthenticationSchemes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
|
@ -40,7 +41,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
private static readonly Action<ILogger, object, Exception> _actionFilterShortCircuit;
|
||||
private static readonly Action<ILogger, object, Exception> _exceptionFilterShortCircuit;
|
||||
|
||||
private static readonly Action<ILogger, string[], Exception> _resultExecuting;
|
||||
private static readonly Action<ILogger, string[], Exception> _forbidResultExecuting;
|
||||
private static readonly Action<ILogger, string, ClaimsPrincipal, Exception> _signInResultExecuting;
|
||||
private static readonly Action<ILogger, string[], Exception> _signOutResultExecuting;
|
||||
|
||||
private static readonly Action<ILogger, int, Exception> _httpStatusCodeResultExecuting;
|
||||
|
||||
|
|
@ -126,11 +129,21 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
4,
|
||||
"Request was short circuited at exception filter '{ExceptionFilter}'.");
|
||||
|
||||
_resultExecuting = LoggerMessage.Define<string[]>(
|
||||
_forbidResultExecuting = LoggerMessage.Define<string[]>(
|
||||
LogLevel.Information,
|
||||
eventId: 1,
|
||||
formatString: $"Executing {nameof(ForbidResult)} with authentication schemes ({{Schemes}}).");
|
||||
|
||||
_signInResultExecuting = LoggerMessage.Define<string, ClaimsPrincipal>(
|
||||
LogLevel.Information,
|
||||
eventId: 1,
|
||||
formatString: $"Executing {nameof(SignInResult)} with authentication scheme ({{Scheme}}) and the following principal: {{Principal}}.");
|
||||
|
||||
_signOutResultExecuting = LoggerMessage.Define<string[]>(
|
||||
LogLevel.Information,
|
||||
eventId: 1,
|
||||
formatString: $"Executing {nameof(SignOutResult)} with authentication schemes ({{Schemes}}).");
|
||||
|
||||
_httpStatusCodeResultExecuting = LoggerMessage.Define<int>(
|
||||
LogLevel.Information,
|
||||
1,
|
||||
|
|
@ -305,7 +318,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
public static void ForbidResultExecuting(this ILogger logger, IList<string> authenticationSchemes)
|
||||
{
|
||||
_resultExecuting(logger, authenticationSchemes.ToArray(), null);
|
||||
_forbidResultExecuting(logger, authenticationSchemes.ToArray(), null);
|
||||
}
|
||||
|
||||
public static void SignInResultExecuting(this ILogger logger, string authenticationScheme, ClaimsPrincipal principal)
|
||||
{
|
||||
_signInResultExecuting(logger, authenticationScheme, principal, null);
|
||||
}
|
||||
|
||||
public static void SignOutResultExecuting(this ILogger logger, IList<string> authenticationSchemes)
|
||||
{
|
||||
_signOutResultExecuting(logger, authenticationSchemes.ToArray(), null);
|
||||
}
|
||||
|
||||
public static void HttpStatusCodeResultExecuting(this ILogger logger, int statusCode)
|
||||
|
|
|
|||
|
|
@ -1146,6 +1146,22 @@ namespace Microsoft.AspNetCore.Mvc.Core
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("Formatter_NoMediaTypes"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// At least one authentication scheme must be specified.
|
||||
/// </summary>
|
||||
internal static string MustSpecifyAtLeastOneAuthenticationScheme
|
||||
{
|
||||
get { return GetString("MustSpecifyAtLeastOneAuthenticationScheme"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// At least one authentication scheme must be specified.
|
||||
/// </summary>
|
||||
internal static string FormatMustSpecifyAtLeastOneAuthenticationScheme()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("MustSpecifyAtLeastOneAuthenticationScheme"));
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -340,4 +340,7 @@
|
|||
<data name="Formatter_NoMediaTypes" xml:space="preserve">
|
||||
<value>No media types found in '{0}.{1}'. Add at least one media type to the list of supported media types.</value>
|
||||
</data>
|
||||
<data name="MustSpecifyAtLeastOneAuthenticationScheme" xml:space="preserve">
|
||||
<value>At least one authentication scheme must be specified.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
// 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.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:AuthenticationManager.SignInAsync"/>.
|
||||
/// </summary>
|
||||
public class SignInResult : ActionResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignInResult"/> with the
|
||||
/// specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to use when signing in the user.</param>
|
||||
/// <param name="principal">The claims principal containing the user claims.</param>
|
||||
public SignInResult(string authenticationScheme, ClaimsPrincipal principal)
|
||||
: this(authenticationScheme, principal, properties: null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignInResult"/> with the
|
||||
/// specified authentication scheme and <paramref name="properties"/>.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication schemes to use when signing in the user.</param>
|
||||
/// <param name="principal">The claims principal containing the user claims.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-in operation.</param>
|
||||
public SignInResult(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
{
|
||||
if (authenticationScheme == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(authenticationScheme));
|
||||
}
|
||||
|
||||
if (principal == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(principal));
|
||||
}
|
||||
|
||||
AuthenticationScheme = authenticationScheme;
|
||||
Principal = principal;
|
||||
Properties = properties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication scheme that is used to perform the sign-in operation.
|
||||
/// </summary>
|
||||
public string AuthenticationScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ClaimsPrincipal"/> containing the user claims.
|
||||
/// </summary>
|
||||
public ClaimsPrincipal Principal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="AuthenticationProperties"/> used to perform the sign-in operation.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (AuthenticationScheme == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
/* property: */ nameof(AuthenticationScheme),
|
||||
/* type: */ nameof(SignInResult)));
|
||||
}
|
||||
|
||||
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||
var logger = loggerFactory.CreateLogger<SignInResult>();
|
||||
|
||||
logger.SignInResultExecuting(AuthenticationScheme, Principal);
|
||||
|
||||
var authentication = context.HttpContext.Authentication;
|
||||
await authentication.SignInAsync(AuthenticationScheme, Principal, Properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:AuthenticationManager.SignOutAsync"/>.
|
||||
/// </summary>
|
||||
public class SignOutResult : ActionResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignOutResult"/> with the
|
||||
/// specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication scheme to use when signing out the user.</param>
|
||||
public SignOutResult(string authenticationScheme)
|
||||
: this(new[] { authenticationScheme })
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignOutResult"/> with the
|
||||
/// specified authentication schemes.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication schemes to use when signing out the user.</param>
|
||||
public SignOutResult(IList<string> authenticationSchemes)
|
||||
: this(authenticationSchemes, properties: null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignOutResult"/> with the
|
||||
/// specified authentication scheme and <paramref name="properties"/>.
|
||||
/// </summary>
|
||||
/// <param name="authenticationScheme">The authentication schemes to use when signing out the user.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-out operation.</param>
|
||||
public SignOutResult(string authenticationScheme, AuthenticationProperties properties)
|
||||
: this(new[] { authenticationScheme }, properties)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignOutResult"/> with the
|
||||
/// specified authentication schemes and <paramref name="properties"/>.
|
||||
/// </summary>
|
||||
/// <param name="authenticationSchemes">The authentication scheme to use when signing out the user.</param>
|
||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-out operation.</param>
|
||||
public SignOutResult(IList<string> authenticationSchemes, AuthenticationProperties properties)
|
||||
{
|
||||
if (authenticationSchemes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(authenticationSchemes));
|
||||
}
|
||||
|
||||
if (authenticationSchemes.Count == 0)
|
||||
{
|
||||
throw new ArgumentException(Resources.MustSpecifyAtLeastOneAuthenticationScheme, nameof(authenticationSchemes));
|
||||
}
|
||||
|
||||
AuthenticationSchemes = authenticationSchemes;
|
||||
Properties = properties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication schemes that are challenged.
|
||||
/// </summary>
|
||||
public IList<string> AuthenticationSchemes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="AuthenticationProperties"/> used to perform the sign-out operation.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (AuthenticationSchemes == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
Resources.FormatPropertyOfTypeCannotBeNull(
|
||||
/* property: */ nameof(AuthenticationSchemes),
|
||||
/* type: */ nameof(SignOutResult)));
|
||||
}
|
||||
|
||||
if (AuthenticationSchemes.Count == 0)
|
||||
{
|
||||
throw new ArgumentException(Resources.MustSpecifyAtLeastOneAuthenticationScheme, nameof(AuthenticationSchemes));
|
||||
}
|
||||
|
||||
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||
var logger = loggerFactory.CreateLogger<SignOutResult>();
|
||||
|
||||
logger.SignOutResultExecuting(AuthenticationSchemes);
|
||||
|
||||
var authentication = context.HttpContext.Authentication;
|
||||
|
||||
for (var i = 0; i < AuthenticationSchemes.Count; i++)
|
||||
{
|
||||
await authentication.SignOutAsync(AuthenticationSchemes[i], Properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public class ForbidResultTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncOnAuthenticationManager()
|
||||
public async Task ExecuteResultAsync_InvokesForbidAsyncOnAuthenticationManager()
|
||||
{
|
||||
// Arrange
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncOnAllConfiguredSchemes()
|
||||
public async Task ExecuteResultAsync_InvokesForbidAsyncOnAllConfiguredSchemes()
|
||||
{
|
||||
// Arrange
|
||||
var authProperties = new AuthenticationProperties();
|
||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
authenticationManager.Verify();
|
||||
}
|
||||
|
||||
public static TheoryData ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData =>
|
||||
public static TheoryData ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData =>
|
||||
new TheoryData<AuthenticationProperties>
|
||||
{
|
||||
null,
|
||||
|
|
@ -85,8 +85,8 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData))]
|
||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncWithAuthProperties(AuthenticationProperties expected)
|
||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData))]
|
||||
public async Task ExecuteResultAsync_InvokesForbidAsyncWithAuthProperties(AuthenticationProperties expected)
|
||||
{
|
||||
// Arrange
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
|
|
@ -113,8 +113,8 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData))]
|
||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncWithAuthProperties_WhenAuthenticationSchemesIsEmpty(
|
||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData))]
|
||||
public async Task ExecuteResultAsync_InvokesForbidAsyncWithAuthProperties_WhenAuthenticationSchemesIsEmpty(
|
||||
AuthenticationProperties expected)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
// 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.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
public class SignInResultTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesSignInAsyncOnAuthenticationManager()
|
||||
{
|
||||
// Arrange
|
||||
var principal = new ClaimsPrincipal();
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
authenticationManager
|
||||
.Setup(c => c.SignInAsync("", principal, null))
|
||||
.Returns(TaskCache.CompletedTask)
|
||||
.Verifiable();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(c => c.RequestServices).Returns(CreateServices());
|
||||
httpContext.Setup(c => c.Authentication).Returns(authenticationManager.Object);
|
||||
var result = new SignInResult("", principal, null);
|
||||
var routeData = new RouteData();
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
httpContext.Object,
|
||||
routeData,
|
||||
new ActionDescriptor());
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
authenticationManager.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesSignInAsyncOnConfiguredScheme()
|
||||
{
|
||||
// Arrange
|
||||
var principal = new ClaimsPrincipal();
|
||||
var authProperties = new AuthenticationProperties();
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
authenticationManager
|
||||
.Setup(c => c.SignInAsync("Scheme1", principal, authProperties))
|
||||
.Returns(TaskCache.CompletedTask)
|
||||
.Verifiable();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(c => c.RequestServices).Returns(CreateServices());
|
||||
httpContext.Setup(c => c.Authentication).Returns(authenticationManager.Object);
|
||||
var result = new SignInResult("Scheme1", principal, authProperties);
|
||||
var routeData = new RouteData();
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
httpContext.Object,
|
||||
routeData,
|
||||
new ActionDescriptor());
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
authenticationManager.Verify();
|
||||
}
|
||||
|
||||
private static IServiceProvider CreateServices()
|
||||
{
|
||||
return new ServiceCollection()
|
||||
.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance)
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
public class SignOutResultTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesSignOutAsyncOnAuthenticationManager()
|
||||
{
|
||||
// Arrange
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
authenticationManager
|
||||
.Setup(c => c.SignOutAsync("", null))
|
||||
.Returns(TaskCache.CompletedTask)
|
||||
.Verifiable();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(c => c.RequestServices).Returns(CreateServices());
|
||||
httpContext.Setup(c => c.Authentication).Returns(authenticationManager.Object);
|
||||
var result = new SignOutResult("", null);
|
||||
var routeData = new RouteData();
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
httpContext.Object,
|
||||
routeData,
|
||||
new ActionDescriptor());
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
authenticationManager.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteResultAsync_InvokesSignOutAsyncOnAllConfiguredSchemes()
|
||||
{
|
||||
// Arrange
|
||||
var authProperties = new AuthenticationProperties();
|
||||
var authenticationManager = new Mock<AuthenticationManager>();
|
||||
authenticationManager
|
||||
.Setup(c => c.SignOutAsync("Scheme1", authProperties))
|
||||
.Returns(TaskCache.CompletedTask)
|
||||
.Verifiable();
|
||||
authenticationManager
|
||||
.Setup(c => c.SignOutAsync("Scheme2", authProperties))
|
||||
.Returns(TaskCache.CompletedTask)
|
||||
.Verifiable();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(c => c.RequestServices).Returns(CreateServices());
|
||||
httpContext.Setup(c => c.Authentication).Returns(authenticationManager.Object);
|
||||
var result = new SignOutResult(new[] { "Scheme1", "Scheme2" }, authProperties);
|
||||
var routeData = new RouteData();
|
||||
|
||||
var actionContext = new ActionContext(
|
||||
httpContext.Object,
|
||||
routeData,
|
||||
new ActionDescriptor());
|
||||
|
||||
// Act
|
||||
await result.ExecuteResultAsync(actionContext);
|
||||
|
||||
// Assert
|
||||
authenticationManager.Verify();
|
||||
}
|
||||
|
||||
private static IServiceProvider CreateServices()
|
||||
{
|
||||
return new ServiceCollection()
|
||||
.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance)
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue