Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
Introduce SignInResult/SignOutResult and ControllerBase.SignIn/SignOut
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinchalet authored and rynowak committed Mar 28, 2016
1 parent 49e0a95 commit f9d24a8
Show file tree
Hide file tree
Showing 11 changed files with 491 additions and 61 deletions.
6 changes: 3 additions & 3 deletions src/Microsoft.AspNetCore.Mvc.Core/ChallengeResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ public override async Task ExecuteResultAsync(ActionContext context)
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)
{
Expand All @@ -113,8 +115,6 @@ public override async Task ExecuteResultAsync(ActionContext context)
{
await authentication.ChallengeAsync(Properties);
}

logger.ChallengeResultExecuting(AuthenticationSchemes);
}
}
}
95 changes: 49 additions & 46 deletions src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -937,22 +937,13 @@ public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object rout
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>
Expand All @@ -965,30 +956,18 @@ public virtual ChallengeResult Challenge(IList<string> authenticationSchemes)
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>
Expand All @@ -999,22 +978,13 @@ public virtual ChallengeResult Challenge(
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>
Expand All @@ -1028,28 +998,61 @@ public virtual ForbidResult Forbid(AuthenticationProperties properties)
=> new ForbidResult(properties);

/// <summary>
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication scheme and
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication schemes 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>
/// <param name="authenticationSchemes">The authentication schemes to 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);
public virtual ForbidResult Forbid(AuthenticationProperties properties, params string[] authenticationSchemes)
=> new ForbidResult(authenticationSchemes, properties);

/// <summary>
/// Creates a <see cref="ForbidResult"/> with the specified specified authentication schemes and
/// 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="authenticationSchemes">The authentication schemes 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>
/// <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 ForbidResult Forbid(IList<string> authenticationSchemes, AuthenticationProperties properties)
=> new ForbidResult(authenticationSchemes, properties);
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
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.AspNetCore.Mvc.Core/ForbidResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public override async Task ExecuteResultAsync(ActionContext context)
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)
Expand All @@ -114,8 +116,6 @@ public override async Task ExecuteResultAsync(ActionContext context)
{
await authentication.ForbidAsync(Properties);
}

logger.ForbidResultExecuting(AuthenticationSchemes);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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;
Expand Down Expand Up @@ -40,7 +41,9 @@ internal static class MvcCoreLoggerExtensions
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;

Expand Down Expand Up @@ -126,11 +129,21 @@ static MvcCoreLoggerExtensions()
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,
Expand Down Expand Up @@ -305,7 +318,17 @@ public static void ActionFilterShortCircuited(

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)
Expand Down
16 changes: 16 additions & 0 deletions src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
95 changes: 95 additions & 0 deletions src/Microsoft.AspNetCore.Mvc.Core/SignInResult.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Loading

0 comments on commit f9d24a8

Please sign in to comment.