Add docs for remaining security items (#26827)

* Add docs for remaining security items

* Google / Facebook / Microsoft Account auth
* Authorization, Authorization.Policy

Contributes to https://github.com/dotnet/aspnetcore/issues/26397

* Apply suggestions from code review

Co-authored-by: Chris Ross <Tratcher@Outlook.com>

* Update src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs

Co-authored-by: Chris Ross <Tratcher@Outlook.com>
This commit is contained in:
Pranav K 2020-10-14 15:36:26 -07:00 committed by GitHub
parent 45c02cd347
commit fae3437139
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 383 additions and 49 deletions

View File

@ -36,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme"></param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddCertificate(this AuthenticationBuilder builder, string authenticationScheme)
=> builder.AddCertificate(authenticationScheme, configureOptions: null);
@ -50,7 +50,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="configureOptions"></param>
/// <param name="configureOptions">A delegate to configure <see cref="CertificateAuthenticationOptions"/>.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddCertificate(this AuthenticationBuilder builder, Action<CertificateAuthenticationOptions> configureOptions)
=> builder.AddCertificate(CertificateAuthenticationDefaults.AuthenticationScheme, configureOptions);
@ -64,8 +64,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme"></param>
/// <param name="configureOptions"></param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="configureOptions">A delegate to configure <see cref="CertificateAuthenticationOptions"/>.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddCertificate(
this AuthenticationBuilder builder,
@ -82,7 +82,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="configureOptions"></param>
/// <param name="configureOptions">A delegate to configure <see cref="CertificateValidationCacheOptions"/>.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddCertificateCache(
this AuthenticationBuilder builder,

View File

@ -3,17 +3,37 @@
namespace Microsoft.AspNetCore.Authentication.Facebook
{
/// <summary>
/// Default values for the Facebook authentication handler.
/// </summary>
public static class FacebookDefaults
{
/// <summary>
/// The default scheme for Facebook authentication. The value is <c>Facebook</c>.
/// </summary>
public const string AuthenticationScheme = "Facebook";
/// <summary>
/// The default display name for Facebook authentication. Defaults to <c>Facebook</c>.
/// </summary>
public static readonly string DisplayName = "Facebook";
// https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#login
/// <summary>
/// The default endpoint used to perform Facebook authentication.
/// </summary>
/// <remarks>
/// For more details about this endpoint, see https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#login.
/// </remarks>
public static readonly string AuthorizationEndpoint = "https://www.facebook.com/v8.0/dialog/oauth";
/// <summary>
/// The OAuth endpoint used to retrieve access tokens.
/// </summary>
public static readonly string TokenEndpoint = "https://graph.facebook.com/v8.0/oauth/access_token";
/// <summary>
/// The Facebook Graph API endpoint that is used to gather additional user information.
/// </summary>
public static readonly string UserInformationEndpoint = "https://graph.facebook.com/v8.0/me";
}
}

View File

@ -7,17 +7,61 @@ using Microsoft.AspNetCore.Authentication.Facebook;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods to configure Facebook OAuth authentication.
/// </summary>
public static class FacebookAuthenticationOptionsExtensions
{
/// <summary>
/// Adds Facebook OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="FacebookDefaults.AuthenticationScheme"/>.
/// <para>
/// Facebook authentication allows application users to sign in with their Facebook account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder)
=> builder.AddFacebook(FacebookDefaults.AuthenticationScheme, _ => { });
/// <summary>
/// Adds Facebook OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="FacebookDefaults.AuthenticationScheme"/>.
/// <para>
/// Facebook authentication allows application users to sign in with their Facebook account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="configureOptions">A delegate to configure <see cref="FacebookOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, Action<FacebookOptions> configureOptions)
=> builder.AddFacebook(FacebookDefaults.AuthenticationScheme, configureOptions);
/// <summary>
/// Adds Facebook OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="FacebookDefaults.AuthenticationScheme"/>.
/// <para>
/// Facebook authentication allows application users to sign in with their Facebook account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="configureOptions">A delegate to configure <see cref="FacebookOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, string authenticationScheme, Action<FacebookOptions> configureOptions)
=> builder.AddFacebook(authenticationScheme, FacebookDefaults.DisplayName, configureOptions);
/// <summary>
/// Adds Facebook OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="FacebookDefaults.AuthenticationScheme"/>.
/// <para>
/// Facebook authentication allows application users to sign in with their Facebook account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="displayName">A display name for the authentication handler.</param>
/// <param name="configureOptions">A delegate to configure <see cref="FacebookOptions"/>.</param>
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<FacebookOptions> configureOptions)
=> builder.AddOAuth<FacebookOptions, FacebookHandler>(authenticationScheme, displayName, configureOptions);
}

View File

@ -17,12 +17,20 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Facebook
{
/// <summary>
/// Authentication handler for Facebook's OAuth based authentication.
/// </summary>
public class FacebookHandler : OAuthHandler<FacebookOptions>
{
/// <summary>
/// Initializes a new instance of <see cref="FacebookHandler"/>.
/// </summary>
/// <inheritdoc />
public FacebookHandler(IOptionsMonitor<FacebookOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
/// <inheritdoc />
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);
@ -64,6 +72,7 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
}
}
/// <inheritdoc />
protected override string FormatScope(IEnumerable<string> scopes)
{
// Facebook deviates from the OAuth spec here. They require comma separated instead of space separated.
@ -72,6 +81,7 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
return string.Join(",", scopes);
}
/// <inheritdoc />
protected override string FormatScope()
=> base.FormatScope();
}

View File

@ -3,9 +3,8 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using System.Globalization;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
@ -68,7 +67,7 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
// Facebook uses a non-standard term for this field.
/// <summary>
/// Gets or sets the Facebook-assigned appId.
/// Gets or sets the Facebook-assigned App ID.
/// </summary>
public string AppId
{
@ -87,15 +86,19 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
}
/// <summary>
/// Gets or sets if the appsecret_proof should be generated and sent with Facebook API calls.
/// This is enabled by default.
/// Gets or sets if the <c>appsecret_proof</c> should be generated and sent with Facebook API calls.
/// </summary>
/// <remarks>See https://developers.facebook.com/docs/graph-api/securing-requests/#appsecret_proof for more details.</remarks>
/// <value>Defaults to <see langword="true"/>.</value>
public bool SendAppSecretProof { get; set; }
/// <summary>
/// The list of fields to retrieve from the UserInformationEndpoint.
/// https://developers.facebook.com/docs/graph-api/reference/user
/// </summary>
/// <value>
/// Defaults to include the following fields if none are specified: "name", "email", "first_name", and "last_name".
/// </value>
public ICollection<string> Fields { get; } = new HashSet<string>();
}
}

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core middleware that enables an application to support Facebook's OAuth 2.0 authentication workflow.</Description>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authentication;security</PackageTags>
</PropertyGroup>

View File

@ -1,8 +1,11 @@
using System.Collections.Generic;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication.OAuth;
namespace Microsoft.AspNetCore.Authentication.Google
{
/// <summary>
/// <see cref="AuthenticationProperties"/> for a Google OAuth challenge.
/// </summary>
public class GoogleChallengeProperties : OAuthChallengeProperties
{
/// <summary>
@ -30,13 +33,24 @@ namespace Microsoft.AspNetCore.Authentication.Google
/// </summary>
public static readonly string PromptParameterKey = "prompt";
/// <summary>
/// Initializes a new instance of <see cref="GoogleChallengeProperties"/>.
/// </summary>
public GoogleChallengeProperties()
{ }
/// <summary>
/// Initializes a new instance of <see cref="GoogleChallengeProperties"/>.
/// </summary>
/// <inheritdoc />
public GoogleChallengeProperties(IDictionary<string, string> items)
: base(items)
{ }
/// <summary>
/// Initializes a new instance of <see cref="GoogleChallengeProperties"/>.
/// </summary>
/// <inheritdoc />
public GoogleChallengeProperties(IDictionary<string, string> items, IDictionary<string, object> parameters)
: base(items, parameters)
{ }

View File

@ -10,16 +10,35 @@ namespace Microsoft.AspNetCore.Authentication.Google
/// </summary>
public static class GoogleDefaults
{
/// <summary>
/// The default scheme for Google authentication. Defaults to <c>Google</c>.
/// </summary>
public const string AuthenticationScheme = "Google";
/// <summary>
/// The default display name for Google authentication. Defaults to <c>Google</c>.
/// </summary>
public static readonly string DisplayName = "Google";
// https://developers.google.com/identity/protocols/oauth2/web-server#httprest
/// <summary>
/// The default endpoint used to perform Google authentication.
/// </summary>
/// <remarks>
/// For more details about this endpoint, see https://developers.google.com/identity/protocols/oauth2/web-server#httprest
/// </remarks>
public static readonly string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
/// <summary>
/// The OAuth endpoint used to exchange access tokens.
/// </summary>
public static readonly string TokenEndpoint = "https://oauth2.googleapis.com/token";
// https://developers.google.com/apis-explorer/#search/oauth2/oauth2/v2/
/// <summary>
/// The Google endpoint that is used to gather additional user information.
/// </summary>
/// <remarks>
/// For more details about this endpoint, see https://developers.google.com/apis-explorer/#search/oauth2/oauth2/v2/.
/// </remarks>
public static readonly string UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
}
}

View File

@ -7,17 +7,62 @@ using Microsoft.AspNetCore.Authentication.Google;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods to configure Google OAuth authentication.
/// </summary>
public static class GoogleExtensions
{
/// <summary>
/// Adds Google OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="GoogleDefaults.AuthenticationScheme"/>.
/// <para>
/// Google authentication allows application users to sign in with their Google account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder)
=> builder.AddGoogle(GoogleDefaults.AuthenticationScheme, _ => { });
/// <summary>
/// Adds Google OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="GoogleDefaults.AuthenticationScheme"/>.
/// <para>
/// Google authentication allows application users to sign in with their Google account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="configureOptions">A delegate to configure <see cref="GoogleOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder, Action<GoogleOptions> configureOptions)
=> builder.AddGoogle(GoogleDefaults.AuthenticationScheme, configureOptions);
/// <summary>
/// Adds Google OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="GoogleDefaults.AuthenticationScheme"/>.
/// <para>
/// Google authentication allows application users to sign in with their Google account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="configureOptions">A delegate to configure <see cref="GoogleOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder, string authenticationScheme, Action<GoogleOptions> configureOptions)
=> builder.AddGoogle(authenticationScheme, GoogleDefaults.DisplayName, configureOptions);
/// <summary>
/// Adds Google OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="GoogleDefaults.AuthenticationScheme"/>.
/// <para>
/// Google authentication allows application users to sign in with their Google account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="displayName">A display name for the authentication handler.</param>
/// <param name="configureOptions">A delegate to configure <see cref="GoogleOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<GoogleOptions> configureOptions)
=> builder.AddOAuth<GoogleOptions, GoogleHandler>(authenticationScheme, displayName, configureOptions);
}

View File

@ -16,12 +16,20 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Google
{
/// <summary>
/// Authentication handler for Google's OAuth based authentication.
/// </summary>
public class GoogleHandler : OAuthHandler<GoogleOptions>
{
/// <summary>
/// Initializes a new instance of <see cref="GoogleHandler"/>.
/// </summary>
/// <inheritdoc />
public GoogleHandler(IOptionsMonitor<GoogleOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
/// <inheritdoc />
protected override async Task<AuthenticationTicket> CreateTicketAsync(
ClaimsIdentity identity,
AuthenticationProperties properties,
@ -46,7 +54,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
}
}
// TODO: Abstract this properties override pattern into the base class?
/// <inheritdoc />
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{
// Google Identity Platform Manual:

View File

@ -34,7 +34,11 @@ namespace Microsoft.AspNetCore.Authentication.Google
}
/// <summary>
/// access_type. Set to 'offline' to request a refresh token.
/// Indicates whether your application can refresh access tokens when the user is not present at the browser.
/// Valid values are <c>online</c>, which is the default value, and <c>offline</c>.
/// <para>
/// Set the value to offline if your application needs to refresh access tokens when the user is not present at the browser.
/// </para>
/// </summary>
public string AccessType { get; set; }
}

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core contains middleware to support Google's OpenId and OAuth 2.0 authentication workflows.</Description>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authentication;security</PackageTags>
</PropertyGroup>

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<Description>ASP.NET Core middleware that enables an application to support the Microsoft Account authentication workflow.</Description>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authentication;security</PackageTags>
</PropertyGroup>

View File

@ -3,17 +3,37 @@
namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
/// <summary>
/// Default values for Microsoft account authentication
/// </summary>
public static class MicrosoftAccountDefaults
{
/// <summary>
/// The default scheme for Microsoft account authentication. Defaults to <c>Microsoft</c>.
/// </summary>
public const string AuthenticationScheme = "Microsoft";
/// <summary>
/// The default display name for Microsoft account authentication. Defaults to <c>Microsoft</c>.
/// </summary>
public static readonly string DisplayName = "Microsoft";
// https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user
/// <summary>
/// The default endpoint used to perform Microsoft account authentication.
/// </summary>
/// <remarks>
/// For more details about this endpoint, see https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user
/// </remarks>
public static readonly string AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
/// <summary>
/// The OAuth endpoint used to exchange access tokens.
/// </summary>
public static readonly string TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
/// <summary>
/// The Microsoft Graph API endpoint that is used to gather additional user information.
/// </summary>
public static readonly string UserInformationEndpoint = "https://graph.microsoft.com/v1.0/me";
}
}

View File

@ -7,18 +7,63 @@ using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods to configure Microsoft Account OAuth authentication.
/// </summary>
public static class MicrosoftAccountExtensions
{
/// <summary>
/// Adds Microsoft Account OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="MicrosoftAccountDefaults.AuthenticationScheme"/>.
/// <para>
/// Microsoft Account authentication allows application users to sign in with their work, school, or personal Microsoft account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder)
=> builder.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, _ => { });
/// <summary>
/// Adds Microsoft Account OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="MicrosoftAccountDefaults.AuthenticationScheme"/>.
/// <para>
/// Microsoft Account authentication allows application users to sign in with their work, school, or personal Microsoft account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="configureOptions">A delegate to configure <see cref="MicrosoftAccountOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder, Action<MicrosoftAccountOptions> configureOptions)
=> builder.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, configureOptions);
/// <summary>
/// Adds Microsoft Account OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="MicrosoftAccountDefaults.AuthenticationScheme"/>.
/// <para>
/// Microsoft Account authentication allows application users to sign in with their work, school, or personal Microsoft account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="configureOptions">A delegate to configure <see cref="MicrosoftAccountOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder, string authenticationScheme, Action<MicrosoftAccountOptions> configureOptions)
=> builder.AddMicrosoftAccount(authenticationScheme, MicrosoftAccountDefaults.DisplayName, configureOptions);
/// <summary>
/// Adds Microsoft Account OAuth-based authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
/// The default scheme is specified by <see cref="MicrosoftAccountDefaults.AuthenticationScheme"/>.
/// <para>
/// Microsoft Account authentication allows application users to sign in with their work, school, or personal Microsoft account.
/// </para>
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <param name="authenticationScheme">The authentication scheme.</param>
/// <param name="displayName">A display name for the authentication handler.</param>
/// <param name="configureOptions">A delegate to configure <see cref="MicrosoftAccountOptions"/>.</param>
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<MicrosoftAccountOptions> configureOptions)
=> builder.AddOAuth<MicrosoftAccountOptions, MicrosoftAccountHandler>(authenticationScheme, displayName, configureOptions);
}
}
}

View File

@ -18,12 +18,20 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
/// <summary>
/// Authentication handler for Microsoft Account based authentication.
/// </summary>
public class MicrosoftAccountHandler : OAuthHandler<MicrosoftAccountOptions>
{
/// <summary>
/// Initializes a new instance of <see cref="MicrosoftAccountHandler"/>.
/// </summary>
/// <inheritdoc />
public MicrosoftAccountHandler(IOptionsMonitor<MicrosoftAccountOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
/// <inheritdoc />
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
@ -44,6 +52,7 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
}
}
/// <inheritdoc />
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{
var queryStrings = new Dictionary<string, string>

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.OAuth;
namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
/// <summary>
/// <see cref="AuthenticationProperties"/> for Microsoft OAuth challenge request.
/// See https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-authorization-code for reference
/// </summary>
public class MicrosoftChallengeProperties : OAuthChallengeProperties
@ -28,19 +29,31 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
/// </summary>
public static readonly string PromptKey = "prompt";
/// <summary>
/// Initializes a new instance for <see cref="MicrosoftChallengeProperties"/>.
/// </summary>
public MicrosoftChallengeProperties()
{ }
/// <summary>
/// Initializes a new instance for <see cref="MicrosoftChallengeProperties"/>.
/// </summary>
/// <inheritdoc />
public MicrosoftChallengeProperties(IDictionary<string, string> items)
: base(items)
{ }
/// <summary>
/// Initializes a new instance for <see cref="MicrosoftChallengeProperties"/>.
/// </summary>
/// <inheritdoc />
public MicrosoftChallengeProperties(IDictionary<string, string> items, IDictionary<string, object> parameters)
: base(items, parameters)
{ }
/// <summary>
/// The "response_mode" parameter value being used for a challenge request.
/// Gets or sets the value for the <c>response_mode</c> parameter used for a challenge request. The response mode specifies the method
/// that should be used to send the resulting token back to the app. Can be one of the following: <c>query</c>, <c>fragment</c>, <c>form_post</c>.
/// </summary>
public string ResponseMode
{
@ -49,7 +62,11 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
}
/// <summary>
/// The "domain_hint" parameter value being used for a challenge request.
/// Gets or sets the value for the "domain_hint" parameter value being used for a challenge request.
/// <para>
/// If included, authentication will skip the email-based discovery process that user goes through on the sign-in page,
/// leading to a slightly more streamlined user experience.
/// </para>
/// </summary>
public string DomainHint
{
@ -58,7 +75,10 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
}
/// <summary>
/// The "login_hint" parameter value being used for a challenge request.
/// Gets or sets the value for the "login_hint" parameter value being used for a challenge request.
/// <para>
/// Can be used to pre-fill the username/email address field of the sign-in page for the user, if their username is known ahead of time.
/// </para>
/// </summary>
public string LoginHint
{
@ -67,7 +87,10 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
}
/// <summary>
/// The "prompt" parameter value being used for a challenge request.
/// Gets or sets the value for the "prompt" parameter value being used for a challenge request.
/// <para>
/// Indicates the type of user interaction that is required. The only valid values at this time are login, none, and consent.
/// </para>
/// </summary>
public string Prompt
{

View File

@ -57,6 +57,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
}
}
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(Handler)} assertion should evaluate to true.";

View File

@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// Used for building policies during application startup.
/// Used for building policies.
/// </summary>
public class AuthorizationPolicyBuilder
{
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Authorization
/// <summary>
/// Creates a new instance of <see cref="AuthorizationPolicyBuilder"/>.
/// </summary>
/// <param name="policy">The <see cref="AuthorizationPolicy"/> to build.</param>
/// <param name="policy">The <see cref="AuthorizationPolicy"/> to copy.</param>
public AuthorizationPolicyBuilder(AuthorizationPolicy policy)
{
Combine(policy);
@ -41,6 +41,9 @@ namespace Microsoft.AspNetCore.Authorization
/// <summary>
/// Gets or sets a list authentication schemes the <see cref="AuthorizationPolicyBuilder.Requirements"/>
/// are evaluated against.
/// <para>
/// When not specified, the requirements are evaluated against default schemes.
/// </para>
/// </summary>
public IList<string> AuthenticationSchemes { get; set; } = new List<string>();
@ -92,8 +95,8 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="ClaimsAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="ClaimsAuthorizationRequirement"/> to the current instance which requires
/// that the current user has the specified claim and that the claim value must be one of the allowed values.
/// </summary>
/// <param name="claimType">The claim type required.</param>
/// <param name="allowedValues">Values the claim must process one or more of for evaluation to succeed.</param>
@ -109,8 +112,8 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="ClaimsAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="ClaimsAuthorizationRequirement"/> to the current instance which requires
/// that the current user has the specified claim and that the claim value must be one of the allowed values.
/// </summary>
/// <param name="claimType">The claim type required.</param>
/// <param name="allowedValues">Values the claim must process one or more of for evaluation to succeed.</param>
@ -127,8 +130,8 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="ClaimsAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="ClaimsAuthorizationRequirement"/> to the current instance which requires
/// that the current user has the specified claim.
/// </summary>
/// <param name="claimType">The claim type required, with no restrictions on claim value.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
@ -144,8 +147,8 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="RolesAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="RolesAuthorizationRequirement"/> to the current instance which enforces that the current user
/// must have at least one of the specified roles.
/// </summary>
/// <param name="roles">The allowed roles.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
@ -160,8 +163,8 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="RolesAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="RolesAuthorizationRequirement"/> to the current instance which enforces that the current user
/// must have at least one of the specified roles.
/// </summary>
/// <param name="roles">The allowed roles.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
@ -177,8 +180,7 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="NameAuthorizationRequirement"/>
/// to the current instance.
/// Adds a <see cref="NameAuthorizationRequirement"/> to the current instance which enforces that the current user matches the specified name.
/// </summary>
/// <param name="userName">The user name the current user must possess.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
@ -194,7 +196,7 @@ namespace Microsoft.AspNetCore.Authorization
}
/// <summary>
/// Adds a <see cref="DenyAnonymousAuthorizationRequirement"/> to the current instance.
/// Adds <see cref="DenyAnonymousAuthorizationRequirement"/> to the current instance which enforces that the current user is authenticated.
/// </summary>
/// <returns>A reference to this instance after the operation has completed.</returns>
public AuthorizationPolicyBuilder RequireAuthenticatedUser()

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims;
namespace Microsoft.AspNetCore.Authorization
@ -30,8 +29,17 @@ namespace Microsoft.AspNetCore.Authorization
/// <returns>A successful result.</returns>
public static AuthorizationResult Success() => new AuthorizationResult { Succeeded = true };
/// <summary>
/// Creates a failed authorization result.
/// </summary>
/// <param name="failure">Contains information about why authorization failed.</param>
/// <returns>The <see cref="AuthorizationResult"/>.</returns>
public static AuthorizationResult Failed(AuthorizationFailure failure) => new AuthorizationResult { Failure = failure };
/// <summary>
/// Creates a failed authorization result.
/// </summary>
/// <returns>The <see cref="AuthorizationResult"/>.</returns>
public static AuthorizationResult Failed() => new AuthorizationResult { Failure = AuthorizationFailure.ExplicitFail() };
}

View File

@ -71,6 +71,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
return Task.CompletedTask;
}
/// <inheritdoc />
public override string ToString()
{
var value = (AllowedValues == null || !AllowedValues.Any())

View File

@ -29,6 +29,7 @@ namespace Microsoft.AspNetCore.Authorization
_handlers = handlers;
}
/// <inheritdoc />
public Task<IEnumerable<IAuthorizationHandler>> GetHandlersAsync(AuthorizationHandlerContext context)
=> Task.FromResult(_handlers);
}

View File

@ -30,6 +30,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
return Task.CompletedTask;
}
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(DenyAnonymousAuthorizationRequirement)}: Requires an authenticated user.";

View File

@ -8,7 +8,7 @@ Microsoft.AspNetCore.Authorization.AuthorizeAttribute</Description>
<TargetFrameworks>$(DefaultNetFxTargetFramework);netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authorization</PackageTags>
<Nullable>enable</Nullable>

View File

@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
return Task.CompletedTask;
}
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(NameAuthorizationRequirement)}:Requires a user identity with Name equal to {RequiredName}";

View File

@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
/// </summary>
public string Name { get; set; } = default!;
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(OperationAuthorizationRequirement)}:Name={Name}";

View File

@ -64,6 +64,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure
return Task.CompletedTask;
}
/// <inheritdoc />
public override string ToString()
{
var roles = $"User.IsInRole must be true for one of the following roles: ({string.Join("|", AllowedRoles)})";

View File

@ -15,9 +15,13 @@ namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Adds the <see cref="AuthorizationMiddleware"/> to the specified <see cref="IApplicationBuilder"/>, which enables authorization capabilities.
/// <para>
/// When authorizing a resource that is routed using endpoint routing, this call must appear between the calls to
/// <c>app.UseRouting()</c> and <c>app.UseEndpoints(...)</c> for the middleware to function correctly.
/// </para>
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <returns>A reference to <paramref name="app"/> after the operation has completed.</returns>
public static IApplicationBuilder UseAuthorization(this IApplicationBuilder app)
{
if (app == null)

View File

@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.Builder
/// </summary>
public static class AuthorizationEndpointConventionBuilderExtensions
{
private static readonly IAllowAnonymous _allowAnonymousMetadata = new AllowAnonymousAttribute();
/// <summary>
@ -97,7 +96,6 @@ namespace Microsoft.AspNetCore.Builder
return builder;
}
private static void RequireAuthorizationCore<TBuilder>(TBuilder builder, IEnumerable<IAuthorizeData> authorizeData)
where TBuilder : IEndpointConventionBuilder
{

View File

@ -9,6 +9,9 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// A middleware that enables authorization capabilities.
/// </summary>
public class AuthorizationMiddleware
{
// AppContext switch used to control whether HttpContext or endpoint is passed as a resource to AuthZ
@ -21,12 +24,21 @@ namespace Microsoft.AspNetCore.Authorization
private readonly RequestDelegate _next;
private readonly IAuthorizationPolicyProvider _policyProvider;
/// <summary>
/// Initializes a new instance of <see cref="AuthorizationMiddleware"/>.
/// </summary>
/// <param name="next">The next middleware in the application middleware pipeline.</param>
/// <param name="policyProvider">The <see cref="IAuthorizationPolicyProvider"/>.</param>
public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider));
}
/// <summary>
/// Invokes the middleware performing authorization.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
public async Task Invoke(HttpContext context)
{
if (context == null)

View File

@ -4,8 +4,12 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authorization.Policy
{
/// <summary>
/// Default implementation for <see cref="IAuthorizationMiddlewareResultHandler"/>.
/// </summary>
public class AuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
/// <inheritdoc />
public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
{
if (authorizeResult.Challenged)

View File

@ -4,8 +4,20 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// Allow custom handling of authorization and handling of the authorization response.
/// </summary>
public interface IAuthorizationMiddlewareResultHandler
{
/// <summary>
/// Evaluates the authorization requirement and processes the authorization result.
/// </summary>
/// <param name="next">
/// The next middleware in the application pipeline. Implementations may not invoke this if the authorization did not succeed.
/// </param>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <param name="policy">The <see cref="AuthorizationPolicy"/> for the resource.</param>
/// <param name="authorizeResult">The result of authorization.</param>
Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult);
}
}

View File

@ -4,7 +4,7 @@
<Description>ASP.NET Core authorization policy helper classes.</Description>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authorization</PackageTags>
<IsPackable>false</IsPackable>

View File

@ -3,6 +3,9 @@
namespace Microsoft.AspNetCore.Authorization.Policy
{
/// <summary>
/// The result of <see cref="IPolicyEvaluator.AuthorizeAsync(AuthorizationPolicy, Authentication.AuthenticateResult, Http.HttpContext, object?)"/>.
/// </summary>
public class PolicyAuthorizationResult
{
private PolicyAuthorizationResult() { }
@ -27,15 +30,32 @@ namespace Microsoft.AspNetCore.Authorization.Policy
/// </summary>
public AuthorizationFailure? AuthorizationFailure { get; private set; }
/// <summary>
///Indicates that an unauthenticated user requested access to an endpoint that requires authentication.
/// </summary>
/// <returns>The <see cref="PolicyAuthorizationResult"/>.</returns>
public static PolicyAuthorizationResult Challenge()
=> new PolicyAuthorizationResult { Challenged = true };
/// <summary>
/// Indiciates that the access to a resource was forbidden.
/// </summary>
/// <returns>The <see cref="PolicyAuthorizationResult"/>.</returns>
public static PolicyAuthorizationResult Forbid()
=> Forbid(null);
/// <summary>
/// Indiciates that the access to a resource was forbidden.
/// </summary>
/// <param name="authorizationFailure">Specifies the reason the authorization failed.s</param>
/// <returns>The <see cref="PolicyAuthorizationResult"/>.</returns>
public static PolicyAuthorizationResult Forbid(AuthorizationFailure? authorizationFailure)
=> new PolicyAuthorizationResult { Forbidden = true, AuthorizationFailure = authorizationFailure };
/// <summary>
/// Indicates a successful authorization.
/// </summary>
/// <returns>The <see cref="PolicyAuthorizationResult"/>.</returns>
public static PolicyAuthorizationResult Success()
=> new PolicyAuthorizationResult { Succeeded = true };

View File

@ -10,6 +10,9 @@ using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Authorization.Policy
{
/// <summary>
/// Default implementation for <see cref="IPolicyEvaluator"/>.
/// </summary>
public class PolicyEvaluator : IPolicyEvaluator
{
private readonly IAuthorizationService _authorization;

View File

@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
public static class PolicyServiceCollectionExtensions
{
/// <summary>
/// Adds the authorization policy evaluator service to the specified <see cref="IServiceCollection" />.
/// Adds the authorization policy evaluator service to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>