From 9d26c4e70f87f134879bb11142b5a845ac32b8c3 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 21 Mar 2017 13:16:02 -0700 Subject: [PATCH 01/16] Auth 2.0: Add Auth Abstractions, Core --- .../AuthenticateContext.cs | 13 ++ .../AuthenticateResult.cs | 90 ++++++++ .../AuthenticationHttpContextExtensions.cs | 58 ++++++ .../AuthenticationOptions.cs | 69 ++++++ .../AuthenticationProperties.cs | 197 ++++++++++++++++++ .../AuthenticationScheme.cs | 34 +++ .../AuthenticationSchemeBuilder.cs | 21 ++ .../AuthenticationTicket.cs | 56 +++++ .../AuthenticationToken.cs | 12 ++ .../BaseAuthenticationContext.cs | 29 +++ .../BaseContext.cs | 33 +++ .../ChallengeBehavior.cs | 12 ++ .../ChallengeContext.cs | 29 +++ .../IAuthenticationFeature.cs | 14 ++ .../IAuthenticationHandler.cs | 20 ++ .../IAuthenticationHandlerProvider.cs | 16 ++ .../IAuthenticationRequestHandler.cs | 18 ++ .../IAuthenticationSchemeProvider.cs | 26 +++ .../IAuthenticationService.cs | 18 ++ .../IClaimsTransformation.cs | 21 ++ .../IDataSerializer.cs | 11 + .../ISecureDataFormat.cs | 13 ++ .../ISystemClock.cs | 19 ++ ...NetCore.Authentication.Abstractions.csproj | 21 ++ .../SignInContext.cs | 20 ++ .../SignOutContext.cs | 15 ++ .../TokenExtensions.cs | 128 ++++++++++++ .../AuthAppBuilderExtensions.cs | 29 +++ ...ticationCoreServiceCollectionExtensions.cs | 51 +++++ .../AuthenticationFeature.cs | 16 ++ .../AuthenticationHandlerProvider.cs | 46 ++++ .../AuthenticationMiddleware.cs | 65 ++++++ .../AuthenticationSchemeProvider.cs | 132 ++++++++++++ .../AuthenticationService.cs | 133 ++++++++++++ ...soft.AspNetCore.Authentication.Core.csproj | 22 ++ .../NoopClaimsTransformation.cs | 19 ++ .../Properties/Resources.Designer.cs | 94 +++++++++ .../Resources.resx | 132 ++++++++++++ .../SystemClock.cs | 27 +++ .../AuthenticationMiddlewareTests.cs | 181 ++++++++++++++++ ...AspNetCore.Authentication.Core.Test.csproj | 20 ++ .../TestExtensions.cs | 86 ++++++++ .../TokenExtensionTests.cs | 181 ++++++++++++++++ .../Transaction.cs | 62 ++++++ 44 files changed, 2309 insertions(+) create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationTicket.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IClaimsTransformation.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/Resources.resx create mode 100644 src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs create mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs new file mode 100644 index 00000000..72321300 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs @@ -0,0 +1,13 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticateContext : BaseAuthenticationContext + { + public AuthenticateContext(HttpContext context, string authenticationScheme) : base(context, authenticationScheme, properties: null) + { } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs new file mode 100644 index 00000000..26ced408 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs @@ -0,0 +1,90 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Contains the result of an Authenticate call + /// + public class AuthenticateResult + { + private AuthenticateResult() { } + + /// + /// If a ticket was produced, authenticate was successful. + /// + public bool Succeeded + { + get + { + return Ticket != null; + } + } + + /// + /// The authentication ticket. + /// + public AuthenticationTicket Ticket { get; private set; } + + // REVIEW: should we also remember AuthenticationScheme? + + /// + /// Gets the claims-principal with authenticated user identities. + /// + public ClaimsPrincipal Principal => Ticket?.Principal; + + /// + /// Additional state values for the authentication session. + /// + public AuthenticationProperties Properties => Ticket?.Properties; + + /// + /// Holds failure information from the authentication. + /// + public Exception Failure { get; private set; } + + /// + /// Indicates that stage of authentication was directly handled by user intervention and no + /// further processing should be attempted. + /// + public bool Handled { get; private set; } + + /// + /// Indicates that there was no information returned for this authentication scheme. + /// + public bool Nothing { get; private set; } + + public static AuthenticateResult Success(AuthenticationTicket ticket) + { + if (ticket == null) + { + throw new ArgumentNullException(nameof(ticket)); + } + return new AuthenticateResult() { Ticket = ticket }; + } + + public static AuthenticateResult Handle() + { + return new AuthenticateResult() { Handled = true }; + } + + public static AuthenticateResult None() + { + return new AuthenticateResult() { Nothing = true }; + } + + public static AuthenticateResult Fail(Exception failure) + { + return new AuthenticateResult() { Failure = failure }; + } + + public static AuthenticateResult Fail(string failureMessage) + { + return new AuthenticateResult() { Failure = new Exception(failureMessage) }; + } + + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs new file mode 100644 index 00000000..44e158c9 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs @@ -0,0 +1,58 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Authentication +{ + public static class AuthenticationHttpContextExtensions + { + public static Task AuthenticateAsync(this HttpContext context) => + context.AuthenticateAsync(scheme: null); + + public static Task AuthenticateAsync(this HttpContext context, string scheme) => + context.RequestServices.GetRequiredService().AuthenticateAsync(context, scheme); + + public static Task ChallengeAsync(this HttpContext context, string scheme) => + context.ChallengeAsync(scheme, properties: null); + + public static Task ChallengeAsync(this HttpContext context) => + context.ChallengeAsync(scheme: null, properties: null); + + public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => + context.ChallengeAsync(scheme, properties: properties, behavior: ChallengeBehavior.Automatic); + + public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior) => + context.RequestServices.GetRequiredService().ChallengeAsync(context, scheme, properties, behavior); + + public static Task ForbidAsync(this HttpContext context, string scheme) => + context.ForbidAsync(scheme, properties: null); + + public static Task ForbidAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => + context.RequestServices.GetRequiredService().ChallengeAsync(context, scheme, properties, ChallengeBehavior.Forbidden); + + public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal) => + context.SignInAsync(scheme, principal, properties: null); + + public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal) => + context.SignInAsync(scheme: null, principal: principal, properties: null); + + public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal, AuthenticationProperties properties) => + context.SignInAsync(scheme: null, principal: principal, properties: properties); + + public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) => + context.RequestServices.GetRequiredService().SignInAsync(context, scheme, principal, properties); + + + public static Task SignOutAsync(this HttpContext context, string scheme) => context.SignOutAsync(scheme, properties: null); + + public static Task SignOutAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => + context.RequestServices.GetRequiredService().SignOutAsync(context, scheme, properties); + + public static Task GetTokenAsync(this HttpContext context, string signInScheme, string tokenName) => + context.RequestServices.GetRequiredService().GetTokenAsync(context, signInScheme, tokenName); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs new file mode 100644 index 00000000..ad757917 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -0,0 +1,69 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationOptions + { + private readonly IList _schemes = new List(); + + /// + /// Returns the schemes in the order they were added (important for request handling priority) + /// + public IEnumerable Schemes + { + get + { + return _schemes; + } + } + + public IDictionary SchemeMap { get; } = new Dictionary(); // case sensitive? + + public void AddScheme(string name, Action configureBuilder) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + if (configureBuilder == null) + { + throw new ArgumentNullException(nameof(configureBuilder)); + } + if (SchemeMap.ContainsKey(name)) + { + throw new InvalidOperationException("Scheme already exists: " + name); + } + + var builder = new AuthenticationSchemeBuilder(name); + configureBuilder(builder); + _schemes.Add(builder); + SchemeMap[name] = builder; + } + + public void ConfigureScheme(string name, Action configureBuilder) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + if (configureBuilder == null) + { + throw new ArgumentNullException(nameof(configureBuilder)); + } + if (!SchemeMap.ContainsKey(name)) + { + throw new InvalidOperationException("Scheme does not exists: " + name); + } + + configureBuilder(SchemeMap[name]); + } + + public string DefaultAuthenticationScheme { get; set; } + public string DefaultSignInScheme { get; set; } + public string DefaultChallengeScheme { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs new file mode 100644 index 00000000..609b6fad --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs @@ -0,0 +1,197 @@ +// 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.Globalization; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Dictionary used to store state values about the authentication session. + /// + public class AuthenticationProperties + { + internal const string IssuedUtcKey = ".issued"; + internal const string ExpiresUtcKey = ".expires"; + internal const string IsPersistentKey = ".persistent"; + internal const string RedirectUriKey = ".redirect"; + internal const string RefreshKey = ".refresh"; + internal const string UtcDateTimeFormat = "r"; + + /// + /// Initializes a new instance of the class + /// + public AuthenticationProperties() + : this(items: null) + { + } + + /// + /// Initializes a new instance of the class + /// + /// + public AuthenticationProperties(IDictionary items) + { + Items = items ?? new Dictionary(StringComparer.Ordinal); + } + + /// + /// State values about the authentication session. + /// + public IDictionary Items { get; } + + /// + /// Gets or sets whether the authentication session is persisted across multiple requests. + /// + public bool IsPersistent + { + get { return Items.ContainsKey(IsPersistentKey); } + set + { + if (Items.ContainsKey(IsPersistentKey)) + { + if (!value) + { + Items.Remove(IsPersistentKey); + } + } + else + { + if (value) + { + Items.Add(IsPersistentKey, string.Empty); + } + } + } + } + + /// + /// Gets or sets the full path or absolute URI to be used as an http redirect response value. + /// + public string RedirectUri + { + get + { + string value; + return Items.TryGetValue(RedirectUriKey, out value) ? value : null; + } + set + { + if (value != null) + { + Items[RedirectUriKey] = value; + } + else + { + if (Items.ContainsKey(RedirectUriKey)) + { + Items.Remove(RedirectUriKey); + } + } + } + } + + /// + /// Gets or sets the time at which the authentication ticket was issued. + /// + public DateTimeOffset? IssuedUtc + { + get + { + string value; + if (Items.TryGetValue(IssuedUtcKey, out value)) + { + DateTimeOffset dateTimeOffset; + if (DateTimeOffset.TryParseExact(value, UtcDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset)) + { + return dateTimeOffset; + } + } + return null; + } + set + { + if (value.HasValue) + { + Items[IssuedUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + } + else + { + if (Items.ContainsKey(IssuedUtcKey)) + { + Items.Remove(IssuedUtcKey); + } + } + } + } + + /// + /// Gets or sets the time at which the authentication ticket expires. + /// + public DateTimeOffset? ExpiresUtc + { + get + { + string value; + if (Items.TryGetValue(ExpiresUtcKey, out value)) + { + DateTimeOffset dateTimeOffset; + if (DateTimeOffset.TryParseExact(value, UtcDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTimeOffset)) + { + return dateTimeOffset; + } + } + return null; + } + set + { + if (value.HasValue) + { + Items[ExpiresUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + } + else + { + if (Items.ContainsKey(ExpiresUtcKey)) + { + Items.Remove(ExpiresUtcKey); + } + } + } + } + + /// + /// Gets or sets if refreshing the authentication session should be allowed. + /// + public bool? AllowRefresh + { + get + { + string value; + if (Items.TryGetValue(RefreshKey, out value)) + { + bool refresh; + if (bool.TryParse(value, out refresh)) + { + return refresh; + } + } + return null; + } + set + { + if (value.HasValue) + { + Items[RefreshKey] = value.Value.ToString(); + } + else + { + if (Items.ContainsKey(RefreshKey)) + { + Items.Remove(RefreshKey); + } + } + } + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs new file mode 100644 index 00000000..afc0cb68 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs @@ -0,0 +1,34 @@ +// 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.Reflection; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationScheme + { + public AuthenticationScheme(string name, Type handlerType) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + if (handlerType == null) + { + throw new ArgumentNullException(nameof(handlerType)); + } + if (!typeof(IAuthenticationHandler).IsAssignableFrom(handlerType)) + { + throw new ArgumentException("handlerType must implement IAuthenticationSchemeHandler."); + } + + Name = name; + HandlerType = handlerType; + } + + // TODO: add display name? + public string Name { get; } + public Type HandlerType { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs new file mode 100644 index 00000000..7787db60 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationSchemeBuilder + { + public AuthenticationSchemeBuilder(string name) + { + Name = name; + } + + public string Name { get; } + + public Type HandlerType { get; set; } + + public AuthenticationScheme Build() => new AuthenticationScheme(Name, HandlerType); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationTicket.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationTicket.cs new file mode 100644 index 00000000..c31f15ec --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationTicket.cs @@ -0,0 +1,56 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Contains user identity information as well as additional authentication state. + /// + public class AuthenticationTicket + { + /// + /// Initializes a new instance of the class + /// + /// the that represents the authenticated user. + /// additional properties that can be consumed by the user or runtime. + /// the authentication middleware that was responsible for this ticket. + public AuthenticationTicket(ClaimsPrincipal principal, AuthenticationProperties properties, string authenticationScheme) + { + if (principal == null) + { + throw new ArgumentNullException(nameof(principal)); + } + + AuthenticationScheme = authenticationScheme; + Principal = principal; + Properties = properties ?? new AuthenticationProperties(); + } + + /// + /// Initializes a new instance of the class + /// + /// the that represents the authenticated user. + /// the authentication middleware that was responsible for this ticket. + public AuthenticationTicket(ClaimsPrincipal principal, string authenticationScheme) + : this(principal, properties: null, authenticationScheme: authenticationScheme) + { } + + /// + /// Gets the authentication type. + /// + public string AuthenticationScheme { get; private set; } + + /// + /// Gets the claims-principal with authenticated user identities. + /// + public ClaimsPrincipal Principal { get; private set; } + + /// + /// Additional state values for the authentication session. + /// + public AuthenticationProperties Properties { get; private set; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs new file mode 100644 index 00000000..6503f0bb --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs @@ -0,0 +1,12 @@ +// 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. + + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationToken + { + public string Name { get; set; } + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs new file mode 100644 index 00000000..0b32cdfa --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public abstract class BaseAuthenticationContext : BaseContext + { + protected BaseAuthenticationContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) : base(context) + { + if (string.IsNullOrEmpty(authenticationScheme)) + { + throw new ArgumentException(nameof(authenticationScheme)); + } + + AuthenticationScheme = authenticationScheme; + Properties = properties ?? new AuthenticationProperties(); + } + + public string AuthenticationScheme { get; } + + /// + /// Contains the extra meta-data arriving with the authentication. May be altered. + /// + public AuthenticationProperties Properties { get; protected set; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs new file mode 100644 index 00000000..26c0ef2f --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs @@ -0,0 +1,33 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public abstract class BaseContext + { + protected BaseContext(HttpContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + HttpContext = context; + } + + public HttpContext HttpContext { get; } + + public HttpRequest Request + { + get { return HttpContext.Request; } + } + + public HttpResponse Response + { + get { return HttpContext.Response; } + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs new file mode 100644 index 00000000..95f9d657 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs @@ -0,0 +1,12 @@ +// 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. + +namespace Microsoft.AspNetCore.Authentication +{ + public enum ChallengeBehavior + { + Automatic, + Unauthorized, + Forbidden + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs new file mode 100644 index 00000000..409a04df --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public class ChallengeContext : BaseAuthenticationContext + { + public ChallengeContext(HttpContext httpContext, string authenticationScheme) + : this(httpContext, authenticationScheme, properties: null, behavior: ChallengeBehavior.Automatic) + { + } + + public ChallengeContext(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) + : base(httpContext, authenticationScheme, properties) + { + if (string.IsNullOrEmpty(authenticationScheme)) + { + throw new ArgumentException(nameof(authenticationScheme)); + } + + Behavior = behavior; + } + + public ChallengeBehavior Behavior { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs new file mode 100644 index 00000000..c2861186 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs @@ -0,0 +1,14 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public interface IAuthenticationFeature + { + PathString OriginalPathBase { get; set; } + + PathString OriginalPath { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs new file mode 100644 index 00000000..d084de70 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + // Created on a per request basis to handle one particular scheme. + public interface IAuthenticationHandler + { + // Gives the handler access to the configuration data + Task InitializeAsync(AuthenticationScheme scheme, HttpContext context); + + Task AuthenticateAsync(AuthenticateContext context); + Task ChallengeAsync(ChallengeContext context); + Task SignInAsync(SignInContext context); + Task SignOutAsync(SignOutContext context); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs new file mode 100644 index 00000000..fdd2df1d --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Provides the appropriate IAuthenticationHandler instance for the authenticationScheme and request. + /// + public interface IAuthenticationHandlerProvider + { + Task GetHandlerAsync(HttpContext context, string authenticationScheme); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs new file mode 100644 index 00000000..aa6595a8 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Authentication +{ + public interface IAuthenticationRequestHandler : IAuthenticationHandler + { + + /// + /// Returns true if request processing should stop. + /// + /// + Task HandleRequestAsync(); + } + +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs new file mode 100644 index 00000000..e3fdfce0 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs @@ -0,0 +1,26 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public interface IAuthenticationSchemeProvider + { + Task> GetAllSchemesAsync(); + Task GetSchemeAsync(string name); + Task GetDefaultAuthenticateSchemeAsync(); + Task GetDefaultChallengeSchemeAsync(); + Task GetDefaultSignInSchemeAsync(); + void AddScheme(AuthenticationScheme scheme); + void RemoveScheme(string name); + + /// + /// Returns the schemes in priority order for request handling. + /// + /// + Task> GetRequestHandlerSchemesAsync(PathString requestPath); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs new file mode 100644 index 00000000..6a537885 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public interface IAuthenticationService + { + Task AuthenticateAsync(HttpContext context, string scheme); + Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior); + Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties); + Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties); + Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IClaimsTransformation.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IClaimsTransformation.cs new file mode 100644 index 00000000..3aed710a --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IClaimsTransformation.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Used by the for claims transformation. + /// + public interface IClaimsTransformation + { + /// + /// Provides a central transformation point to change the specified principal. + /// + /// The to transform. + /// The transformed principal. + Task TransformAsync(ClaimsPrincipal principal); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs new file mode 100644 index 00000000..ad9c5230 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs @@ -0,0 +1,11 @@ +// 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. + +namespace Microsoft.AspNetCore.Authentication +{ + public interface IDataSerializer + { + byte[] Serialize(TModel model); + TModel Deserialize(byte[] data); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs new file mode 100644 index 00000000..73b1b882 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs @@ -0,0 +1,13 @@ +// 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. + +namespace Microsoft.AspNetCore.Authentication +{ + public interface ISecureDataFormat + { + string Protect(TData data); + string Protect(TData data, string purpose); + TData Unprotect(string protectedText); + TData Unprotect(string protectedText, string purpose); + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs new file mode 100644 index 00000000..55826698 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs @@ -0,0 +1,19 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Abstracts the system clock to facilitate testing. + /// + public interface ISystemClock + { + /// + /// Retrieves the current system time in UTC. + /// + DateTimeOffset UtcNow { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj new file mode 100644 index 00000000..6c6c868a --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj @@ -0,0 +1,21 @@ + + + + ASP.NET Core common types used by the various authentication components. + 1.2.0 + net451;netstandard1.3 + $(NoWarn);CS1591 + true + aspnetcore;authentication;security + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs new file mode 100644 index 00000000..baee19ef --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs @@ -0,0 +1,20 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public class SignInContext : BaseAuthenticationContext + { + public SignInContext(HttpContext context, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) + : base(context, authenticationScheme, properties) + { + Principal = principal ?? throw new ArgumentNullException(nameof(principal)); + } + + public ClaimsPrincipal Principal { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs new file mode 100644 index 00000000..a7883d11 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs @@ -0,0 +1,15 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + public class SignOutContext : BaseAuthenticationContext + { + public SignOutContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) + : base(context, authenticationScheme, properties) + { + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs new file mode 100644 index 00000000..9aaee4e2 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs @@ -0,0 +1,128 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + public static class AuthenticationTokenExtensions + { + private static string TokenNamesKey = ".TokenNames"; + private static string TokenKeyPrefix = ".Token."; + + public static void StoreTokens(this AuthenticationProperties properties, IEnumerable tokens) + { + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + if (tokens == null) + { + throw new ArgumentNullException(nameof(tokens)); + } + + // Clear old tokens first + var oldTokens = properties.GetTokens(); + foreach (var t in oldTokens) + { + properties.Items.Remove(TokenKeyPrefix + t.Name); + } + properties.Items.Remove(TokenNamesKey); + + var tokenNames = new List(); + foreach (var token in tokens) + { + // REVIEW: should probably check that there are no ; in the token name and throw or encode + tokenNames.Add(token.Name); + properties.Items[TokenKeyPrefix+token.Name] = token.Value; + } + if (tokenNames.Count > 0) + { + properties.Items[TokenNamesKey] = string.Join(";", tokenNames.ToArray()); + } + } + + public static string GetTokenValue(this AuthenticationProperties properties, string tokenName) + { + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + if (tokenName == null) + { + throw new ArgumentNullException(nameof(tokenName)); + } + + var tokenKey = TokenKeyPrefix + tokenName; + return properties.Items.ContainsKey(tokenKey) + ? properties.Items[tokenKey] + : null; + } + + public static bool UpdateTokenValue(this AuthenticationProperties properties, string tokenName, string tokenValue) + { + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + if (tokenName == null) + { + throw new ArgumentNullException(nameof(tokenName)); + } + + var tokenKey = TokenKeyPrefix + tokenName; + if (!properties.Items.ContainsKey(tokenKey)) + { + return false; + } + properties.Items[tokenKey] = tokenValue; + return true; + } + + public static IEnumerable GetTokens(this AuthenticationProperties properties) + { + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + + var tokens = new List(); + if (properties.Items.ContainsKey(TokenNamesKey)) + { + var tokenNames = properties.Items[TokenNamesKey].Split(';'); + foreach (var name in tokenNames) + { + var token = properties.GetTokenValue(name); + if (token != null) + { + tokens.Add(new AuthenticationToken { Name = name, Value = token }); + } + } + } + + return tokens; + } + + public static async Task GetTokenAsync(this IAuthenticationService auth, HttpContext context, string scheme, string tokenName) + { + if (auth == null) + { + throw new ArgumentNullException(nameof(auth)); + } + if (scheme == null) + { + throw new ArgumentNullException(nameof(scheme)); + } + if (tokenName == null) + { + throw new ArgumentNullException(nameof(tokenName)); + } + + var result = await auth.AuthenticateAsync(context, scheme); + return result?.Properties?.GetTokenValue(tokenName); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs new file mode 100644 index 00000000..eba1ce30 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.AspNetCore.Authentication; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Extension methods to add authentication capabilities to an HTTP application pipeline. + /// + public static class AuthAppBuilderExtensions + { + /// + /// Adds the middleware to the specified , which enables authentication capabilities. + /// + /// The to add the middleware to. + /// A reference to this instance after the operation has completed. + public static IApplicationBuilder UseAuthentication(this IApplicationBuilder app) + { + if (app == null) + { + throw new ArgumentNullException(nameof(app)); + } + + return app.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs new file mode 100644 index 00000000..ec1cea84 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs @@ -0,0 +1,51 @@ +// 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 Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extension methods for setting up authentication services in an . + /// + public static class AuthenticationCoreServiceCollectionExtensions + { + public static IServiceCollection AddAuthentication(this IServiceCollection services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.TryAddSingleton(); + services.AddDataProtection(); + services.AddWebEncoders(); + services.TryAddScoped(); + services.TryAddSingleton(); // Can be replaced with scoped ones that use DbContext + services.TryAddScoped(); + services.TryAddSingleton(); + return services; + } + + public static IServiceCollection AddAuthentication(this IServiceCollection services, Action configureOptions) { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (configureOptions == null) + { + throw new ArgumentNullException(nameof(configureOptions)); + } + + services.AddAuthentication(); + services.Configure(configureOptions); + return services; + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs new file mode 100644 index 00000000..b53ffead --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Used to capture path info so redirects can be computed properly within an app.Map(). + /// + public class AuthenticationFeature : IAuthenticationFeature + { + public PathString OriginalPathBase { get; set; } + public PathString OriginalPath { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs new file mode 100644 index 00000000..408c1b2f --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs @@ -0,0 +1,46 @@ +// 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.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider + { + public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes) + { + Schemes = schemes; + } + + public IAuthenticationSchemeProvider Schemes { get; } + + // handler instance cache, need to initialize once per request + private Dictionary _handlerMap = new Dictionary(); + + public async Task GetHandlerAsync(HttpContext context, string authenticationScheme) + { + if (_handlerMap.ContainsKey(authenticationScheme)) + { + return _handlerMap[authenticationScheme]; + } + + var scheme = await Schemes.GetSchemeAsync(authenticationScheme); + if (scheme == null) + { + return null; + } + var handler = (context.RequestServices.GetService(scheme.HandlerType) ?? + ActivatorUtilities.CreateInstance(context.RequestServices, scheme.HandlerType)) + as IAuthenticationHandler; + if (handler != null) + { + await handler.InitializeAsync(scheme, context); + _handlerMap[authenticationScheme] = handler; + } + return handler; + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs new file mode 100644 index 00000000..3e377d55 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs @@ -0,0 +1,65 @@ +// 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.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationMiddleware + { + private readonly RequestDelegate _next; + + public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes) + { + _next = next ?? throw new ArgumentNullException(nameof(next)); + Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); + } + + public IAuthenticationSchemeProvider Schemes { get; set; } + + public async Task Invoke(HttpContext context) + { + var oldFeature = context.Features.Get(); + try + { + context.Features.Set(new AuthenticationFeature + { + OriginalPath = context.Request.Path, + OriginalPathBase = context.Request.PathBase + }); + + var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); + if (defaultAuthenticate != null) + { + var result = await context.AuthenticateAsync(defaultAuthenticate.Name); + if (result?.Principal != null) + { + context.User = result.Principal; + } + } + + // REVIEW: alternatively could depend on a routing middleware to do this + + // Give any IAuthenticationRequestHandler schemes a chance to handle the request + var handlers = context.RequestServices.GetRequiredService(); + foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync(context.Request.Path)) + { + var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler; + if (handler != null && await handler.HandleRequestAsync()) + { + return; + } + } + + await _next(context); + } + finally + { + context.Features.Set(oldFeature); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs new file mode 100644 index 00000000..cc33fbb1 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -0,0 +1,132 @@ +// 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.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Builds the actual AuthenticationScheme instances from the AuthenticationOptions. + /// + public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider + { + public AuthenticationSchemeProvider(IOptions options) + { + _options = options.Value; + + foreach (var builder in _options.Schemes) + { + var scheme = builder.Build(); + AddScheme(scheme); + } + } + + private readonly AuthenticationOptions _options; + private readonly object _lock = new object(); + + private IDictionary _map = new Dictionary(StringComparer.Ordinal); // case sensitive? + + private List _requestHandlers = new List(); + + public Task GetDefaultAuthenticateSchemeAsync() + { + if (_options.DefaultAuthenticationScheme != null) + { + return GetSchemeAsync(_options.DefaultAuthenticationScheme); + } + if (_map.Count == 1) + { + return Task.FromResult(_map.Values.First()); + } + return Task.FromResult(null); + } + + public Task GetDefaultChallengeSchemeAsync() + { + if (_options.DefaultChallengeScheme != null) + { + return GetSchemeAsync(_options.DefaultChallengeScheme); + } + if (_map.Count == 1) + { + return Task.FromResult(_map.Values.First()); + } + return Task.FromResult(null); + } + + public Task GetDefaultSignInSchemeAsync() + { + if (_options.DefaultSignInScheme != null) + { + return GetSchemeAsync(_options.DefaultSignInScheme); + } + if (_map.Count == 1) + { + return Task.FromResult(_map.Values.First()); + } + return Task.FromResult(null); + } + + public Task GetSchemeAsync(string name) + { + if (_map.ContainsKey(name)) + { + return Task.FromResult(_map[name]); + } + return Task.FromResult(null); + } + + public Task> GetRequestHandlerSchemesAsync(PathString requestPath) + { + return Task.FromResult>(_requestHandlers); + } + + public void AddScheme(AuthenticationScheme scheme) + { + if (_map.ContainsKey(scheme.Name)) + { + throw new InvalidOperationException("Scheme already exists: " + scheme.Name); + } + lock (_lock) + { + if (_map.ContainsKey(scheme.Name)) + { + throw new InvalidOperationException("Scheme already exists: " + scheme.Name); + } + if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) + { + _requestHandlers.Add(scheme); + } + _map[scheme.Name] = scheme; + } + } + + public void RemoveScheme(string name) + { + if (!_map.ContainsKey(name)) + { + return; + } + lock (_lock) + { + if (_map.ContainsKey(name)) + { + var scheme = _map[name]; + _requestHandlers.Remove(_requestHandlers.Where(s => s.Name == name).FirstOrDefault()); + _map.Remove(name); + } + } + } + + public Task> GetAllSchemesAsync() + { + return Task.FromResult>(_map.Values); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs new file mode 100644 index 00000000..ac2819b3 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs @@ -0,0 +1,133 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationService : IAuthenticationService + { + public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform) + { + Schemes = schemes; + Handlers = handlers; + Transform = transform; + } + + public IAuthenticationSchemeProvider Schemes { get; } + + + public IAuthenticationHandlerProvider Handlers { get; } + + public IClaimsTransformation Transform { get; } + + public virtual async Task AuthenticateAsync(HttpContext httpContext, string authenticationScheme) + { + if (authenticationScheme == null) + { + var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); + authenticationScheme = defaultScheme?.Name; + if (authenticationScheme == null) + { + throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); + } + } + + var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + if (handler == null) + { + throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {authenticationScheme}"); + } + + var context = new AuthenticateContext(httpContext, authenticationScheme); + var result = await handler.AuthenticateAsync(context); + if (result.Succeeded) + { + var transformed = await Transform.TransformAsync(result.Principal); + return AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme)); + } + return result; + } + + public virtual async Task ChallengeAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) + { + if (authenticationScheme == null) + { + var defaultChallengeScheme = await Schemes.GetDefaultChallengeSchemeAsync(); + authenticationScheme = defaultChallengeScheme?.Name; + if (authenticationScheme == null) + { + throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultChallengeScheme found."); + } + } + + var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + if (handler == null) + { + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + } + + var challengeContext = new ChallengeContext(httpContext, authenticationScheme, properties, behavior); + await handler.ChallengeAsync(challengeContext); + } + + public virtual async Task SignInAsync(HttpContext httpContext, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) + { + if (principal == null) + { + throw new ArgumentNullException(nameof(principal)); + } + + if (authenticationScheme == null) + { + var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync(); + authenticationScheme = defaultScheme?.Name; + if (authenticationScheme == null) + { + throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); + } + } + + var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + if (handler == null) + { + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + } + + var signInContext = new SignInContext(httpContext, authenticationScheme, principal, properties); + await handler.SignInAsync(signInContext); + } + + public virtual async Task SignOutAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties) + { + if (string.IsNullOrEmpty(authenticationScheme)) + { + throw new ArgumentException(nameof(authenticationScheme)); + } + + var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + if (handler == null) + { + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + } + + var signOutContext = new SignOutContext(httpContext, authenticationScheme, properties); + await handler.SignOutAsync(signOutContext); + } + + // Deny access (typically a 403) + public virtual Task ForbidAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties) + { + if (authenticationScheme == null) + { + throw new ArgumentNullException(nameof(authenticationScheme)); + } + + return ChallengeAsync(httpContext, authenticationScheme, properties, ChallengeBehavior.Forbidden); + } + + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj new file mode 100644 index 00000000..2e41c797 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -0,0 +1,22 @@ + + + + + + ASP.NET Core common types used by the various authentication middleware components. + 1.2.0 + net451;netstandard1.3 + $(NoWarn);CS1591 + true + aspnetcore;authentication;security + + + + + + + + + + + diff --git a/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs b/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs new file mode 100644 index 00000000..c9d87d7c --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Default claims transformation is a no-op. + /// + public class NoopClaimsTransformation : IClaimsTransformation + { + public virtual Task TransformAsync(ClaimsPrincipal principal) + { + return Task.FromResult(principal); + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs new file mode 100644 index 00000000..11e2e458 --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs @@ -0,0 +1,94 @@ +// +namespace Microsoft.AspNetCore.Authentication +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.Authentication.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// The default data protection provider may only be used when the IApplicationBuilder.Properties contains an appropriate 'host.AppName' key. + /// + internal static string Exception_DefaultDpapiRequiresAppNameKey + { + get { return GetString("Exception_DefaultDpapiRequiresAppNameKey"); } + } + + /// + /// The default data protection provider may only be used when the IApplicationBuilder.Properties contains an appropriate 'host.AppName' key. + /// + internal static string FormatException_DefaultDpapiRequiresAppNameKey() + { + return GetString("Exception_DefaultDpapiRequiresAppNameKey"); + } + + /// + /// The state passed to UnhookAuthentication may only be the return value from HookAuthentication. + /// + internal static string Exception_UnhookAuthenticationStateType + { + get { return GetString("Exception_UnhookAuthenticationStateType"); } + } + + /// + /// The state passed to UnhookAuthentication may only be the return value from HookAuthentication. + /// + internal static string FormatException_UnhookAuthenticationStateType() + { + return GetString("Exception_UnhookAuthenticationStateType"); + } + + /// + /// The AuthenticationTokenProvider's required synchronous events have not been registered. + /// + internal static string Exception_AuthenticationTokenDoesNotProvideSyncMethods + { + get { return GetString("Exception_AuthenticationTokenDoesNotProvideSyncMethods"); } + } + + /// + /// The AuthenticationTokenProvider's required synchronous events have not been registered. + /// + internal static string FormatException_AuthenticationTokenDoesNotProvideSyncMethods() + { + return GetString("Exception_AuthenticationTokenDoesNotProvideSyncMethods"); + } + + /// + /// The '{0}' option must be provided. + /// + internal static string Exception_OptionMustBeProvided + { + get { return GetString("Exception_OptionMustBeProvided"); } + } + + /// + /// The '{0}' option must be provided. + /// + internal static string FormatException_OptionMustBeProvided(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Exception_OptionMustBeProvided"), p0); + } + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx new file mode 100644 index 00000000..54d22bcc --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The default data protection provider may only be used when the IApplicationBuilder.Properties contains an appropriate 'host.AppName' key. + + + The state passed to UnhookAuthentication may only be the return value from HookAuthentication. + + + The AuthenticationTokenProvider's required synchronous events have not been registered. + + + The '{0}' option must be provided. + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs b/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs new file mode 100644 index 00000000..2320982c --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs @@ -0,0 +1,27 @@ +// 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; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Provides access to the normal system clock with precision in seconds. + /// + public class SystemClock : ISystemClock + { + /// + /// Retrieves the current system time in UTC. + /// + public DateTimeOffset UtcNow + { + get + { + // the clock measures whole seconds only, to have integral expires_in results, and + // because milliseconds do not round-trip serialization formats + var utcNowPrecisionSeconds = new DateTime((DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond, DateTimeKind.Utc); + return new DateTimeOffset(utcNowPrecisionSeconds); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs new file mode 100644 index 00000000..9220be05 --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs @@ -0,0 +1,181 @@ +// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information. + +using System; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.AspNetCore.Authentication +{ + public class AuthenticationMiddlewareTests + { + [Fact] + public async Task OnlyInvokesCanHandleRequestHandlers() + { + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseAuthentication(); + }) + .ConfigureServices(services => services.AddAuthentication(o => + { + o.AddScheme("Skip", s => + { + s.HandlerType = typeof(SkipHandler); + }); + // Won't get hit since CanHandleRequests is false + o.AddScheme("throws", s => + { + s.HandlerType = typeof(ThrowsHandler); + }); + o.AddScheme("607", s => + { + s.HandlerType = typeof(SixOhSevenHandler); + }); + // Won't get run since 607 will finish + o.AddScheme("305", s => + { + s.HandlerType = typeof(ThreeOhFiveHandler); + }); + })); + var server = new TestServer(builder); + var response = await server.CreateClient().GetAsync("http://example.com/"); + Assert.Equal(607, (int)response.StatusCode); + } + + private class ThreeOhFiveHandler : StatusCodeHandler { + public ThreeOhFiveHandler() : base(305) { } + } + + private class SixOhSevenHandler : StatusCodeHandler + { + public SixOhSevenHandler() : base(607) { } + } + + private class SevenOhSevenHandler : StatusCodeHandler + { + public SevenOhSevenHandler() : base(707) { } + } + + private class StatusCodeHandler : IAuthenticationRequestHandler + { + private HttpContext _context; + private int _code; + + public StatusCodeHandler(int code) + { + _code = code; + } + + public Task AuthenticateAsync(AuthenticateContext context) + { + throw new NotImplementedException(); + } + + public Task ChallengeAsync(ChallengeContext context) + { + throw new NotImplementedException(); + } + + public Task HandleRequestAsync() + { + _context.Response.StatusCode = _code; + return Task.FromResult(true); + } + + public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) + { + _context = context; + return Task.FromResult(0); + } + + public Task SignInAsync(SignInContext context) + { + throw new NotImplementedException(); + } + + public Task SignOutAsync(SignOutContext context) + { + throw new NotImplementedException(); + } + } + + private class ThrowsHandler : IAuthenticationHandler + { + private HttpContext _context; + + public Task AuthenticateAsync(AuthenticateContext context) + { + throw new NotImplementedException(); + } + + public Task ChallengeAsync(ChallengeContext context) + { + throw new NotImplementedException(); + } + + public Task HandleRequestAsync() + { + throw new NotImplementedException(); + } + + public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) + { + _context = context; + return Task.FromResult(0); + } + + public Task SignInAsync(SignInContext context) + { + throw new NotImplementedException(); + } + + public Task SignOutAsync(SignOutContext context) + { + throw new NotImplementedException(); + } + } + + private class SkipHandler : IAuthenticationRequestHandler + { + private HttpContext _context; + + public Task AuthenticateAsync(AuthenticateContext context) + { + throw new NotImplementedException(); + } + + public Task ChallengeAsync(ChallengeContext context) + { + throw new NotImplementedException(); + } + + public Task HandleRequestAsync() + { + return Task.FromResult(false); + } + + public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) + { + _context = context; + return Task.FromResult(0); + } + + public Task SignInAsync(SignInContext context) + { + throw new NotImplementedException(); + } + + public Task SignOutAsync(SignOutContext context) + { + throw new NotImplementedException(); + } + } + + } +} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj new file mode 100644 index 00000000..3f8bbca6 --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj @@ -0,0 +1,20 @@ + + + + + netcoreapp1.1;net452 + netcoreapp1.1 + + + + + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs new file mode 100644 index 00000000..87d6d95a --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs @@ -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.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; + +namespace Microsoft.AspNetCore.Authentication +{ + public static class TestExtensions + { + public const string CookieAuthenticationScheme = "External"; + + public static async Task SendAsync(this TestServer server, string uri, string cookieHeader = null) + { + var request = new HttpRequestMessage(HttpMethod.Get, uri); + if (!string.IsNullOrEmpty(cookieHeader)) + { + request.Headers.Add("Cookie", cookieHeader); + } + var transaction = new Transaction + { + Request = request, + Response = await server.CreateClient().SendAsync(request), + }; + if (transaction.Response.Headers.Contains("Set-Cookie")) + { + transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList(); + } + transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync(); + + if (transaction.Response.Content != null && + transaction.Response.Content.Headers.ContentType != null && + transaction.Response.Content.Headers.ContentType.MediaType == "text/xml") + { + transaction.ResponseElement = XElement.Parse(transaction.ResponseText); + } + return transaction; + } + + public static void Describe(this HttpResponse res, ClaimsPrincipal principal) + { + res.StatusCode = 200; + res.ContentType = "text/xml"; + var xml = new XElement("xml"); + if (principal != null) + { + foreach (var identity in principal.Identities) + { + xml.Add(identity.Claims.Select(claim => + new XElement("claim", new XAttribute("type", claim.Type), + new XAttribute("value", claim.Value), + new XAttribute("issuer", claim.Issuer)))); + } + } + var xmlBytes = Encoding.UTF8.GetBytes(xml.ToString()); + res.Body.Write(xmlBytes, 0, xmlBytes.Length); + } + + public static void Describe(this HttpResponse res, IEnumerable tokens) + { + res.StatusCode = 200; + res.ContentType = "text/xml"; + var xml = new XElement("xml"); + if (tokens != null) + { + foreach (var token in tokens) + { + xml.Add(new XElement("token", new XAttribute("name", token.Name), + new XAttribute("value", token.Value))); + } + } + var xmlBytes = Encoding.UTF8.GetBytes(xml.ToString()); + res.Body.Write(xmlBytes, 0, xmlBytes.Length); + } + + } +} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs new file mode 100644 index 00000000..fb7ea344 --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs @@ -0,0 +1,181 @@ +// 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.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.Authentication +{ + public class TokenExtensionTests + { + [Fact] + public void CanStoreMultipleTokens() + { + var props = new AuthenticationProperties(); + var tokens = new List(); + var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + tokens.Add(tok1); + tokens.Add(tok2); + tokens.Add(tok3); + props.StoreTokens(tokens); + + Assert.Equal("1", props.GetTokenValue("One")); + Assert.Equal("2", props.GetTokenValue("Two")); + Assert.Equal("3", props.GetTokenValue("Three")); + Assert.Equal(3, props.GetTokens().Count()); + } + + [Fact] + public void SubsequentStoreTokenDeletesPreviousTokens() + { + var props = new AuthenticationProperties(); + var tokens = new List(); + var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + tokens.Add(tok1); + tokens.Add(tok2); + tokens.Add(tok3); + + props.StoreTokens(tokens); + + props.StoreTokens(new[] { new AuthenticationToken { Name = "Zero", Value = "0" } }); + + Assert.Equal("0", props.GetTokenValue("Zero")); + Assert.Equal(null, props.GetTokenValue("One")); + Assert.Equal(null, props.GetTokenValue("Two")); + Assert.Equal(null, props.GetTokenValue("Three")); + Assert.Equal(1, props.GetTokens().Count()); + } + + [Fact] + public void CanUpdateTokens() + { + var props = new AuthenticationProperties(); + var tokens = new List(); + var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + tokens.Add(tok1); + tokens.Add(tok2); + tokens.Add(tok3); + props.StoreTokens(tokens); + + tok1.Value = ".1"; + tok2.Value = ".2"; + tok3.Value = ".3"; + props.StoreTokens(tokens); + + Assert.Equal(".1", props.GetTokenValue("One")); + Assert.Equal(".2", props.GetTokenValue("Two")); + Assert.Equal(".3", props.GetTokenValue("Three")); + Assert.Equal(3, props.GetTokens().Count()); + } + + [Fact] + public void CanUpdateTokenValues() + { + var props = new AuthenticationProperties(); + var tokens = new List(); + var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + tokens.Add(tok1); + tokens.Add(tok2); + tokens.Add(tok3); + props.StoreTokens(tokens); + + Assert.True(props.UpdateTokenValue("One", ".11")); + Assert.True(props.UpdateTokenValue("Two", ".22")); + Assert.True(props.UpdateTokenValue("Three", ".33")); + + Assert.Equal(".11", props.GetTokenValue("One")); + Assert.Equal(".22", props.GetTokenValue("Two")); + Assert.Equal(".33", props.GetTokenValue("Three")); + Assert.Equal(3, props.GetTokens().Count()); + } + + [Fact] + public void UpdateTokenValueReturnsFalseForUnknownToken() + { + var props = new AuthenticationProperties(); + var tokens = new List(); + var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + tokens.Add(tok1); + tokens.Add(tok2); + tokens.Add(tok3); + props.StoreTokens(tokens); + + Assert.False(props.UpdateTokenValue("ONE", ".11")); + Assert.False(props.UpdateTokenValue("Jigglypuff", ".11")); + + Assert.Null(props.GetTokenValue("ONE")); + Assert.Null(props.GetTokenValue("Jigglypuff")); + Assert.Equal(3, props.GetTokens().Count()); + + } + + //public class TestAuthHandler : IAuthenticationHandler + //{ + // private readonly AuthenticationProperties _props; + // public TestAuthHandler(AuthenticationProperties props) + // { + // _props = props; + // } + + // public Task AuthenticateAsync(AuthenticateContext context) + // { + // context.Authenticated(new ClaimsPrincipal(), _props.Items, new Dictionary()); + // return Task.FromResult(0); + // } + + // public Task ChallengeAsync(ChallengeContext context) + // { + // throw new NotImplementedException(); + // } + + // public void GetDescriptions(DescribeSchemesContext context) + // { + // throw new NotImplementedException(); + // } + + // public Task SignInAsync(SignInContext context) + // { + // throw new NotImplementedException(); + // } + + // public Task SignOutAsync(SignOutContext context) + // { + // throw new NotImplementedException(); + // } + //} + + //[Fact] + //public async Task CanGetTokenFromContext() + //{ + // var props = new AuthenticationProperties(); + // var tokens = new List(); + // var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; + // var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; + // var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; + // tokens.Add(tok1); + // tokens.Add(tok2); + // tokens.Add(tok3); + // props.StoreTokens(tokens); + + // var context = new DefaultHttpContext(); + // var handler = new TestAuthHandler(props); + // context.Features.Set(new HttpAuthenticationFeature() { Handler = handler }); + + // Assert.Equal("1", await context.GetTokenAsync("One")); + // Assert.Equal("2", await context.GetTokenAsync("Two")); + // Assert.Equal("3", await context.GetTokenAsync("Three")); + //} + + } +} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs new file mode 100644 index 00000000..f7128a6f --- /dev/null +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs @@ -0,0 +1,62 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Xml.Linq; + +namespace Microsoft.AspNetCore.Authentication +{ + public class Transaction + { + public HttpRequestMessage Request { get; set; } + public HttpResponseMessage Response { get; set; } + + public IList SetCookie { get; set; } + + public string ResponseText { get; set; } + public XElement ResponseElement { get; set; } + + public string AuthenticationCookieValue + { + get + { + if (SetCookie != null && SetCookie.Count > 0) + { + var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme + "=")); + if (authCookie != null) + { + return authCookie.Substring(0, authCookie.IndexOf(';')); + } + } + + return null; + } + } + + public string FindClaimValue(string claimType, string issuer = null) + { + var claim = ResponseElement.Elements("claim") + .SingleOrDefault(elt => elt.Attribute("type").Value == claimType && + (issuer == null || elt.Attribute("issuer").Value == issuer)); + if (claim == null) + { + return null; + } + return claim.Attribute("value").Value; + } + + public string FindTokenValue(string name) + { + var claim = ResponseElement.Elements("token") + .SingleOrDefault(elt => elt.Attribute("name").Value == name); + if (claim == null) + { + return null; + } + return claim.Attribute("value").Value; + } + + } +} From ea970a37314b763bdeb8f114e1f8c6571d526236 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 21 Mar 2017 13:22:36 -0700 Subject: [PATCH 02/16] Add auth to sln --- HttpAbstractions.sln | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/HttpAbstractions.sln b/HttpAbstractions.sln index 9525343a..6434e357 100644 --- a/HttpAbstractions.sln +++ b/HttpAbstractions.sln @@ -57,6 +57,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{ED7BCAC5 build\Key.snk = build\Key.snk EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Abstractions", "src\Microsoft.AspNetCore.Authentication.Abstractions\Microsoft.AspNetCore.Authentication.Abstractions.csproj", "{3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Core", "src\Microsoft.AspNetCore.Authentication.Core\Microsoft.AspNetCore.Authentication.Core.csproj", "{73CA3145-91BD-4DA5-BC74-40008DE7EA98}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Core.Test", "test\Microsoft.AspNetCore.Authentication.Core.Test\Microsoft.AspNetCore.Authentication.Core.Test.csproj", "{A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -223,6 +229,42 @@ Global {1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.ActiveCfg = Release|Any CPU {1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.Build.0 = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|x86.ActiveCfg = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Debug|x86.Build.0 = Debug|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|Any CPU.Build.0 = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|x86.ActiveCfg = Release|Any CPU + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852}.Release|x86.Build.0 = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|x86.ActiveCfg = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Debug|x86.Build.0 = Debug|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|Any CPU.Build.0 = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|x86.ActiveCfg = Release|Any CPU + {73CA3145-91BD-4DA5-BC74-40008DE7EA98}.Release|x86.Build.0 = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|x86.ActiveCfg = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Debug|x86.Build.0 = Debug|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|Any CPU.Build.0 = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|x86.ActiveCfg = Release|Any CPU + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -244,5 +286,8 @@ Global {E6BB7AD1-BD10-4A23-B780-F4A86ADF00D1} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} {1D0764B4-1DEB-4232-A714-D4B7E846918A} = {982F09D8-621E-4872-BA7B-BBDEA47D1EFD} {ED7BCAC5-2796-44BD-9954-7C248263BC8B} = {C6C48D5F-B289-4150-A6FC-77A5C7064BCE} + {3D8C9A87-5DFB-4EC0-9CB6-174AD3B33852} = {A5A15F1C-885A-452A-A731-B0173DDBD913} + {73CA3145-91BD-4DA5-BC74-40008DE7EA98} = {A5A15F1C-885A-452A-A731-B0173DDBD913} + {A85950C5-2794-47E2-8EAA-05A1DC7C6DA7} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} EndGlobalSection EndGlobal From f87c88b9428e7472ebb2c2eb24c3b4921babed64 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Tue, 21 Mar 2017 13:26:31 -0700 Subject: [PATCH 03/16] Cleanup --- .../ChallengeContext.cs | 4 +--- .../SignInContext.cs | 6 +++++- .../SignOutContext.cs | 3 +-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs index 409a04df..d5f63ce3 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs @@ -10,8 +10,7 @@ public class ChallengeContext : BaseAuthenticationContext { public ChallengeContext(HttpContext httpContext, string authenticationScheme) : this(httpContext, authenticationScheme, properties: null, behavior: ChallengeBehavior.Automatic) - { - } + { } public ChallengeContext(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) : base(httpContext, authenticationScheme, properties) @@ -20,7 +19,6 @@ public ChallengeContext(HttpContext httpContext, string authenticationScheme, Au { throw new ArgumentException(nameof(authenticationScheme)); } - Behavior = behavior; } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs index baee19ef..f080de43 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs @@ -12,7 +12,11 @@ public class SignInContext : BaseAuthenticationContext public SignInContext(HttpContext context, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) : base(context, authenticationScheme, properties) { - Principal = principal ?? throw new ArgumentNullException(nameof(principal)); + if (principal == null) + { + throw new ArgumentNullException(nameof(principal)); + } + Principal = principal; } public ClaimsPrincipal Principal { get; } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs index a7883d11..c4a6f139 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs @@ -9,7 +9,6 @@ public class SignOutContext : BaseAuthenticationContext { public SignOutContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) : base(context, authenticationScheme, properties) - { - } + { } } } \ No newline at end of file From 027b65c9605f33e1a54f9eb81023dfb08320d351 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 23 Mar 2017 10:48:13 -0700 Subject: [PATCH 04/16] Move data back to security auth --- .../IDataSerializer.cs | 11 -------- .../ISecureDataFormat.cs | 13 --------- .../ISystemClock.cs | 19 ------------- ...NetCore.Authentication.Abstractions.csproj | 1 - ...ticationCoreServiceCollectionExtensions.cs | 9 +++---- ...soft.AspNetCore.Authentication.Core.csproj | 4 +-- .../SystemClock.cs | 27 ------------------- 7 files changed, 5 insertions(+), 79 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs delete mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs delete mode 100644 src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs delete mode 100644 src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs deleted file mode 100644 index ad9c5230..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IDataSerializer.cs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -namespace Microsoft.AspNetCore.Authentication -{ - public interface IDataSerializer - { - byte[] Serialize(TModel model); - TModel Deserialize(byte[] data); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs deleted file mode 100644 index 73b1b882..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISecureDataFormat.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -namespace Microsoft.AspNetCore.Authentication -{ - public interface ISecureDataFormat - { - string Protect(TData data); - string Protect(TData data, string purpose); - TData Unprotect(string protectedText); - TData Unprotect(string protectedText, string purpose); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs deleted file mode 100644 index 55826698..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/ISystemClock.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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; - -namespace Microsoft.AspNetCore.Authentication -{ - /// - /// Abstracts the system clock to facilitate testing. - /// - public interface ISystemClock - { - /// - /// Retrieves the current system time in UTC. - /// - DateTimeOffset UtcNow { get; } - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj index 6c6c868a..23ea6be8 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj @@ -9,7 +9,6 @@ aspnetcore;authentication;security - diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs index ec1cea84..d95ec425 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs @@ -15,16 +15,13 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class AuthenticationCoreServiceCollectionExtensions { - public static IServiceCollection AddAuthentication(this IServiceCollection services) + public static IServiceCollection AddAuthenticationCore(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } - services.TryAddSingleton(); - services.AddDataProtection(); - services.AddWebEncoders(); services.TryAddScoped(); services.TryAddSingleton(); // Can be replaced with scoped ones that use DbContext services.TryAddScoped(); @@ -32,7 +29,7 @@ public static IServiceCollection AddAuthentication(this IServiceCollection servi return services; } - public static IServiceCollection AddAuthentication(this IServiceCollection services, Action configureOptions) { + public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action configureOptions) { if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -43,7 +40,7 @@ public static IServiceCollection AddAuthentication(this IServiceCollection servi throw new ArgumentNullException(nameof(configureOptions)); } - services.AddAuthentication(); + services.AddAuthenticationCore(); services.Configure(configureOptions); return services; } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj index 2e41c797..0e8e647f 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs b/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs deleted file mode 100644 index 2320982c..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Core/SystemClock.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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; - -namespace Microsoft.AspNetCore.Authentication -{ - /// - /// Provides access to the normal system clock with precision in seconds. - /// - public class SystemClock : ISystemClock - { - /// - /// Retrieves the current system time in UTC. - /// - public DateTimeOffset UtcNow - { - get - { - // the clock measures whole seconds only, to have integral expires_in results, and - // because milliseconds do not round-trip serialization formats - var utcNowPrecisionSeconds = new DateTime((DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond, DateTimeKind.Utc); - return new DateTimeOffset(utcNowPrecisionSeconds); - } - } - } -} From 380d9cc44d0c786334468b80febf6088be4699f4 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 23 Mar 2017 12:40:29 -0700 Subject: [PATCH 05/16] Move auth middleware back to Security --- .../AuthAppBuilderExtensions.cs | 29 --------- .../AuthenticationMiddleware.cs | 65 ------------------- ...soft.AspNetCore.Authentication.Core.csproj | 1 - 3 files changed, 95 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs deleted file mode 100644 index eba1ce30..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthAppBuilderExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 Microsoft.AspNetCore.Authentication; - -namespace Microsoft.AspNetCore.Builder -{ - /// - /// Extension methods to add authentication capabilities to an HTTP application pipeline. - /// - public static class AuthAppBuilderExtensions - { - /// - /// Adds the middleware to the specified , which enables authentication capabilities. - /// - /// The to add the middleware to. - /// A reference to this instance after the operation has completed. - public static IApplicationBuilder UseAuthentication(this IApplicationBuilder app) - { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } - - return app.UseMiddleware(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs deleted file mode 100644 index 3e377d55..00000000 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationMiddleware.cs +++ /dev/null @@ -1,65 +0,0 @@ -// 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.Extensions.DependencyInjection; - -namespace Microsoft.AspNetCore.Authentication -{ - public class AuthenticationMiddleware - { - private readonly RequestDelegate _next; - - public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes) - { - _next = next ?? throw new ArgumentNullException(nameof(next)); - Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); - } - - public IAuthenticationSchemeProvider Schemes { get; set; } - - public async Task Invoke(HttpContext context) - { - var oldFeature = context.Features.Get(); - try - { - context.Features.Set(new AuthenticationFeature - { - OriginalPath = context.Request.Path, - OriginalPathBase = context.Request.PathBase - }); - - var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); - if (defaultAuthenticate != null) - { - var result = await context.AuthenticateAsync(defaultAuthenticate.Name); - if (result?.Principal != null) - { - context.User = result.Principal; - } - } - - // REVIEW: alternatively could depend on a routing middleware to do this - - // Give any IAuthenticationRequestHandler schemes a chance to handle the request - var handlers = context.RequestServices.GetRequiredService(); - foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync(context.Request.Path)) - { - var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler; - if (handler != null && await handler.HandleRequestAsync()) - { - return; - } - } - - await _next(context); - } - finally - { - context.Features.Set(oldFeature); - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj index 0e8e647f..c6766a92 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -16,7 +16,6 @@ - From 47fe3ddca4bb56c75f40828276a940485d73e621 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 23 Mar 2017 14:40:13 -0700 Subject: [PATCH 06/16] Obsolete old Auth --- .../AuthenticationOptions.cs | 4 ++-- .../AuthenticationProperties.cs | 8 ++++---- .../TokenExtensions.cs | 10 +++++----- .../AuthenticationHandlerProvider.cs | 4 ++-- .../AuthenticationSchemeProvider.cs | 6 +++--- .../Properties/Resources.Designer.cs | 4 ++-- .../Resources.resx | 4 ++-- .../Authentication/AuthenticateInfo.cs | 4 ++++ .../AuthenticationDescription.cs | 1 + .../Authentication/AuthenticationManager.cs | 20 +++++++++++++++++++ .../AuthenticationProperties.cs | 7 +++++++ .../HttpContext.cs | 1 + .../Authentication/AuthenticateContext.cs | 1 + .../Authentication/ChallengeBehavior.cs | 3 +++ .../Authentication/ChallengeContext.cs | 1 + .../Authentication/DescribeSchemesContext.cs | 2 ++ .../Authentication/IAuthenticationHandler.cs | 7 +++++++ .../IHttpAuthenticationFeature.cs | 2 ++ .../Authentication/SignInContext.cs | 1 + .../Authentication/SignOutContext.cs | 1 + .../DefaultAuthenticationManager.cs | 8 ++++++++ .../DefaultHttpContext.cs | 7 +++++++ .../HttpAuthenticationFeature.cs | 2 ++ .../Authentication/AuthenticateContextTest.cs | 2 ++ .../DefaultAuthenticationManagerTests.cs | 2 ++ 25 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index ad757917..8a1da98c 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -41,7 +41,7 @@ public void AddScheme(string name, Action configure var builder = new AuthenticationSchemeBuilder(name); configureBuilder(builder); _schemes.Add(builder); - SchemeMap[name] = builder; + SchemeMap[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = builder; } public void ConfigureScheme(string name, Action configureBuilder) @@ -59,7 +59,7 @@ public void ConfigureScheme(string name, Action con throw new InvalidOperationException("Scheme does not exists: " + name); } - configureBuilder(SchemeMap[name]); + configureBuilder(SchemeMap[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]); } public string DefaultAuthenticationScheme { get; set; } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs index 609b6fad..68251bbf 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs @@ -80,7 +80,7 @@ public string RedirectUri { if (value != null) { - Items[RedirectUriKey] = value; + Items[RedirectUriKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value; } else { @@ -114,7 +114,7 @@ public DateTimeOffset? IssuedUtc { if (value.HasValue) { - Items[IssuedUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + Items[IssuedUtcKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); } else { @@ -148,7 +148,7 @@ public DateTimeOffset? ExpiresUtc { if (value.HasValue) { - Items[ExpiresUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + Items[ExpiresUtcKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); } else { @@ -182,7 +182,7 @@ public bool? AllowRefresh { if (value.HasValue) { - Items[RefreshKey] = value.Value.ToString(); + Items[RefreshKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(); } else { diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs index 9aaee4e2..14fb254b 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs @@ -37,11 +37,11 @@ public static void StoreTokens(this AuthenticationProperties properties, IEnumer { // REVIEW: should probably check that there are no ; in the token name and throw or encode tokenNames.Add(token.Name); - properties.Items[TokenKeyPrefix+token.Name] = token.Value; + properties.Items[TokenKeyPrefix+token.Name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = token.Value; } if (tokenNames.Count > 0) { - properties.Items[TokenNamesKey] = string.Join(";", tokenNames.ToArray()); + properties.Items[TokenNamesKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = string.Join(";", tokenNames.ToArray()); } } @@ -58,7 +58,7 @@ public static string GetTokenValue(this AuthenticationProperties properties, str var tokenKey = TokenKeyPrefix + tokenName; return properties.Items.ContainsKey(tokenKey) - ? properties.Items[tokenKey] + ? properties.Items[tokenKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] : null; } @@ -78,7 +78,7 @@ public static bool UpdateTokenValue(this AuthenticationProperties properties, st { return false; } - properties.Items[tokenKey] = tokenValue; + properties.Items[tokenKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = tokenValue; return true; } @@ -92,7 +92,7 @@ public static IEnumerable GetTokens(this AuthenticationProp var tokens = new List(); if (properties.Items.ContainsKey(TokenNamesKey)) { - var tokenNames = properties.Items[TokenNamesKey].Split(';'); + var tokenNames = properties.Items[TokenNamesKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)].Split(';'); foreach (var name in tokenNames) { var token = properties.GetTokenValue(name); diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs index 408c1b2f..804a258d 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs @@ -24,7 +24,7 @@ public async Task GetHandlerAsync(HttpContext context, s { if (_handlerMap.ContainsKey(authenticationScheme)) { - return _handlerMap[authenticationScheme]; + return _handlerMap[authenticationScheme[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]; } var scheme = await Schemes.GetSchemeAsync(authenticationScheme); @@ -38,7 +38,7 @@ public async Task GetHandlerAsync(HttpContext context, s if (handler != null) { await handler.InitializeAsync(scheme, context); - _handlerMap[authenticationScheme] = handler; + _handlerMap[authenticationScheme[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = handler; } return handler; } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index cc33fbb1..6d2c8453 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -77,7 +77,7 @@ public Task GetSchemeAsync(string name) { if (_map.ContainsKey(name)) { - return Task.FromResult(_map[name]); + return Task.FromResult(_map[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]); } return Task.FromResult(null); } @@ -103,7 +103,7 @@ public void AddScheme(AuthenticationScheme scheme) { _requestHandlers.Add(scheme); } - _map[scheme.Name] = scheme; + _map[scheme.Name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = scheme; } } @@ -117,7 +117,7 @@ public void RemoveScheme(string name) { if (_map.ContainsKey(name)) { - var scheme = _map[name]; + var scheme = _map[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]; _requestHandlers.Remove(_requestHandlers.Where(s => s.Name == name).FirstOrDefault()); _map.Remove(name); } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs index 11e2e458..7d6b94a9 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs @@ -74,7 +74,7 @@ internal static string FormatException_OptionMustBeProvided(object p0) return string.Format(CultureInfo.CurrentCulture, GetString("Exception_OptionMustBeProvided"), p0); } - private static string GetString(string name, params string[] formatterNames) + private static string GetString(string name, params string[[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] formatterNames) { var value = _resourceManager.GetString(name); @@ -84,7 +84,7 @@ private static string GetString(string name, params string[] formatterNames) { for (var i = 0; i < formatterNames.Length; i++) { - value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + value = value.Replace("{" + formatterNames[i[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] + "}", "{" + i + "}"); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx index 54d22bcc..7baf79d2 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx +++ b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx @@ -20,10 +20,10 @@ this is my long stringthis is a comment Blue - [base64 mime encoded serialized .NET Framework object] + [base64 mime encoded serialized .NET Framework object[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] - [base64 mime encoded string representing a byte array form of the .NET Framework object] + [base64 mime encoded string representing a byte array form of the .NET Framework object[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] This is a comment diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticateInfo.cs b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticateInfo.cs index 9e8e3fd5..3c893dbb 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticateInfo.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticateInfo.cs @@ -9,21 +9,25 @@ namespace Microsoft.AspNetCore.Http.Authentication /// /// Used to store the results of an Authenticate call. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class AuthenticateInfo { /// /// The . /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public ClaimsPrincipal Principal { get; set; } /// /// The . /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public AuthenticationProperties Properties { get; set; } /// /// The . /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public AuthenticationDescription Description { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationDescription.cs b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationDescription.cs index fb0a073f..fb2d00c8 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationDescription.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationDescription.cs @@ -10,6 +10,7 @@ namespace Microsoft.AspNetCore.Http.Authentication /// /// Contains information describing an authentication provider. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class AuthenticationDescription { private const string DisplayNamePropertyKey = "DisplayName"; diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationManager.cs b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationManager.cs index 56d9dbad..164618dc 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationManager.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationManager.cs @@ -9,37 +9,47 @@ namespace Microsoft.AspNetCore.Http.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract class AuthenticationManager { /// /// Constant used to represent the automatic scheme /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public const string AutomaticScheme = "Automatic"; + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract HttpContext HttpContext { get; } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract IEnumerable GetAuthenticationSchemes(); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract Task GetAuthenticateInfoAsync(string authenticationScheme); // Will remove once callees have been updated + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract Task AuthenticateAsync(AuthenticateContext context); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual async Task AuthenticateAsync(string authenticationScheme) { return (await GetAuthenticateInfoAsync(authenticationScheme))?.Principal; } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ChallengeAsync() { return ChallengeAsync(properties: null); } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ChallengeAsync(AuthenticationProperties properties) { return ChallengeAsync(authenticationScheme: AutomaticScheme, properties: properties); } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ChallengeAsync(string authenticationScheme) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -51,6 +61,7 @@ public virtual Task ChallengeAsync(string authenticationScheme) } // Leave it up to authentication handler to do the right thing for the challenge + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ChallengeAsync(string authenticationScheme, AuthenticationProperties properties) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -61,6 +72,7 @@ public virtual Task ChallengeAsync(string authenticationScheme, AuthenticationPr return ChallengeAsync(authenticationScheme, properties, ChallengeBehavior.Automatic); } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task SignInAsync(string authenticationScheme, ClaimsPrincipal principal) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -80,9 +92,11 @@ public virtual Task SignInAsync(string authenticationScheme, ClaimsPrincipal pri /// Creates a challenge for the authentication manager with . /// /// A that represents the asynchronous challenge operation. + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ForbidAsync() => ForbidAsync(AutomaticScheme, properties: null); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ForbidAsync(string authenticationScheme) { if (authenticationScheme == null) @@ -94,6 +108,7 @@ public virtual Task ForbidAsync(string authenticationScheme) } // Deny access (typically a 403) + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ForbidAsync(string authenticationScheme, AuthenticationProperties properties) { if (authenticationScheme == null) @@ -109,13 +124,17 @@ public virtual Task ForbidAsync(string authenticationScheme, AuthenticationPrope /// /// Additional arbitrary values which may be used by particular authentication types. /// A that represents the asynchronous challenge operation. + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task ForbidAsync(AuthenticationProperties properties) => ForbidAsync(AutomaticScheme, properties); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract Task ChallengeAsync(string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract Task SignInAsync(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public virtual Task SignOutAsync(string authenticationScheme) { if (authenticationScheme == null) @@ -126,6 +145,7 @@ public virtual Task SignOutAsync(string authenticationScheme) return SignOutAsync(authenticationScheme, properties: null); } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract Task SignOutAsync(string authenticationScheme, AuthenticationProperties properties); } } diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationProperties.cs b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationProperties.cs index 6e883efb..a01c5d4c 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationProperties.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/Authentication/AuthenticationProperties.cs @@ -10,6 +10,7 @@ namespace Microsoft.AspNetCore.Http.Authentication /// /// Dictionary used to store state values about the authentication session. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class AuthenticationProperties { internal const string IssuedUtcKey = ".issued"; @@ -39,11 +40,13 @@ public AuthenticationProperties(IDictionary items) /// /// State values about the authentication session. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public IDictionary Items { get; } /// /// Gets or sets whether the authentication session is persisted across multiple requests. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public bool IsPersistent { get { return Items.ContainsKey(IsPersistentKey); } @@ -69,6 +72,7 @@ public bool IsPersistent /// /// Gets or sets the full path or absolute URI to be used as an http redirect response value. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public string RedirectUri { get @@ -95,6 +99,7 @@ public string RedirectUri /// /// Gets or sets the time at which the authentication ticket was issued. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public DateTimeOffset? IssuedUtc { get @@ -129,6 +134,7 @@ public DateTimeOffset? IssuedUtc /// /// Gets or sets the time at which the authentication ticket expires. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public DateTimeOffset? ExpiresUtc { get @@ -163,6 +169,7 @@ public DateTimeOffset? ExpiresUtc /// /// Gets or sets if refreshing the authentication session should be allowed. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public bool? AllowRefresh { get diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/HttpContext.cs b/src/Microsoft.AspNetCore.Http.Abstractions/HttpContext.cs index 7f72dcd8..6b38ae43 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/HttpContext.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/HttpContext.cs @@ -43,6 +43,7 @@ public abstract class HttpContext /// /// Gets an object that facilitates authentication for this request. /// + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public abstract AuthenticationManager Authentication { get; } /// diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/AuthenticateContext.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/AuthenticateContext.cs index e7306166..67e89f18 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/AuthenticateContext.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/AuthenticateContext.cs @@ -7,6 +7,7 @@ namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class AuthenticateContext { public AuthenticateContext(string authenticationScheme) diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeBehavior.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeBehavior.cs index 549d5113..9fdceb0a 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeBehavior.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeBehavior.cs @@ -1,8 +1,11 @@ // 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; + namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public enum ChallengeBehavior { Automatic, diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeContext.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeContext.cs index c0fe4708..d8e04c14 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeContext.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/ChallengeContext.cs @@ -6,6 +6,7 @@ namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class ChallengeContext { public ChallengeContext(string authenticationScheme) diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/DescribeSchemesContext.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/DescribeSchemesContext.cs index b25c2c97..e86f8475 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/DescribeSchemesContext.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/DescribeSchemesContext.cs @@ -1,10 +1,12 @@ // 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; namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class DescribeSchemesContext { private List> _results; diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/IAuthenticationHandler.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/IAuthenticationHandler.cs index 3b723641..7d5b9c01 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/IAuthenticationHandler.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/IAuthenticationHandler.cs @@ -1,20 +1,27 @@ // 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; namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public interface IAuthenticationHandler { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] void GetDescriptions(DescribeSchemesContext context); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] Task AuthenticateAsync(AuthenticateContext context); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] Task ChallengeAsync(ChallengeContext context); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] Task SignInAsync(SignInContext context); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] Task SignOutAsync(SignOutContext context); } } diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/IHttpAuthenticationFeature.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/IHttpAuthenticationFeature.cs index 080ce405..b018e51a 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/IHttpAuthenticationFeature.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/IHttpAuthenticationFeature.cs @@ -1,6 +1,7 @@ // 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; namespace Microsoft.AspNetCore.Http.Features.Authentication @@ -9,6 +10,7 @@ public interface IHttpAuthenticationFeature { ClaimsPrincipal User { get; set; } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] IAuthenticationHandler Handler { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/SignInContext.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/SignInContext.cs index f04dade5..982f4400 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/SignInContext.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/SignInContext.cs @@ -7,6 +7,7 @@ namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class SignInContext { public SignInContext(string authenticationScheme, ClaimsPrincipal principal, IDictionary properties) diff --git a/src/Microsoft.AspNetCore.Http.Features/Authentication/SignOutContext.cs b/src/Microsoft.AspNetCore.Http.Features/Authentication/SignOutContext.cs index c752f057..e99773e9 100644 --- a/src/Microsoft.AspNetCore.Http.Features/Authentication/SignOutContext.cs +++ b/src/Microsoft.AspNetCore.Http.Features/Authentication/SignOutContext.cs @@ -6,6 +6,7 @@ namespace Microsoft.AspNetCore.Http.Features.Authentication { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class SignOutContext { public SignOutContext(string authenticationScheme, IDictionary properties) diff --git a/src/Microsoft.AspNetCore.Http/Authentication/DefaultAuthenticationManager.cs b/src/Microsoft.AspNetCore.Http/Authentication/DefaultAuthenticationManager.cs index 666e2179..028555f4 100644 --- a/src/Microsoft.AspNetCore.Http/Authentication/DefaultAuthenticationManager.cs +++ b/src/Microsoft.AspNetCore.Http/Authentication/DefaultAuthenticationManager.cs @@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.Http.Authentication.Internal { + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public class DefaultAuthenticationManager : AuthenticationManager { // Lambda hoisted to static readonly field to improve inlining https://github.com/dotnet/roslyn/issues/13624 @@ -35,11 +36,13 @@ public virtual void Uninitialize() _features = default(FeatureReferences); } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override HttpContext HttpContext => _context; private IHttpAuthenticationFeature HttpAuthenticationFeature => _features.Fetch(ref _features.Cache, _newAuthenticationFeature); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override IEnumerable GetAuthenticationSchemes() { var handler = HttpAuthenticationFeature.Handler; @@ -54,6 +57,7 @@ public override IEnumerable GetAuthenticationSchemes( } // Remove once callers have been switched to GetAuthenticateInfoAsync + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override async Task AuthenticateAsync(AuthenticateContext context) { if (context == null) @@ -73,6 +77,7 @@ public override async Task AuthenticateAsync(AuthenticateContext context) } } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override async Task GetAuthenticateInfoAsync(string authenticationScheme) { if (authenticationScheme == null) @@ -100,6 +105,7 @@ public override async Task GetAuthenticateInfoAsync(string aut }; } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override async Task ChallengeAsync(string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -121,6 +127,7 @@ public override async Task ChallengeAsync(string authenticationScheme, Authentic } } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override async Task SignInAsync(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -147,6 +154,7 @@ public override async Task SignInAsync(string authenticationScheme, ClaimsPrinci } } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override async Task SignOutAsync(string authenticationScheme, AuthenticationProperties properties) { if (string.IsNullOrEmpty(authenticationScheme)) diff --git a/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs b/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs index d1e431c7..883cc33e 100644 --- a/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs +++ b/src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs @@ -28,7 +28,9 @@ public class DefaultHttpContext : HttpContext private HttpRequest _request; private HttpResponse _response; +#pragma warning disable 618 private AuthenticationManager _authenticationManager; +#pragma warning restore 618 private ConnectionInfo _connection; private WebSocketManager _websockets; @@ -66,7 +68,9 @@ public virtual void Uninitialize() } if (_authenticationManager != null) { +#pragma warning disable 618 UninitializeAuthenticationManager(_authenticationManager); +#pragma warning restore 618 _authenticationManager = null; } if (_connection != null) @@ -111,6 +115,7 @@ public virtual void Uninitialize() public override ConnectionInfo Connection => _connection ?? (_connection = InitializeConnectionInfo()); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public override AuthenticationManager Authentication => _authenticationManager ?? (_authenticationManager = InitializeAuthenticationManager()); public override WebSocketManager WebSockets => _websockets ?? (_websockets = InitializeWebSocketManager()); @@ -190,7 +195,9 @@ protected virtual void UninitializeHttpResponse(HttpResponse instance) { } protected virtual ConnectionInfo InitializeConnectionInfo() => new DefaultConnectionInfo(Features); protected virtual void UninitializeConnectionInfo(ConnectionInfo instance) { } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] protected virtual AuthenticationManager InitializeAuthenticationManager() => new DefaultAuthenticationManager(this); + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] protected virtual void UninitializeAuthenticationManager(AuthenticationManager instance) { } protected virtual WebSocketManager InitializeWebSocketManager() => new DefaultWebSocketManager(Features); diff --git a/src/Microsoft.AspNetCore.Http/Features/Authentication/HttpAuthenticationFeature.cs b/src/Microsoft.AspNetCore.Http/Features/Authentication/HttpAuthenticationFeature.cs index 9a14b657..89f06e3b 100644 --- a/src/Microsoft.AspNetCore.Http/Features/Authentication/HttpAuthenticationFeature.cs +++ b/src/Microsoft.AspNetCore.Http/Features/Authentication/HttpAuthenticationFeature.cs @@ -1,6 +1,7 @@ // 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; namespace Microsoft.AspNetCore.Http.Features.Authentication @@ -13,6 +14,7 @@ public ClaimsPrincipal User set; } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] public IAuthenticationHandler Handler { get; diff --git a/test/Microsoft.AspNetCore.Http.Features.Tests/Authentication/AuthenticateContextTest.cs b/test/Microsoft.AspNetCore.Http.Features.Tests/Authentication/AuthenticateContextTest.cs index c4d90132..1fae5b0a 100644 --- a/test/Microsoft.AspNetCore.Http.Features.Tests/Authentication/AuthenticateContextTest.cs +++ b/test/Microsoft.AspNetCore.Http.Features.Tests/Authentication/AuthenticateContextTest.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Xunit; +#pragma warning disable 618 namespace Microsoft.AspNetCore.Http.Features.Authentication { public class AuthenticateContextTest @@ -160,3 +161,4 @@ public void AuthenticateContext_NotAuthenticated_SetsUnusedPropertiesToDefault_F } } } +#pragma warning restore 618 diff --git a/test/Microsoft.AspNetCore.Http.Tests/Authentication/DefaultAuthenticationManagerTests.cs b/test/Microsoft.AspNetCore.Http.Tests/Authentication/DefaultAuthenticationManagerTests.cs index 85968a94..73c0c931 100644 --- a/test/Microsoft.AspNetCore.Http.Tests/Authentication/DefaultAuthenticationManagerTests.cs +++ b/test/Microsoft.AspNetCore.Http.Tests/Authentication/DefaultAuthenticationManagerTests.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Http.Features.Authentication; using Xunit; +#pragma warning disable 618 namespace Microsoft.AspNetCore.Http.Authentication.Internal { public class DefaultAuthenticationManagerTests @@ -100,3 +101,4 @@ private HttpContext CreateContext() } } } +#pragma warning restore 618 From 4f3ed5d80e15ef683856cebc3be4c50f6fc97674 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 23 Mar 2017 14:48:13 -0700 Subject: [PATCH 07/16] Fixup --- .../AuthenticationOptions.cs | 4 ++-- .../AuthenticationProperties.cs | 8 ++++---- .../TokenExtensions.cs | 10 +++++----- src/Microsoft.AspNetCore.Owin/OwinFeatureCollection.cs | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index 8a1da98c..ad757917 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -41,7 +41,7 @@ public void AddScheme(string name, Action configure var builder = new AuthenticationSchemeBuilder(name); configureBuilder(builder); _schemes.Add(builder); - SchemeMap[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = builder; + SchemeMap[name] = builder; } public void ConfigureScheme(string name, Action configureBuilder) @@ -59,7 +59,7 @@ public void ConfigureScheme(string name, Action con throw new InvalidOperationException("Scheme does not exists: " + name); } - configureBuilder(SchemeMap[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]); + configureBuilder(SchemeMap[name]); } public string DefaultAuthenticationScheme { get; set; } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs index 68251bbf..609b6fad 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationProperties.cs @@ -80,7 +80,7 @@ public string RedirectUri { if (value != null) { - Items[RedirectUriKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value; + Items[RedirectUriKey] = value; } else { @@ -114,7 +114,7 @@ public DateTimeOffset? IssuedUtc { if (value.HasValue) { - Items[IssuedUtcKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + Items[IssuedUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); } else { @@ -148,7 +148,7 @@ public DateTimeOffset? ExpiresUtc { if (value.HasValue) { - Items[ExpiresUtcKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); + Items[ExpiresUtcKey] = value.Value.ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); } else { @@ -182,7 +182,7 @@ public bool? AllowRefresh { if (value.HasValue) { - Items[RefreshKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = value.Value.ToString(); + Items[RefreshKey] = value.Value.ToString(); } else { diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs index 14fb254b..9aaee4e2 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs @@ -37,11 +37,11 @@ public static void StoreTokens(this AuthenticationProperties properties, IEnumer { // REVIEW: should probably check that there are no ; in the token name and throw or encode tokenNames.Add(token.Name); - properties.Items[TokenKeyPrefix+token.Name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = token.Value; + properties.Items[TokenKeyPrefix+token.Name] = token.Value; } if (tokenNames.Count > 0) { - properties.Items[TokenNamesKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = string.Join(";", tokenNames.ToArray()); + properties.Items[TokenNamesKey] = string.Join(";", tokenNames.ToArray()); } } @@ -58,7 +58,7 @@ public static string GetTokenValue(this AuthenticationProperties properties, str var tokenKey = TokenKeyPrefix + tokenName; return properties.Items.ContainsKey(tokenKey) - ? properties.Items[tokenKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] + ? properties.Items[tokenKey] : null; } @@ -78,7 +78,7 @@ public static bool UpdateTokenValue(this AuthenticationProperties properties, st { return false; } - properties.Items[tokenKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = tokenValue; + properties.Items[tokenKey] = tokenValue; return true; } @@ -92,7 +92,7 @@ public static IEnumerable GetTokens(this AuthenticationProp var tokens = new List(); if (properties.Items.ContainsKey(TokenNamesKey)) { - var tokenNames = properties.Items[TokenNamesKey[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)].Split(';'); + var tokenNames = properties.Items[TokenNamesKey].Split(';'); foreach (var name in tokenNames) { var token = properties.GetTokenValue(name); diff --git a/src/Microsoft.AspNetCore.Owin/OwinFeatureCollection.cs b/src/Microsoft.AspNetCore.Owin/OwinFeatureCollection.cs index 4838b99f..4a71310c 100644 --- a/src/Microsoft.AspNetCore.Owin/OwinFeatureCollection.cs +++ b/src/Microsoft.AspNetCore.Owin/OwinFeatureCollection.cs @@ -279,6 +279,7 @@ ClaimsPrincipal IHttpAuthenticationFeature.User } } + [Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470")] IAuthenticationHandler IHttpAuthenticationFeature.Handler { get; set; } /// From 8dc98b9c5ce410132f17529dcbb54ebb7d12f458 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 23 Mar 2017 14:52:24 -0700 Subject: [PATCH 08/16] Fix rogue obsoletes --- .../AuthenticationHandlerProvider.cs | 4 ++-- .../AuthenticationSchemeProvider.cs | 6 +++--- .../Properties/Resources.Designer.cs | 4 ++-- src/Microsoft.AspNetCore.Authentication.Core/Resources.resx | 4 ++-- .../DefaultHttpContextTests.cs | 4 ++++ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs index 804a258d..408c1b2f 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs @@ -24,7 +24,7 @@ public async Task GetHandlerAsync(HttpContext context, s { if (_handlerMap.ContainsKey(authenticationScheme)) { - return _handlerMap[authenticationScheme[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]; + return _handlerMap[authenticationScheme]; } var scheme = await Schemes.GetSchemeAsync(authenticationScheme); @@ -38,7 +38,7 @@ public async Task GetHandlerAsync(HttpContext context, s if (handler != null) { await handler.InitializeAsync(scheme, context); - _handlerMap[authenticationScheme[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = handler; + _handlerMap[authenticationScheme] = handler; } return handler; } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index 6d2c8453..cc33fbb1 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -77,7 +77,7 @@ public Task GetSchemeAsync(string name) { if (_map.ContainsKey(name)) { - return Task.FromResult(_map[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]); + return Task.FromResult(_map[name]); } return Task.FromResult(null); } @@ -103,7 +103,7 @@ public void AddScheme(AuthenticationScheme scheme) { _requestHandlers.Add(scheme); } - _map[scheme.Name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] = scheme; + _map[scheme.Name] = scheme; } } @@ -117,7 +117,7 @@ public void RemoveScheme(string name) { if (_map.ContainsKey(name)) { - var scheme = _map[name[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)]; + var scheme = _map[name]; _requestHandlers.Remove(_requestHandlers.Where(s => s.Name == name).FirstOrDefault()); _map.Remove(name); } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs index 7d6b94a9..11e2e458 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/Properties/Resources.Designer.cs @@ -74,7 +74,7 @@ internal static string FormatException_OptionMustBeProvided(object p0) return string.Format(CultureInfo.CurrentCulture, GetString("Exception_OptionMustBeProvided"), p0); } - private static string GetString(string name, params string[[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] formatterNames) + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); @@ -84,7 +84,7 @@ private static string GetString(string name, params string[[Obsolete("See https: { for (var i = 0; i < formatterNames.Length; i++) { - value = value.Replace("{" + formatterNames[i[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] + "}", "{" + i + "}"); + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx index 7baf79d2..54d22bcc 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx +++ b/src/Microsoft.AspNetCore.Authentication.Core/Resources.resx @@ -20,10 +20,10 @@ this is my long stringthis is a comment Blue - [base64 mime encoded serialized .NET Framework object[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] + [base64 mime encoded serialized .NET Framework object] - [base64 mime encoded string representing a byte array form of the .NET Framework object[Obsolete("See https://go.microsoft.com/fwlink/?linkid=845470", error: true)] + [base64 mime encoded string representing a byte array form of the .NET Framework object] This is a comment diff --git a/test/Microsoft.AspNetCore.Http.Tests/DefaultHttpContextTests.cs b/test/Microsoft.AspNetCore.Http.Tests/DefaultHttpContextTests.cs index 13b9ee65..7766210e 100644 --- a/test/Microsoft.AspNetCore.Http.Tests/DefaultHttpContextTests.cs +++ b/test/Microsoft.AspNetCore.Http.Tests/DefaultHttpContextTests.cs @@ -191,7 +191,9 @@ void TestAllCachedFeaturesAreNull(HttpContext context, IFeatureCollection featur TestCachedFeaturesAreNull(context, features); TestCachedFeaturesAreNull(context.Request, features); TestCachedFeaturesAreNull(context.Response, features); +#pragma warning disable 618 TestCachedFeaturesAreNull(context.Authentication, features); +#pragma warning restore 618 TestCachedFeaturesAreNull(context.Connection, features); TestCachedFeaturesAreNull(context.WebSockets, features); } @@ -220,7 +222,9 @@ void TestAllCachedFeaturesAreSet(HttpContext context, IFeatureCollection feature TestCachedFeaturesAreSet(context, features); TestCachedFeaturesAreSet(context.Request, features); TestCachedFeaturesAreSet(context.Response, features); +#pragma warning disable 618 TestCachedFeaturesAreSet(context.Authentication, features); +#pragma warning restore 618 TestCachedFeaturesAreSet(context.Connection, features); TestCachedFeaturesAreSet(context.WebSockets, features); } From e17091a6950b29e257bd200d1ace80a792b36e00 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 12:57:06 -0700 Subject: [PATCH 09/16] Add doc comments --- .../AuthenticateContext.cs | 8 ++ .../AuthenticateResult.cs | 35 ++++-- .../AuthenticationHttpContextExtensions.cs | 107 +++++++++++++++++- .../AuthenticationSchemeBuilder.cs | 17 +++ .../AuthenticationToken.cs | 10 ++ .../BaseAuthenticationContext.cs | 12 ++ .../BaseContext.cs | 16 +++ .../ChallengeBehavior.cs | 3 + .../ChallengeContext.cs | 18 +++ .../IAuthenticationFeature.cs | 9 ++ .../IAuthenticationHandler.cs | 34 +++++- .../IAuthenticationHandlerProvider.cs | 6 + .../IAuthenticationRequestHandler.cs | 3 + .../IAuthenticationSchemeProvider.cs | 46 +++++++- ...NetCore.Authentication.Abstractions.csproj | 2 +- .../TokenExtensions.cs | 27 +++++ ...soft.AspNetCore.Authentication.Core.csproj | 2 +- 17 files changed, 336 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs index 72321300..814d7024 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateContext.cs @@ -5,8 +5,16 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Base class used by methods. + /// public class AuthenticateContext : BaseAuthenticationContext { + /// + /// Constructor. + /// + /// The context. + /// The name of the authentication scheme. public AuthenticateContext(HttpContext context, string authenticationScheme) : base(context, authenticationScheme, properties: null) { } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs index 26ced408..bb9bbb97 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticateResult.cs @@ -16,21 +16,13 @@ private AuthenticateResult() { } /// /// If a ticket was produced, authenticate was successful. /// - public bool Succeeded - { - get - { - return Ticket != null; - } - } + public bool Succeeded => Ticket != null; /// /// The authentication ticket. /// public AuthenticationTicket Ticket { get; private set; } - // REVIEW: should we also remember AuthenticationScheme? - /// /// Gets the claims-principal with authenticated user identities. /// @@ -57,6 +49,11 @@ public bool Succeeded /// public bool Nothing { get; private set; } + /// + /// Indicates that authentication was successful. + /// + /// The ticket representing the authentication result. + /// The result. public static AuthenticateResult Success(AuthenticationTicket ticket) { if (ticket == null) @@ -66,25 +63,43 @@ public static AuthenticateResult Success(AuthenticationTicket ticket) return new AuthenticateResult() { Ticket = ticket }; } + /// + /// Indicates that stage of authentication was directly handled by user intervention and no + /// further processing should be attempted. + /// + /// The result. public static AuthenticateResult Handle() { return new AuthenticateResult() { Handled = true }; } + /// + /// Indicates that there was no information returned for this authentication scheme. + /// + /// The result. public static AuthenticateResult None() { return new AuthenticateResult() { Nothing = true }; } + /// + /// Indicates that there was a failure during authentication. + /// + /// The failure exception. + /// The result. public static AuthenticateResult Fail(Exception failure) { return new AuthenticateResult() { Failure = failure }; } + /// + /// Indicates that there was a failure during authentication. + /// + /// The failure message. + /// The result. public static AuthenticateResult Fail(string failureMessage) { return new AuthenticateResult() { Failure = new Exception(failureMessage) }; } - } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs index 44e158c9..e928ff0c 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs @@ -4,55 +4,154 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Authentication { + /// + /// Extension methods to expose Authentication on HttpContext. + /// public static class AuthenticationHttpContextExtensions { + /// + /// Extension method for authenticate using the scheme. + /// + /// The context. + /// The . public static Task AuthenticateAsync(this HttpContext context) => context.AuthenticateAsync(scheme: null); + /// + /// Extension method for authenticate. + /// + /// The context. + /// The name of the authentication scheme. + /// The . public static Task AuthenticateAsync(this HttpContext context, string scheme) => context.RequestServices.GetRequiredService().AuthenticateAsync(context, scheme); + /// + /// Extension method for Challenge. + /// + /// The context. + /// The name of the authentication scheme. + /// The result. public static Task ChallengeAsync(this HttpContext context, string scheme) => context.ChallengeAsync(scheme, properties: null); + /// + /// Extension method for authenticate using the scheme. + /// + /// The context. + /// The task. public static Task ChallengeAsync(this HttpContext context) => context.ChallengeAsync(scheme: null, properties: null); + /// + /// Extension method for Challenge. + /// + /// The context. + /// The name of the authentication scheme. + /// The properties. + /// The task. public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => context.ChallengeAsync(scheme, properties: properties, behavior: ChallengeBehavior.Automatic); + /// + /// Extension method for Challenge. + /// + /// The context. + /// The name of the authentication scheme. + /// The properties. + /// The behavior. + /// The task. public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior) => context.RequestServices.GetRequiredService().ChallengeAsync(context, scheme, properties, behavior); + /// + /// Extension method for Forbid. + /// + /// The context. + /// The name of the authentication scheme. + /// The task. public static Task ForbidAsync(this HttpContext context, string scheme) => context.ForbidAsync(scheme, properties: null); + /// + /// Extension method for Forbid. + /// + /// The context. + /// The name of the authentication scheme. + /// The properties. + /// The task. public static Task ForbidAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => context.RequestServices.GetRequiredService().ChallengeAsync(context, scheme, properties, ChallengeBehavior.Forbidden); + /// + /// Extension method for SignIn. + /// + /// The context. + /// The name of the authentication scheme. + /// The user. + /// The task. public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal) => context.SignInAsync(scheme, principal, properties: null); + /// + /// Extension method for SignIn using the . + /// + /// The context. + /// The user. + /// The task. public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal) => context.SignInAsync(scheme: null, principal: principal, properties: null); + /// + /// Extension method for SignIn using the . + /// + /// The context. + /// The user. + /// The properties. + /// The task. public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal, AuthenticationProperties properties) => context.SignInAsync(scheme: null, principal: principal, properties: properties); + /// + /// Extension method for SignIn. + /// + /// The context. + /// The name of the authentication scheme. + /// The user. + /// The properties. + /// The task. public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) => context.RequestServices.GetRequiredService().SignInAsync(context, scheme, principal, properties); - + /// + /// Extension method for SignOut. + /// + /// The context. + /// The name of the authentication scheme. + /// The task. public static Task SignOutAsync(this HttpContext context, string scheme) => context.SignOutAsync(scheme, properties: null); + /// + /// Extension method for SignOut. + /// + /// The context. + /// The name of the authentication scheme. + /// The properties. + /// public static Task SignOutAsync(this HttpContext context, string scheme, AuthenticationProperties properties) => context.RequestServices.GetRequiredService().SignOutAsync(context, scheme, properties); - public static Task GetTokenAsync(this HttpContext context, string signInScheme, string tokenName) => - context.RequestServices.GetRequiredService().GetTokenAsync(context, signInScheme, tokenName); + /// + /// Extension method for getting the value of an authentication token. + /// + /// The context. + /// The name of the authentication scheme. + /// The name of the token. + /// The value of the token. + public static Task GetTokenAsync(this HttpContext context, string scheme, string tokenName) => + context.RequestServices.GetRequiredService().GetTokenAsync(context, scheme, tokenName); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs index 7787db60..e1ea0cbc 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationSchemeBuilder.cs @@ -5,17 +5,34 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Used to build s. + /// public class AuthenticationSchemeBuilder { + /// + /// Constructor. + /// + /// The name of the scheme being built. public AuthenticationSchemeBuilder(string name) { Name = name; } + /// + /// The name of the scheme being built. + /// public string Name { get; } + /// + /// The type responsible for this scheme. + /// public Type HandlerType { get; set; } + /// + /// Builds the instance. + /// + /// public AuthenticationScheme Build() => new AuthenticationScheme(Name, HandlerType); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs index 6503f0bb..555da9e0 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationToken.cs @@ -4,9 +4,19 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Name/Value representing an token. + /// public class AuthenticationToken { + /// + /// Name. + /// public string Name { get; set; } + + /// + /// Value. + /// public string Value { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs index 0b32cdfa..cfe5809c 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseAuthenticationContext.cs @@ -6,8 +6,17 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Base context for authentication. + /// public abstract class BaseAuthenticationContext : BaseContext { + /// + /// Constructor. + /// + /// The context. + /// The name of the scheme. + /// The properties. protected BaseAuthenticationContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) : base(context) { if (string.IsNullOrEmpty(authenticationScheme)) @@ -19,6 +28,9 @@ protected BaseAuthenticationContext(HttpContext context, string authenticationSc Properties = properties ?? new AuthenticationProperties(); } + /// + /// The name of the scheme. + /// public string AuthenticationScheme { get; } /// diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs index 26c0ef2f..3d65f0dd 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/BaseContext.cs @@ -6,8 +6,15 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Base class used by other context classes. + /// public abstract class BaseContext { + /// + /// Constructor. + /// + /// The request context. protected BaseContext(HttpContext context) { if (context == null) @@ -18,13 +25,22 @@ protected BaseContext(HttpContext context) HttpContext = context; } + /// + /// The context. + /// public HttpContext HttpContext { get; } + /// + /// The request. + /// public HttpRequest Request { get { return HttpContext.Request; } } + /// + /// The response. + /// public HttpResponse Response { get { return HttpContext.Response; } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs index 95f9d657..1506021d 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeBehavior.cs @@ -3,6 +3,9 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Controls how challenge will behave (i.e. 401 vs 403). + /// public enum ChallengeBehavior { Automatic, diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs index d5f63ce3..ee2392eb 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/ChallengeContext.cs @@ -6,12 +6,27 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Context used for challenges. + /// public class ChallengeContext : BaseAuthenticationContext { + /// + /// Constructor. + /// + /// The context. + /// The name of the scheme. public ChallengeContext(HttpContext httpContext, string authenticationScheme) : this(httpContext, authenticationScheme, properties: null, behavior: ChallengeBehavior.Automatic) { } + /// + /// Constructor + /// + /// The context. + /// The name of the scheme. + /// The properties. + /// The challenge behavior. public ChallengeContext(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) : base(httpContext, authenticationScheme, properties) { @@ -22,6 +37,9 @@ public ChallengeContext(HttpContext httpContext, string authenticationScheme, Au Behavior = behavior; } + /// + /// The challenge behavior. + /// public ChallengeBehavior Behavior { get; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs index c2861186..8ab100d1 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs @@ -5,10 +5,19 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Feature used to remember the original path/base. + /// public interface IAuthenticationFeature { + /// + /// The original path base. + /// PathString OriginalPathBase { get; set; } + /// + /// The original path. + /// PathString OriginalPath { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs index d084de70..7a805f7a 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandler.cs @@ -6,15 +6,45 @@ namespace Microsoft.AspNetCore.Authentication { - // Created on a per request basis to handle one particular scheme. + /// + /// Created per request to handle authentication for to a particular scheme. + /// public interface IAuthenticationHandler { - // Gives the handler access to the configuration data + /// + /// The handler should initialize anything it needs from the request and scheme here. + /// + /// The scheme. + /// The context. + /// Task InitializeAsync(AuthenticationScheme scheme, HttpContext context); + /// + /// Authentication behavior. + /// + /// The context. + /// The result. Task AuthenticateAsync(AuthenticateContext context); + + /// + /// Challenge behavior. + /// + /// The context. + /// A task. Task ChallengeAsync(ChallengeContext context); + + /// + /// Handle sign in. + /// + /// The context. + /// A task. Task SignInAsync(SignInContext context); + + /// + /// Signout behavior. + /// + /// The context. + /// A task. Task SignOutAsync(SignOutContext context); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs index fdd2df1d..adb044af 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs @@ -11,6 +11,12 @@ namespace Microsoft.AspNetCore.Authentication /// public interface IAuthenticationHandlerProvider { + /// + /// Returns the handler instance that will be used. + /// + /// The context. + /// The name of the authentication scheme being handled. + /// Task GetHandlerAsync(HttpContext context, string authenticationScheme); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs index aa6595a8..fffe08f4 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationRequestHandler.cs @@ -5,6 +5,9 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Used to determine if a handler wants to participate in request processing. + /// public interface IAuthenticationRequestHandler : IAuthenticationHandler { diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs index e3fdfce0..3ee8d8c6 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs @@ -7,20 +7,64 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Responsible for managing what authenticationSchemes are supported. + /// public interface IAuthenticationSchemeProvider { + /// + /// Returns all currently registered s. + /// + /// All currently registered s. Task> GetAllSchemesAsync(); + + /// + /// Returns the matching the name, or null. + /// + /// The name of the authenticationScheme. + /// The scheme or null if not found. Task GetSchemeAsync(string name); + + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . Task GetDefaultAuthenticateSchemeAsync(); + + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . Task GetDefaultChallengeSchemeAsync(); + + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . Task GetDefaultSignInSchemeAsync(); + + /// + /// Registers a scheme for use by . + /// + /// The scheme. void AddScheme(AuthenticationScheme scheme); + + /// + /// Removes a scheme, preventing it from being used by . + /// + /// The name of the authenticationScheme being removed. void RemoveScheme(string name); /// /// Returns the schemes in priority order for request handling. /// /// - Task> GetRequestHandlerSchemesAsync(PathString requestPath); + Task> GetRequestHandlerSchemesAsync(); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj index 23ea6be8..e2a8546b 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj @@ -3,7 +3,7 @@ ASP.NET Core common types used by the various authentication components. 1.2.0 - net451;netstandard1.3 + netstandard1.3;net46 $(NoWarn);CS1591 true aspnetcore;authentication;security diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs index 9aaee4e2..24f66d90 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/TokenExtensions.cs @@ -8,11 +8,19 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Extension methods for storing authentication tokens in . + /// public static class AuthenticationTokenExtensions { private static string TokenNamesKey = ".TokenNames"; private static string TokenKeyPrefix = ".Token."; + /// + /// Stores a set of authentication tokens, after removing any old tokens. + /// + /// The properties. + /// The tokens to store. public static void StoreTokens(this AuthenticationProperties properties, IEnumerable tokens) { if (properties == null) @@ -45,6 +53,12 @@ public static void StoreTokens(this AuthenticationProperties properties, IEnumer } } + /// + /// Returns the value of a token. + /// + /// The properties. + /// The token name. + /// The token value. public static string GetTokenValue(this AuthenticationProperties properties, string tokenName) { if (properties == null) @@ -82,6 +96,11 @@ public static bool UpdateTokenValue(this AuthenticationProperties properties, st return true; } + /// + /// Returns all of the AuthenticationTokens contained in the properties. + /// + /// The properties. + /// The authentication toekns. public static IEnumerable GetTokens(this AuthenticationProperties properties) { if (properties == null) @@ -106,6 +125,14 @@ public static IEnumerable GetTokens(this AuthenticationProp return tokens; } + /// + /// Extension method for getting the value of an authentication token. + /// + /// The . + /// The context. + /// The name of the authentication scheme. + /// The name of the token. + /// The value of the token. public static async Task GetTokenAsync(this IAuthenticationService auth, HttpContext context, string scheme, string tokenName) { if (auth == null) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj index c6766a92..d5aa75e7 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -5,7 +5,7 @@ ASP.NET Core common types used by the various authentication middleware components. 1.2.0 - net451;netstandard1.3 + netstandard1.3;net46 $(NoWarn);CS1591 true aspnetcore;authentication;security From a01fba5d9ec41de5050cba6c98a7e5705e15b99b Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 13:25:52 -0700 Subject: [PATCH 10/16] PR fixes --- .../AuthenticationHttpContextExtensions.cs | 1 + ...NetCore.Authentication.Abstractions.csproj | 13 +- .../AuthenticationSchemeProvider.cs | 4 +- .../AuthenticationService.cs | 2 +- .../AuthenticationMiddlewareTests.cs | 181 ------------------ ...AspNetCore.Authentication.Core.Test.csproj | 3 +- .../TestExtensions.cs | 86 --------- .../TokenExtensionTests.cs | 58 ------ .../Transaction.cs | 62 ------ 9 files changed, 13 insertions(+), 397 deletions(-) delete mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs delete mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs delete mode 100644 test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs index e928ff0c..a1fd3756 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationHttpContextExtensions.cs @@ -4,6 +4,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Authentication { diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj index e2a8546b..0b08bca4 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj @@ -2,17 +2,20 @@ ASP.NET Core common types used by the various authentication components. - 1.2.0 netstandard1.3;net46 $(NoWarn);CS1591 true aspnetcore;authentication;security + - - - - + + + + + + + diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index cc33fbb1..ee7ab955 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -30,7 +30,7 @@ public AuthenticationSchemeProvider(IOptions options) private readonly AuthenticationOptions _options; private readonly object _lock = new object(); - private IDictionary _map = new Dictionary(StringComparer.Ordinal); // case sensitive? + private IDictionary _map = new Dictionary(StringComparer.Ordinal); private List _requestHandlers = new List(); @@ -82,7 +82,7 @@ public Task GetSchemeAsync(string name) return Task.FromResult(null); } - public Task> GetRequestHandlerSchemesAsync(PathString requestPath) + public Task> GetRequestHandlerSchemesAsync() { return Task.FromResult>(_requestHandlers); } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs index ac2819b3..e4fbe76f 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs @@ -87,7 +87,7 @@ public virtual async Task SignInAsync(HttpContext httpContext, string authentica authenticationScheme = defaultScheme?.Name; if (authenticationScheme == null) { - throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); + throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignInScheme found."); } } diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs deleted file mode 100644 index 9220be05..00000000 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/AuthenticationMiddlewareTests.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information. - -using System; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Authentication -{ - public class AuthenticationMiddlewareTests - { - [Fact] - public async Task OnlyInvokesCanHandleRequestHandlers() - { - var builder = new WebHostBuilder() - .Configure(app => - { - app.UseAuthentication(); - }) - .ConfigureServices(services => services.AddAuthentication(o => - { - o.AddScheme("Skip", s => - { - s.HandlerType = typeof(SkipHandler); - }); - // Won't get hit since CanHandleRequests is false - o.AddScheme("throws", s => - { - s.HandlerType = typeof(ThrowsHandler); - }); - o.AddScheme("607", s => - { - s.HandlerType = typeof(SixOhSevenHandler); - }); - // Won't get run since 607 will finish - o.AddScheme("305", s => - { - s.HandlerType = typeof(ThreeOhFiveHandler); - }); - })); - var server = new TestServer(builder); - var response = await server.CreateClient().GetAsync("http://example.com/"); - Assert.Equal(607, (int)response.StatusCode); - } - - private class ThreeOhFiveHandler : StatusCodeHandler { - public ThreeOhFiveHandler() : base(305) { } - } - - private class SixOhSevenHandler : StatusCodeHandler - { - public SixOhSevenHandler() : base(607) { } - } - - private class SevenOhSevenHandler : StatusCodeHandler - { - public SevenOhSevenHandler() : base(707) { } - } - - private class StatusCodeHandler : IAuthenticationRequestHandler - { - private HttpContext _context; - private int _code; - - public StatusCodeHandler(int code) - { - _code = code; - } - - public Task AuthenticateAsync(AuthenticateContext context) - { - throw new NotImplementedException(); - } - - public Task ChallengeAsync(ChallengeContext context) - { - throw new NotImplementedException(); - } - - public Task HandleRequestAsync() - { - _context.Response.StatusCode = _code; - return Task.FromResult(true); - } - - public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) - { - _context = context; - return Task.FromResult(0); - } - - public Task SignInAsync(SignInContext context) - { - throw new NotImplementedException(); - } - - public Task SignOutAsync(SignOutContext context) - { - throw new NotImplementedException(); - } - } - - private class ThrowsHandler : IAuthenticationHandler - { - private HttpContext _context; - - public Task AuthenticateAsync(AuthenticateContext context) - { - throw new NotImplementedException(); - } - - public Task ChallengeAsync(ChallengeContext context) - { - throw new NotImplementedException(); - } - - public Task HandleRequestAsync() - { - throw new NotImplementedException(); - } - - public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) - { - _context = context; - return Task.FromResult(0); - } - - public Task SignInAsync(SignInContext context) - { - throw new NotImplementedException(); - } - - public Task SignOutAsync(SignOutContext context) - { - throw new NotImplementedException(); - } - } - - private class SkipHandler : IAuthenticationRequestHandler - { - private HttpContext _context; - - public Task AuthenticateAsync(AuthenticateContext context) - { - throw new NotImplementedException(); - } - - public Task ChallengeAsync(ChallengeContext context) - { - throw new NotImplementedException(); - } - - public Task HandleRequestAsync() - { - return Task.FromResult(false); - } - - public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) - { - _context = context; - return Task.FromResult(0); - } - - public Task SignInAsync(SignInContext context) - { - throw new NotImplementedException(); - } - - public Task SignOutAsync(SignOutContext context) - { - throw new NotImplementedException(); - } - } - - } -} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj index 3f8bbca6..1a967ac6 100644 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj @@ -2,14 +2,13 @@ - netcoreapp1.1;net452 + netcoreapp1.1;net46 netcoreapp1.1 - diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs deleted file mode 100644 index 87d6d95a..00000000 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/TestExtensions.cs +++ /dev/null @@ -1,86 +0,0 @@ -// 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.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.TestHost; - -namespace Microsoft.AspNetCore.Authentication -{ - public static class TestExtensions - { - public const string CookieAuthenticationScheme = "External"; - - public static async Task SendAsync(this TestServer server, string uri, string cookieHeader = null) - { - var request = new HttpRequestMessage(HttpMethod.Get, uri); - if (!string.IsNullOrEmpty(cookieHeader)) - { - request.Headers.Add("Cookie", cookieHeader); - } - var transaction = new Transaction - { - Request = request, - Response = await server.CreateClient().SendAsync(request), - }; - if (transaction.Response.Headers.Contains("Set-Cookie")) - { - transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList(); - } - transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync(); - - if (transaction.Response.Content != null && - transaction.Response.Content.Headers.ContentType != null && - transaction.Response.Content.Headers.ContentType.MediaType == "text/xml") - { - transaction.ResponseElement = XElement.Parse(transaction.ResponseText); - } - return transaction; - } - - public static void Describe(this HttpResponse res, ClaimsPrincipal principal) - { - res.StatusCode = 200; - res.ContentType = "text/xml"; - var xml = new XElement("xml"); - if (principal != null) - { - foreach (var identity in principal.Identities) - { - xml.Add(identity.Claims.Select(claim => - new XElement("claim", new XAttribute("type", claim.Type), - new XAttribute("value", claim.Value), - new XAttribute("issuer", claim.Issuer)))); - } - } - var xmlBytes = Encoding.UTF8.GetBytes(xml.ToString()); - res.Body.Write(xmlBytes, 0, xmlBytes.Length); - } - - public static void Describe(this HttpResponse res, IEnumerable tokens) - { - res.StatusCode = 200; - res.ContentType = "text/xml"; - var xml = new XElement("xml"); - if (tokens != null) - { - foreach (var token in tokens) - { - xml.Add(new XElement("token", new XAttribute("name", token.Name), - new XAttribute("value", token.Value))); - } - } - var xmlBytes = Encoding.UTF8.GetBytes(xml.ToString()); - res.Body.Write(xmlBytes, 0, xmlBytes.Length); - } - - } -} diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs index fb7ea344..3e3eb9c5 100644 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/TokenExtensionTests.cs @@ -119,63 +119,5 @@ public void UpdateTokenValueReturnsFalseForUnknownToken() Assert.Equal(3, props.GetTokens().Count()); } - - //public class TestAuthHandler : IAuthenticationHandler - //{ - // private readonly AuthenticationProperties _props; - // public TestAuthHandler(AuthenticationProperties props) - // { - // _props = props; - // } - - // public Task AuthenticateAsync(AuthenticateContext context) - // { - // context.Authenticated(new ClaimsPrincipal(), _props.Items, new Dictionary()); - // return Task.FromResult(0); - // } - - // public Task ChallengeAsync(ChallengeContext context) - // { - // throw new NotImplementedException(); - // } - - // public void GetDescriptions(DescribeSchemesContext context) - // { - // throw new NotImplementedException(); - // } - - // public Task SignInAsync(SignInContext context) - // { - // throw new NotImplementedException(); - // } - - // public Task SignOutAsync(SignOutContext context) - // { - // throw new NotImplementedException(); - // } - //} - - //[Fact] - //public async Task CanGetTokenFromContext() - //{ - // var props = new AuthenticationProperties(); - // var tokens = new List(); - // var tok1 = new AuthenticationToken { Name = "One", Value = "1" }; - // var tok2 = new AuthenticationToken { Name = "Two", Value = "2" }; - // var tok3 = new AuthenticationToken { Name = "Three", Value = "3" }; - // tokens.Add(tok1); - // tokens.Add(tok2); - // tokens.Add(tok3); - // props.StoreTokens(tokens); - - // var context = new DefaultHttpContext(); - // var handler = new TestAuthHandler(props); - // context.Features.Set(new HttpAuthenticationFeature() { Handler = handler }); - - // Assert.Equal("1", await context.GetTokenAsync("One")); - // Assert.Equal("2", await context.GetTokenAsync("Two")); - // Assert.Equal("3", await context.GetTokenAsync("Three")); - //} - } } diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs b/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs deleted file mode 100644 index f7128a6f..00000000 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/Transaction.cs +++ /dev/null @@ -1,62 +0,0 @@ -// 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.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Xml.Linq; - -namespace Microsoft.AspNetCore.Authentication -{ - public class Transaction - { - public HttpRequestMessage Request { get; set; } - public HttpResponseMessage Response { get; set; } - - public IList SetCookie { get; set; } - - public string ResponseText { get; set; } - public XElement ResponseElement { get; set; } - - public string AuthenticationCookieValue - { - get - { - if (SetCookie != null && SetCookie.Count > 0) - { - var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme + "=")); - if (authCookie != null) - { - return authCookie.Substring(0, authCookie.IndexOf(';')); - } - } - - return null; - } - } - - public string FindClaimValue(string claimType, string issuer = null) - { - var claim = ResponseElement.Elements("claim") - .SingleOrDefault(elt => elt.Attribute("type").Value == claimType && - (issuer == null || elt.Attribute("issuer").Value == issuer)); - if (claim == null) - { - return null; - } - return claim.Attribute("value").Value; - } - - public string FindTokenValue(string name) - { - var claim = ResponseElement.Elements("token") - .SingleOrDefault(elt => elt.Attribute("name").Value == name); - if (claim == null) - { - return null; - } - return claim.Attribute("value").Value; - } - - } -} From a9e2842fb86609428a8c68eea1426a28e125107b Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 13:27:17 -0700 Subject: [PATCH 11/16] Ordinal --- .../AuthenticationHandlerProvider.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs index 408c1b2f..58684d61 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs @@ -1,6 +1,7 @@ // 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; @@ -18,7 +19,7 @@ public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes) public IAuthenticationSchemeProvider Schemes { get; } // handler instance cache, need to initialize once per request - private Dictionary _handlerMap = new Dictionary(); + private Dictionary _handlerMap = new Dictionary(StringComparer.Ordinal); public async Task GetHandlerAsync(HttpContext context, string authenticationScheme) { From 2a2327ac828a4943e7373ec5da77b3ec0b7bcd22 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 13:29:18 -0700 Subject: [PATCH 12/16] PR cleanup --- .../AuthenticationOptions.cs | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index ad757917..175e323e 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -21,7 +21,7 @@ public IEnumerable Schemes } } - public IDictionary SchemeMap { get; } = new Dictionary(); // case sensitive? + public IDictionary SchemeMap { get; } = new Dictionary(StringComparer.Ordinal); public void AddScheme(string name, Action configureBuilder) { @@ -44,24 +44,6 @@ public void AddScheme(string name, Action configure SchemeMap[name] = builder; } - public void ConfigureScheme(string name, Action configureBuilder) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (configureBuilder == null) - { - throw new ArgumentNullException(nameof(configureBuilder)); - } - if (!SchemeMap.ContainsKey(name)) - { - throw new InvalidOperationException("Scheme does not exists: " + name); - } - - configureBuilder(SchemeMap[name]); - } - public string DefaultAuthenticationScheme { get; set; } public string DefaultSignInScheme { get; set; } public string DefaultChallengeScheme { get; set; } From 55f136bc6fd851a4d2811b189530c60b0332dd25 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 16:39:19 -0700 Subject: [PATCH 13/16] Add doc comments + cleanup --- .../AuthenticationOptions.cs | 8 +- .../AuthenticationScheme.cs | 16 +++ .../IAuthenticationFeature.cs | 2 +- .../IAuthenticationHandlerProvider.cs | 2 +- .../IAuthenticationSchemeProvider.cs | 4 +- .../IAuthenticationService.cs | 36 +++++- ...NetCore.Authentication.Abstractions.csproj | 1 + .../SignInContext.cs | 13 ++ .../SignOutContext.cs | 9 ++ ...ticationCoreServiceCollectionExtensions.cs | 14 ++- .../AuthenticationFeature.cs | 7 ++ .../AuthenticationHandlerProvider.cs | 16 +++ .../AuthenticationSchemeProvider.cs | 42 ++++++- .../AuthenticationService.cs | 116 +++++++++++------- ...soft.AspNetCore.Authentication.Core.csproj | 1 + .../NoopClaimsTransformation.cs | 5 + 16 files changed, 234 insertions(+), 58 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index 175e323e..0a7cf925 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -13,13 +13,7 @@ public class AuthenticationOptions /// /// Returns the schemes in the order they were added (important for request handling priority) /// - public IEnumerable Schemes - { - get - { - return _schemes; - } - } + public IEnumerable Schemes => _schemes; public IDictionary SchemeMap { get; } = new Dictionary(StringComparer.Ordinal); diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs index afc0cb68..4d30dd11 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs @@ -6,8 +6,17 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// AuthenticationSchemes are basically a name for a specific + /// handlerType. + /// public class AuthenticationScheme { + /// + /// Constructor. + /// + /// The name for the authentication scheme. + /// The type that handles this scheme. public AuthenticationScheme(string name, Type handlerType) { if (name == null) @@ -28,7 +37,14 @@ public AuthenticationScheme(string name, Type handlerType) } // TODO: add display name? + /// + /// The name of the authentication scheme. + /// public string Name { get; } + + /// + /// The type that handles this scheme. + /// public Type HandlerType { get; } } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs index 8ab100d1..43e5a13b 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationFeature.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Authentication { /// - /// Feature used to remember the original path/base. + /// Used to capture path info so redirects can be computed properly within an app.Map(). /// public interface IAuthenticationFeature { diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs index adb044af..0507f51d 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationHandlerProvider.cs @@ -16,7 +16,7 @@ public interface IAuthenticationHandlerProvider /// /// The context. /// The name of the authentication scheme being handled. - /// + /// The handler instance. Task GetHandlerAsync(HttpContext context, string authenticationScheme); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs index 3ee8d8c6..4b36abda 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationSchemeProvider.cs @@ -43,7 +43,7 @@ public interface IAuthenticationSchemeProvider /// /// Returns the scheme that will be used by default for . - /// This is typically specified via . + /// This is typically specified via . /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. /// /// The scheme that will be used by default for . @@ -64,7 +64,7 @@ public interface IAuthenticationSchemeProvider /// /// Returns the schemes in priority order for request handling. /// - /// + /// The schemes in priority order for request handling Task> GetRequestHandlerSchemesAsync(); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs index 6a537885..ec54325e 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/IAuthenticationService.cs @@ -7,12 +7,46 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Used to provide authentication. + /// public interface IAuthenticationService { + /// + /// Authenticate for the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The result. Task AuthenticateAsync(HttpContext context, string scheme); + + /// + /// Challenge the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The . + /// The . + /// A task. Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior); - Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties); + + /// + /// Sign a principal in for the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The to sign in. + /// The . + /// A task. Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties); + + /// + /// Sign out the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The . + /// A task. Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties); } } diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj index 0b08bca4..aa2fae7f 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/Microsoft.AspNetCore.Authentication.Abstractions.csproj @@ -6,6 +6,7 @@ $(NoWarn);CS1591 true aspnetcore;authentication;security + false diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs index f080de43..e89b663a 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignInContext.cs @@ -7,8 +7,18 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Context used for sign out. + /// public class SignInContext : BaseAuthenticationContext { + /// + /// Constructor. + /// + /// The context. + /// The name of the authentication scheme. + /// The user to sign in. + /// The properties. public SignInContext(HttpContext context, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) : base(context, authenticationScheme, properties) { @@ -19,6 +29,9 @@ public SignInContext(HttpContext context, string authenticationScheme, ClaimsPri Principal = principal; } + /// + /// The user to sign in. + /// public ClaimsPrincipal Principal { get; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs index c4a6f139..307a3af8 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/SignOutContext.cs @@ -5,8 +5,17 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Context used to sign out. + /// public class SignOutContext : BaseAuthenticationContext { + /// + /// Constructor. + /// + /// The context. + /// The name of the authentication scheme. + /// The properties. public SignOutContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) : base(context, authenticationScheme, properties) { } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs index d95ec425..fdf85a9b 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationCoreServiceCollectionExtensions.cs @@ -2,11 +2,8 @@ // 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 Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { @@ -15,6 +12,11 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class AuthenticationCoreServiceCollectionExtensions { + /// + /// Add core authentication services needed for . + /// + /// The . + /// The service collection. public static IServiceCollection AddAuthenticationCore(this IServiceCollection services) { if (services == null) @@ -29,6 +31,12 @@ public static IServiceCollection AddAuthenticationCore(this IServiceCollection s return services; } + /// + /// Add core authentication services needed for . + /// + /// The . + /// Used to configure the . + /// The service collection. public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action configureOptions) { if (services == null) { diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs index b53ffead..3282cbf4 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationFeature.cs @@ -10,7 +10,14 @@ namespace Microsoft.AspNetCore.Authentication /// public class AuthenticationFeature : IAuthenticationFeature { + /// + /// The original path base. + /// public PathString OriginalPathBase { get; set; } + + /// + /// The original path. + /// public PathString OriginalPath { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs index 58684d61..c4921e53 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationHandlerProvider.cs @@ -9,18 +9,34 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Implementation of . + /// public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider { + /// + /// Constructor. + /// + /// The . public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes) { Schemes = schemes; } + /// + /// The . + /// public IAuthenticationSchemeProvider Schemes { get; } // handler instance cache, need to initialize once per request private Dictionary _handlerMap = new Dictionary(StringComparer.Ordinal); + /// + /// Returns the handler instance that will be used. + /// + /// The context. + /// The name of the authentication scheme being handled. + /// The handler instance. public async Task GetHandlerAsync(HttpContext context, string authenticationScheme) { if (_handlerMap.ContainsKey(authenticationScheme)) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index ee7ab955..fe347d6e 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -12,10 +12,14 @@ namespace Microsoft.AspNetCore.Authentication { /// - /// Builds the actual AuthenticationScheme instances from the AuthenticationOptions. + /// Implements . /// public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider { + /// + /// Constructor. + /// + /// The options. public AuthenticationSchemeProvider(IOptions options) { _options = options.Value; @@ -31,9 +35,14 @@ public AuthenticationSchemeProvider(IOptions options) private readonly object _lock = new object(); private IDictionary _map = new Dictionary(StringComparer.Ordinal); - private List _requestHandlers = new List(); + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . public Task GetDefaultAuthenticateSchemeAsync() { if (_options.DefaultAuthenticationScheme != null) @@ -47,6 +56,12 @@ public Task GetDefaultAuthenticateSchemeAsync() return Task.FromResult(null); } + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . public Task GetDefaultChallengeSchemeAsync() { if (_options.DefaultChallengeScheme != null) @@ -60,6 +75,12 @@ public Task GetDefaultChallengeSchemeAsync() return Task.FromResult(null); } + /// + /// Returns the scheme that will be used by default for . + /// This is typically specified via . + /// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. + /// + /// The scheme that will be used by default for . public Task GetDefaultSignInSchemeAsync() { if (_options.DefaultSignInScheme != null) @@ -73,6 +94,11 @@ public Task GetDefaultSignInSchemeAsync() return Task.FromResult(null); } + /// + /// Returns the matching the name, or null. + /// + /// The name of the authenticationScheme. + /// The scheme or null if not found. public Task GetSchemeAsync(string name) { if (_map.ContainsKey(name)) @@ -82,11 +108,19 @@ public Task GetSchemeAsync(string name) return Task.FromResult(null); } + /// + /// Returns the schemes in priority order for request handling. + /// + /// The schemes in priority order for request handling public Task> GetRequestHandlerSchemesAsync() { return Task.FromResult>(_requestHandlers); } + /// + /// Registers a scheme for use by . + /// + /// The scheme. public void AddScheme(AuthenticationScheme scheme) { if (_map.ContainsKey(scheme.Name)) @@ -107,6 +141,10 @@ public void AddScheme(AuthenticationScheme scheme) } } + /// + /// Removes a scheme, preventing it from being used by . + /// + /// The name of the authenticationScheme being removed. public void RemoveScheme(string name) { if (!_map.ContainsKey(name)) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs index e4fbe76f..9b8837f2 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationService.cs @@ -8,8 +8,17 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Implements . + /// public class AuthenticationService : IAuthenticationService { + /// + /// Constructor. + /// + /// The . + /// The . + /// The The . public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform) { Schemes = schemes; @@ -17,33 +26,47 @@ public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticat Transform = transform; } + /// + /// Used to lookup AuthenticationSchemes. + /// public IAuthenticationSchemeProvider Schemes { get; } - + /// + /// Used to resolve IAuthenticationHandler instances. + /// public IAuthenticationHandlerProvider Handlers { get; } + /// + /// Used for claims transformation. + /// public IClaimsTransformation Transform { get; } - public virtual async Task AuthenticateAsync(HttpContext httpContext, string authenticationScheme) + /// + /// Authenticate for the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The result. + public virtual async Task AuthenticateAsync(HttpContext context, string scheme) { - if (authenticationScheme == null) + if (scheme == null) { var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); - authenticationScheme = defaultScheme?.Name; - if (authenticationScheme == null) + scheme = defaultScheme?.Name; + if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); } } - var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { - throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {authenticationScheme}"); + throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {scheme}"); } - var context = new AuthenticateContext(httpContext, authenticationScheme); - var result = await handler.AuthenticateAsync(context); + var authContext = new AuthenticateContext(context, scheme); + var result = await handler.AuthenticateAsync(authContext); if (result.Succeeded) { var transformed = await Transform.TransformAsync(result.Principal); @@ -52,82 +75,93 @@ public virtual async Task AuthenticateAsync(HttpContext http return result; } - public virtual async Task ChallengeAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior) + /// + /// Challenge the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The . + /// The . + /// A task. + public virtual async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior) { - if (authenticationScheme == null) + if (scheme == null) { var defaultChallengeScheme = await Schemes.GetDefaultChallengeSchemeAsync(); - authenticationScheme = defaultChallengeScheme?.Name; - if (authenticationScheme == null) + scheme = defaultChallengeScheme?.Name; + if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultChallengeScheme found."); } } - var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { - throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}"); } - var challengeContext = new ChallengeContext(httpContext, authenticationScheme, properties, behavior); + var challengeContext = new ChallengeContext(context, scheme, properties, behavior); await handler.ChallengeAsync(challengeContext); } - public virtual async Task SignInAsync(HttpContext httpContext, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) + /// + /// Sign a principal in for the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The to sign in. + /// The . + /// A task. + public virtual async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) { if (principal == null) { throw new ArgumentNullException(nameof(principal)); } - if (authenticationScheme == null) + if (scheme == null) { var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync(); - authenticationScheme = defaultScheme?.Name; - if (authenticationScheme == null) + scheme = defaultScheme?.Name; + if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignInScheme found."); } } - var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { - throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}"); } - var signInContext = new SignInContext(httpContext, authenticationScheme, principal, properties); + var signInContext = new SignInContext(context, scheme, principal, properties); await handler.SignInAsync(signInContext); } - public virtual async Task SignOutAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties) + /// + /// Sign out the specified authentication scheme. + /// + /// The . + /// The name of the authentication scheme. + /// The . + /// A task. + public virtual async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties) { - if (string.IsNullOrEmpty(authenticationScheme)) + if (string.IsNullOrEmpty(scheme)) { - throw new ArgumentException(nameof(authenticationScheme)); + throw new ArgumentException(nameof(scheme)); } - var handler = await Handlers.GetHandlerAsync(httpContext, authenticationScheme); + var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { - throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {authenticationScheme}"); + throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}"); } - var signOutContext = new SignOutContext(httpContext, authenticationScheme, properties); + var signOutContext = new SignOutContext(context, scheme, properties); await handler.SignOutAsync(signOutContext); } - - // Deny access (typically a 403) - public virtual Task ForbidAsync(HttpContext httpContext, string authenticationScheme, AuthenticationProperties properties) - { - if (authenticationScheme == null) - { - throw new ArgumentNullException(nameof(authenticationScheme)); - } - - return ChallengeAsync(httpContext, authenticationScheme, properties, ChallengeBehavior.Forbidden); - } - } } diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj index d5aa75e7..657706d7 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -9,6 +9,7 @@ $(NoWarn);CS1591 true aspnetcore;authentication;security + false diff --git a/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs b/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs index c9d87d7c..83c488fe 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/NoopClaimsTransformation.cs @@ -11,6 +11,11 @@ namespace Microsoft.AspNetCore.Authentication /// public class NoopClaimsTransformation : IClaimsTransformation { + /// + /// Returns the principal unchanged. + /// + /// The user. + /// The principal unchanged. public virtual Task TransformAsync(ClaimsPrincipal principal) { return Task.FromResult(principal); From f57aacffe7a30517bff7e1283a15f97c53429a64 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 16:55:32 -0700 Subject: [PATCH 14/16] Add missing comments --- .../AuthenticationOptions.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs index 0a7cf925..5f688d0f 100644 --- a/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationOptions.cs @@ -15,8 +15,16 @@ public class AuthenticationOptions /// public IEnumerable Schemes => _schemes; + /// + /// Maps schemes by name. + /// public IDictionary SchemeMap { get; } = new Dictionary(StringComparer.Ordinal); + /// + /// Adds an . + /// + /// The name of the scheme being added. + /// Configures the scheme. public void AddScheme(string name, Action configureBuilder) { if (name == null) @@ -38,8 +46,19 @@ public void AddScheme(string name, Action configure SchemeMap[name] = builder; } + /// + /// Used by as the default scheme by . + /// public string DefaultAuthenticationScheme { get; set; } + + /// + /// Used by as the default scheme by . + /// public string DefaultSignInScheme { get; set; } + + /// + /// Used by as the default scheme by . + /// public string DefaultChallengeScheme { get; set; } } } From 763e589cda9ace32f257c6623d9b8d05fd2f7fb9 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Fri, 31 Mar 2017 11:29:32 -0700 Subject: [PATCH 15/16] Extract versions --- .../Microsoft.AspNetCore.Authentication.Core.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj index 657706d7..61628336 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj +++ b/src/Microsoft.AspNetCore.Authentication.Core/Microsoft.AspNetCore.Authentication.Core.csproj @@ -4,7 +4,6 @@ ASP.NET Core common types used by the various authentication middleware components. - 1.2.0 netstandard1.3;net46 $(NoWarn);CS1591 true @@ -16,7 +15,7 @@ - + From 4a1ffdaa6b9c2a3d1e1f5a94f35502c6031bd056 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Fri, 31 Mar 2017 11:32:06 -0700 Subject: [PATCH 16/16] Fix test csproj --- ...rosoft.AspNetCore.Authentication.Core.Test.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj index 1a967ac6..925f5aa0 100644 --- a/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj +++ b/test/Microsoft.AspNetCore.Authentication.Core.Test/Microsoft.AspNetCore.Authentication.Core.Test.csproj @@ -2,15 +2,15 @@ - netcoreapp1.1;net46 - netcoreapp1.1 + netcoreapp2.0;net46 + netcoreapp2.0 - - - - + + + +