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 loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||||
var logger = loggerFactory.CreateLogger<ChallengeResult>();
|
var logger = loggerFactory.CreateLogger<ChallengeResult>();
|
||||||
|
|
||||||
|
logger.ChallengeResultExecuting(AuthenticationSchemes);
|
||||||
|
|
||||||
var authentication = context.HttpContext.Authentication;
|
var authentication = context.HttpContext.Authentication;
|
||||||
if (AuthenticationSchemes.Count > 0)
|
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var scheme in AuthenticationSchemes)
|
foreach (var scheme in AuthenticationSchemes)
|
||||||
{
|
{
|
||||||
|
|
@ -113,8 +115,6 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
{
|
{
|
||||||
await authentication.ChallengeAsync(Properties);
|
await authentication.ChallengeAsync(Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.ChallengeResultExecuting(AuthenticationSchemes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -937,22 +937,13 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
public virtual ChallengeResult Challenge()
|
public virtual ChallengeResult Challenge()
|
||||||
=> new ChallengeResult();
|
=> 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>
|
/// <summary>
|
||||||
/// Creates a <see cref="ChallengeResult"/> with the specified authentication schemes.
|
/// Creates a <see cref="ChallengeResult"/> with the specified authentication schemes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ChallengeResult Challenge(IList<string> authenticationSchemes)
|
public virtual ChallengeResult Challenge(params string[] authenticationSchemes)
|
||||||
=> new ChallengeResult(authenticationSchemes);
|
=> new ChallengeResult(authenticationSchemes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -965,30 +956,18 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
public virtual ChallengeResult Challenge(AuthenticationProperties properties)
|
public virtual ChallengeResult Challenge(AuthenticationProperties properties)
|
||||||
=> new ChallengeResult(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>
|
/// <summary>
|
||||||
/// Creates a <see cref="ChallengeResult"/> with the specified specified authentication schemes and
|
/// Creates a <see cref="ChallengeResult"/> with the specified specified authentication schemes and
|
||||||
/// <paramref name="properties" />.
|
/// <paramref name="properties" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
|
||||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||||
/// challenge.</param>
|
/// challenge.</param>
|
||||||
|
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||||
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
/// <returns>The created <see cref="ChallengeResult"/> for the response.</returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ChallengeResult Challenge(
|
public virtual ChallengeResult Challenge(
|
||||||
IList<string> authenticationSchemes,
|
AuthenticationProperties properties,
|
||||||
AuthenticationProperties properties)
|
params string[] authenticationSchemes)
|
||||||
=> new ChallengeResult(authenticationSchemes, properties);
|
=> new ChallengeResult(authenticationSchemes, properties);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -999,22 +978,13 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
public virtual ForbidResult Forbid()
|
public virtual ForbidResult Forbid()
|
||||||
=> new ForbidResult();
|
=> 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>
|
/// <summary>
|
||||||
/// Creates a <see cref="ForbidResult"/> with the specified authentication schemes.
|
/// Creates a <see cref="ForbidResult"/> with the specified authentication schemes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ForbidResult Forbid(IList<string> authenticationSchemes)
|
public virtual ForbidResult Forbid(params string[] authenticationSchemes)
|
||||||
=> new ForbidResult(authenticationSchemes);
|
=> new ForbidResult(authenticationSchemes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1027,30 +997,63 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
public virtual ForbidResult Forbid(AuthenticationProperties properties)
|
public virtual ForbidResult Forbid(AuthenticationProperties properties)
|
||||||
=> new ForbidResult(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>
|
/// <summary>
|
||||||
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication schemes and
|
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication schemes and
|
||||||
/// <paramref name="properties" />.
|
/// <paramref name="properties" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
|
||||||
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the authentication
|
||||||
/// challenge.</param>
|
/// challenge.</param>
|
||||||
|
/// <param name="authenticationSchemes">The authentication schemes to challenge.</param>
|
||||||
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
/// <returns>The created <see cref="ForbidResult"/> for the response.</returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual ForbidResult Forbid(IList<string> authenticationSchemes, AuthenticationProperties properties)
|
public virtual ForbidResult Forbid(AuthenticationProperties properties, params string[] authenticationSchemes)
|
||||||
=> new ForbidResult(authenticationSchemes, properties);
|
=> 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>
|
/// <summary>
|
||||||
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
/// Updates the specified <paramref name="model"/> instance using values from the controller's current
|
||||||
/// <see cref="IValueProvider"/>.
|
/// <see cref="IValueProvider"/>.
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
|
||||||
var logger = loggerFactory.CreateLogger<ForbidResult>();
|
var logger = loggerFactory.CreateLogger<ForbidResult>();
|
||||||
|
|
||||||
|
logger.ForbidResultExecuting(AuthenticationSchemes);
|
||||||
|
|
||||||
var authentication = context.HttpContext.Authentication;
|
var authentication = context.HttpContext.Authentication;
|
||||||
|
|
||||||
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
|
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 0)
|
||||||
|
|
@ -114,8 +116,6 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
{
|
{
|
||||||
await authentication.ForbidAsync(Properties);
|
await authentication.ForbidAsync(Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.ForbidResultExecuting(AuthenticationSchemes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
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> _actionFilterShortCircuit;
|
||||||
private static readonly Action<ILogger, object, Exception> _exceptionFilterShortCircuit;
|
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;
|
private static readonly Action<ILogger, int, Exception> _httpStatusCodeResultExecuting;
|
||||||
|
|
||||||
|
|
@ -126,11 +129,21 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
4,
|
4,
|
||||||
"Request was short circuited at exception filter '{ExceptionFilter}'.");
|
"Request was short circuited at exception filter '{ExceptionFilter}'.");
|
||||||
|
|
||||||
_resultExecuting = LoggerMessage.Define<string[]>(
|
_forbidResultExecuting = LoggerMessage.Define<string[]>(
|
||||||
LogLevel.Information,
|
LogLevel.Information,
|
||||||
eventId: 1,
|
eventId: 1,
|
||||||
formatString: $"Executing {nameof(ForbidResult)} with authentication schemes ({{Schemes}}).");
|
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>(
|
_httpStatusCodeResultExecuting = LoggerMessage.Define<int>(
|
||||||
LogLevel.Information,
|
LogLevel.Information,
|
||||||
1,
|
1,
|
||||||
|
|
@ -305,7 +318,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
|
|
||||||
public static void ForbidResultExecuting(this ILogger logger, IList<string> authenticationSchemes)
|
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)
|
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);
|
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)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -340,4 +340,7 @@
|
||||||
<data name="Formatter_NoMediaTypes" xml:space="preserve">
|
<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>
|
<value>No media types found in '{0}.{1}'. Add at least one media type to the list of supported media types.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MustSpecifyAtLeastOneAuthenticationScheme" xml:space="preserve">
|
||||||
|
<value>At least one authentication scheme must be specified.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</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
|
public class ForbidResultTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncOnAuthenticationManager()
|
public async Task ExecuteResultAsync_InvokesForbidAsyncOnAuthenticationManager()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authenticationManager = new Mock<AuthenticationManager>();
|
var authenticationManager = new Mock<AuthenticationManager>();
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncOnAllConfiguredSchemes()
|
public async Task ExecuteResultAsync_InvokesForbidAsyncOnAllConfiguredSchemes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authProperties = new AuthenticationProperties();
|
var authProperties = new AuthenticationProperties();
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
authenticationManager.Verify();
|
authenticationManager.Verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData =>
|
public static TheoryData ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData =>
|
||||||
new TheoryData<AuthenticationProperties>
|
new TheoryData<AuthenticationProperties>
|
||||||
{
|
{
|
||||||
null,
|
null,
|
||||||
|
|
@ -85,8 +85,8 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
};
|
};
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData))]
|
[MemberData(nameof(ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData))]
|
||||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncWithAuthProperties(AuthenticationProperties expected)
|
public async Task ExecuteResultAsync_InvokesForbidAsyncWithAuthProperties(AuthenticationProperties expected)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var authenticationManager = new Mock<AuthenticationManager>();
|
var authenticationManager = new Mock<AuthenticationManager>();
|
||||||
|
|
@ -113,8 +113,8 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(ExecuteResultAsync_InvokesForbiddenAsyncWithAuthPropertiesData))]
|
[MemberData(nameof(ExecuteResultAsync_InvokesForbidAsyncWithAuthPropertiesData))]
|
||||||
public async Task ExecuteResultAsync_InvokesForbiddenAsyncWithAuthProperties_WhenAuthenticationSchemesIsEmpty(
|
public async Task ExecuteResultAsync_InvokesForbidAsyncWithAuthProperties_WhenAuthenticationSchemesIsEmpty(
|
||||||
AuthenticationProperties expected)
|
AuthenticationProperties expected)
|
||||||
{
|
{
|
||||||
// Arrange
|
// 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