Initial Auth 2.0 checkin
This commit is contained in:
parent
a0bb843dd5
commit
13925be91e
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class used by <see cref="IAuthenticationHandler"/> methods.
|
||||
/// </summary>
|
||||
public class AuthenticateContext : BaseAuthenticationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme.</param>
|
||||
public AuthenticateContext(HttpContext context, string authenticationScheme) : base(context, authenticationScheme, properties: null)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the result of an Authenticate call
|
||||
/// </summary>
|
||||
public class AuthenticateResult
|
||||
{
|
||||
private AuthenticateResult() { }
|
||||
|
||||
/// <summary>
|
||||
/// If a ticket was produced, authenticate was successful.
|
||||
/// </summary>
|
||||
public bool Succeeded => Ticket != null;
|
||||
|
||||
/// <summary>
|
||||
/// The authentication ticket.
|
||||
/// </summary>
|
||||
public AuthenticationTicket Ticket { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the claims-principal with authenticated user identities.
|
||||
/// </summary>
|
||||
public ClaimsPrincipal Principal => Ticket?.Principal;
|
||||
|
||||
/// <summary>
|
||||
/// Additional state values for the authentication session.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties => Ticket?.Properties;
|
||||
|
||||
/// <summary>
|
||||
/// Holds failure information from the authentication.
|
||||
/// </summary>
|
||||
public Exception Failure { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that stage of authentication was directly handled by user intervention and no
|
||||
/// further processing should be attempted.
|
||||
/// </summary>
|
||||
public bool Handled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was no information returned for this authentication scheme.
|
||||
/// </summary>
|
||||
public bool Nothing { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that authentication was successful.
|
||||
/// </summary>
|
||||
/// <param name="ticket">The ticket representing the authentication result.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult Success(AuthenticationTicket ticket)
|
||||
{
|
||||
if (ticket == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ticket));
|
||||
}
|
||||
return new AuthenticateResult() { Ticket = ticket };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that stage of authentication was directly handled by user intervention and no
|
||||
/// further processing should be attempted.
|
||||
/// </summary>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult Handle()
|
||||
{
|
||||
return new AuthenticateResult() { Handled = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was no information returned for this authentication scheme.
|
||||
/// </summary>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult None()
|
||||
{
|
||||
return new AuthenticateResult() { Nothing = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was a failure during authentication.
|
||||
/// </summary>
|
||||
/// <param name="failure">The failure exception.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult Fail(Exception failure)
|
||||
{
|
||||
return new AuthenticateResult() { Failure = failure };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there was a failure during authentication.
|
||||
/// </summary>
|
||||
/// <param name="failureMessage">The failure message.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public static AuthenticateResult Fail(string failureMessage)
|
||||
{
|
||||
return new AuthenticateResult() { Failure = new Exception(failureMessage) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to expose Authentication on HttpContext.
|
||||
/// </summary>
|
||||
public static class AuthenticationHttpContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension method for authenticate using the <see cref="AuthenticationOptions.DefaultAuthenticationScheme"/> scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <returns>The <see cref="AuthenticateResult"/>.</returns>
|
||||
public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context) =>
|
||||
context.AuthenticateAsync(scheme: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for authenticate.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The <see cref="AuthenticateResult"/>.</returns>
|
||||
public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Challenge.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public static Task ChallengeAsync(this HttpContext context, string scheme) =>
|
||||
context.ChallengeAsync(scheme, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for authenticate using the <see cref="AuthenticationOptions.DefaultChallengeScheme"/> scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task ChallengeAsync(this HttpContext context) =>
|
||||
context.ChallengeAsync(scheme: null, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Challenge.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties) =>
|
||||
context.ChallengeAsync(scheme, properties: properties, behavior: ChallengeBehavior.Automatic);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Challenge.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <param name="behavior">The <see cref="ChallengeBehavior"/> behavior.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().ChallengeAsync(context, scheme, properties, behavior);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Forbid.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task ForbidAsync(this HttpContext context, string scheme) =>
|
||||
context.ForbidAsync(scheme, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for Forbid.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task ForbidAsync(this HttpContext context, string scheme, AuthenticationProperties properties) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().ChallengeAsync(context, scheme, properties, ChallengeBehavior.Forbidden);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignIn.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="principal">The user.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal) =>
|
||||
context.SignInAsync(scheme, principal, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignIn using the <see cref="AuthenticationOptions.DefaultSignInScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="principal">The user.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal) =>
|
||||
context.SignInAsync(scheme: null, principal: principal, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignIn using the <see cref="AuthenticationOptions.DefaultSignInScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="principal">The user.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal, AuthenticationProperties properties) =>
|
||||
context.SignInAsync(scheme: null, principal: principal, properties: properties);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignIn.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="principal">The user.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignOut.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The task.</returns>
|
||||
public static Task SignOutAsync(this HttpContext context, string scheme) => context.SignOutAsync(scheme, properties: null);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for SignOut.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns></returns>
|
||||
public static Task SignOutAsync(this HttpContext context, string scheme, AuthenticationProperties properties) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().SignOutAsync(context, scheme, properties);
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for getting the value of an authentication token.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="tokenName">The name of the token.</param>
|
||||
/// <returns>The value of the token.</returns>
|
||||
public static Task<string> GetTokenAsync(this HttpContext context, string scheme, string tokenName) =>
|
||||
context.RequestServices.GetRequiredService<IAuthenticationService>().GetTokenAsync(context, scheme, tokenName);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
public class AuthenticationOptions
|
||||
{
|
||||
private readonly IList<AuthenticationSchemeBuilder> _schemes = new List<AuthenticationSchemeBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the schemes in the order they were added (important for request handling priority)
|
||||
/// </summary>
|
||||
public IEnumerable<AuthenticationSchemeBuilder> Schemes => _schemes;
|
||||
|
||||
/// <summary>
|
||||
/// Maps schemes by name.
|
||||
/// </summary>
|
||||
public IDictionary<string, AuthenticationSchemeBuilder> SchemeMap { get; } = new Dictionary<string, AuthenticationSchemeBuilder>(StringComparer.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="AuthenticationScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the scheme being added.</param>
|
||||
/// <param name="configureBuilder">Configures the scheme.</param>
|
||||
public void AddScheme(string name, Action<AuthenticationSchemeBuilder> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by as the default scheme by <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.
|
||||
/// </summary>
|
||||
public string DefaultAuthenticationScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used by as the default scheme by <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.
|
||||
/// </summary>
|
||||
public string DefaultSignInScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used by as the default scheme by <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties, ChallengeBehavior)"/>.
|
||||
/// </summary>
|
||||
public string DefaultChallengeScheme { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Dictionary used to store state values about the authentication session.
|
||||
/// </summary>
|
||||
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";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationProperties"/> class
|
||||
/// </summary>
|
||||
public AuthenticationProperties()
|
||||
: this(items: null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationProperties"/> class
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public AuthenticationProperties(IDictionary<string, string> items)
|
||||
{
|
||||
Items = items ?? new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State values about the authentication session.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Items { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the authentication session is persisted across multiple requests.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the full path or absolute URI to be used as an http redirect response value.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time at which the authentication ticket was issued.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time at which the authentication ticket expires.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if refreshing the authentication session should be allowed.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// AuthenticationSchemes assign a name to a specific <see cref="IAuthenticationHandler"/>
|
||||
/// handlerType.
|
||||
/// </summary>
|
||||
public class AuthenticationScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="name">The name for the authentication scheme.</param>
|
||||
/// <param name="handlerType">The <see cref="IAuthenticationHandler"/> type that handles this scheme.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the authentication scheme.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthenticationHandler"/> type that handles this scheme.
|
||||
/// </summary>
|
||||
public Type HandlerType { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to build <see cref="AuthenticationScheme"/>s.
|
||||
/// </summary>
|
||||
public class AuthenticationSchemeBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the scheme being built.</param>
|
||||
public AuthenticationSchemeBuilder(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the scheme being built.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthenticationHandler"/> type responsible for this scheme.
|
||||
/// </summary>
|
||||
public Type HandlerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Builds the <see cref="AuthenticationScheme"/> instance.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public AuthenticationScheme Build() => new AuthenticationScheme(Name, HandlerType);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains user identity information as well as additional authentication state.
|
||||
/// </summary>
|
||||
public class AuthenticationTicket
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationTicket"/> class
|
||||
/// </summary>
|
||||
/// <param name="principal">the <see cref="ClaimsPrincipal"/> that represents the authenticated user.</param>
|
||||
/// <param name="properties">additional properties that can be consumed by the user or runtime.</param>
|
||||
/// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param>
|
||||
public AuthenticationTicket(ClaimsPrincipal principal, AuthenticationProperties properties, string authenticationScheme)
|
||||
{
|
||||
if (principal == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(principal));
|
||||
}
|
||||
|
||||
AuthenticationScheme = authenticationScheme;
|
||||
Principal = principal;
|
||||
Properties = properties ?? new AuthenticationProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationTicket"/> class
|
||||
/// </summary>
|
||||
/// <param name="principal">the <see cref="ClaimsPrincipal"/> that represents the authenticated user.</param>
|
||||
/// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param>
|
||||
public AuthenticationTicket(ClaimsPrincipal principal, string authenticationScheme)
|
||||
: this(principal, properties: null, authenticationScheme: authenticationScheme)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication type.
|
||||
/// </summary>
|
||||
public string AuthenticationScheme { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the claims-principal with authenticated user identities.
|
||||
/// </summary>
|
||||
public ClaimsPrincipal Principal { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional state values for the authentication session.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Name/Value representing an token.
|
||||
/// </summary>
|
||||
public class AuthenticationToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Value.
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Base context for authentication.
|
||||
/// </summary>
|
||||
public abstract class BaseAuthenticationContext : BaseContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the scheme.</param>
|
||||
/// <param name="properties">The properties.</param>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the scheme.
|
||||
/// </summary>
|
||||
public string AuthenticationScheme { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the extra meta-data arriving with the authentication. May be altered.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties { get; protected set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class used by other context classes.
|
||||
/// </summary>
|
||||
public abstract class BaseContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="context">The request context.</param>
|
||||
protected BaseContext(HttpContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
HttpContext = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The context.
|
||||
/// </summary>
|
||||
public HttpContext HttpContext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The request.
|
||||
/// </summary>
|
||||
public HttpRequest Request
|
||||
{
|
||||
get { return HttpContext.Request; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The response.
|
||||
/// </summary>
|
||||
public HttpResponse Response
|
||||
{
|
||||
get { return HttpContext.Response; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls how challenge will behave (i.e. 401 vs 403).
|
||||
/// </summary>
|
||||
public enum ChallengeBehavior
|
||||
{
|
||||
Automatic,
|
||||
Unauthorized,
|
||||
Forbidden
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Context used for challenges.
|
||||
/// </summary>
|
||||
public class ChallengeContext : BaseAuthenticationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the scheme.</param>
|
||||
public ChallengeContext(HttpContext httpContext, string authenticationScheme)
|
||||
: this(httpContext, authenticationScheme, properties: null, behavior: ChallengeBehavior.Automatic)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the scheme.</param>
|
||||
/// <param name="properties">The properties.</param>
|
||||
/// <param name="behavior">The challenge behavior.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The challenge behavior.
|
||||
/// </summary>
|
||||
public ChallengeBehavior Behavior { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to capture path info so redirects can be computed properly within an app.Map().
|
||||
/// </summary>
|
||||
public interface IAuthenticationFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The original path base.
|
||||
/// </summary>
|
||||
PathString OriginalPathBase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The original path.
|
||||
/// </summary>
|
||||
PathString OriginalPath { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Created per request to handle authentication for to a particular scheme.
|
||||
/// </summary>
|
||||
public interface IAuthenticationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// The handler should initialize anything it needs from the request and scheme here.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The <see cref="AuthenticationScheme"/> scheme.</param>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <returns></returns>
|
||||
Task InitializeAsync(AuthenticationScheme scheme, HttpContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Authentication behavior.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="AuthenticateContext"/> context.</param>
|
||||
/// <returns>The <see cref="AuthenticateResult"/> result.</returns>
|
||||
Task<AuthenticateResult> AuthenticateAsync(AuthenticateContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Challenge behavior.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ChallengeContext"/> context.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task ChallengeAsync(ChallengeContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Handle sign in.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="SignInContext"/> context.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignInAsync(SignInContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Signout behavior.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="SignOutContext"/> context.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignOutAsync(SignOutContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the appropriate IAuthenticationHandler instance for the authenticationScheme and request.
|
||||
/// </summary>
|
||||
public interface IAuthenticationHandlerProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the handler instance that will be used.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme being handled.</param>
|
||||
/// <returns>The handler instance.</returns>
|
||||
Task<IAuthenticationHandler> GetHandlerAsync(HttpContext context, string authenticationScheme);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to determine if a handler wants to participate in request processing.
|
||||
/// </summary>
|
||||
public interface IAuthenticationRequestHandler : IAuthenticationHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if request processing should stop.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<bool> HandleRequestAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for managing what authenticationSchemes are supported.
|
||||
/// </summary>
|
||||
public interface IAuthenticationSchemeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all currently registered <see cref="AuthenticationScheme"/>s.
|
||||
/// </summary>
|
||||
/// <returns>All currently registered <see cref="AuthenticationScheme"/>s.</returns>
|
||||
Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="AuthenticationScheme"/> matching the name, or null.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme.</param>
|
||||
/// <returns>The scheme or null if not found.</returns>
|
||||
Task<AuthenticationScheme> GetSchemeAsync(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultAuthenticationScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.</returns>
|
||||
Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties, ChallengeBehavior)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultChallengeScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties, ChallengeBehavior)"/>.</returns>
|
||||
Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignInScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.</returns>
|
||||
Task<AuthenticationScheme> GetDefaultSignInSchemeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a scheme for use by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The scheme.</param>
|
||||
void AddScheme(AuthenticationScheme scheme);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a scheme, preventing it from being used by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme being removed.</param>
|
||||
void RemoveScheme(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the schemes in priority order for request handling.
|
||||
/// </summary>
|
||||
/// <returns>The schemes in priority order for request handling</returns>
|
||||
Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to provide authentication.
|
||||
/// </summary>
|
||||
public interface IAuthenticationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Authenticate for the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The result.</returns>
|
||||
Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme);
|
||||
|
||||
/// <summary>
|
||||
/// Challenge the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <param name="behavior">The <see cref="ChallengeBehavior"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior);
|
||||
|
||||
/// <summary>
|
||||
/// Sign a principal in for the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/> to sign in.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties);
|
||||
|
||||
/// <summary>
|
||||
/// Sign out the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the <see cref="IAuthenticationService"/> for claims transformation.
|
||||
/// </summary>
|
||||
public interface IClaimsTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a central transformation point to change the specified principal.
|
||||
/// </summary>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/> to transform.</param>
|
||||
/// <returns>The transformed principal.</returns>
|
||||
Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
|
||||
<Import Project="..\..\build\common.props" />
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core common types used by the various authentication components.</Description>
|
||||
<TargetFrameworks>netstandard1.3;net46</TargetFrameworks>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Http.Abstractions\Microsoft.AspNetCore.Http.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.TaskCache.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Context used for sign out.
|
||||
/// </summary>
|
||||
public class SignInContext : BaseAuthenticationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme.</param>
|
||||
/// <param name="principal">The user to sign in.</param>
|
||||
/// <param name="properties">The properties.</param>
|
||||
public SignInContext(HttpContext context, string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
: base(context, authenticationScheme, properties)
|
||||
{
|
||||
if (principal == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(principal));
|
||||
}
|
||||
Principal = principal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user to sign in.
|
||||
/// </summary>
|
||||
public ClaimsPrincipal Principal { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Context used to sign out.
|
||||
/// </summary>
|
||||
public class SignOutContext : BaseAuthenticationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The properties.</param>
|
||||
public SignOutContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties)
|
||||
: base(context, authenticationScheme, properties)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for storing authentication tokens in <see cref="AuthenticationProperties"/>.
|
||||
/// </summary>
|
||||
public static class AuthenticationTokenExtensions
|
||||
{
|
||||
private static string TokenNamesKey = ".TokenNames";
|
||||
private static string TokenKeyPrefix = ".Token.";
|
||||
|
||||
/// <summary>
|
||||
/// Stores a set of authentication tokens, after removing any old tokens.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <param name="tokens">The tokens to store.</param>
|
||||
public static void StoreTokens(this AuthenticationProperties properties, IEnumerable<AuthenticationToken> 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<string>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value of a token.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <param name="tokenName">The token name.</param>
|
||||
/// <returns>The token value.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the AuthenticationTokens contained in the properties.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The authentication toekns.</returns>
|
||||
public static IEnumerable<AuthenticationToken> GetTokens(this AuthenticationProperties properties)
|
||||
{
|
||||
if (properties == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(properties));
|
||||
}
|
||||
|
||||
var tokens = new List<AuthenticationToken>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for getting the value of an authentication token.
|
||||
/// </summary>
|
||||
/// <param name="auth">The <see cref="IAuthenticationService"/>.</param>
|
||||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="tokenName">The name of the token.</param>
|
||||
/// <returns>The value of the token.</returns>
|
||||
public static async Task<string> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for setting up authentication services in an <see cref="IServiceCollection" />.
|
||||
/// </summary>
|
||||
public static class AuthenticationCoreServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add core authentication services needed for <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <returns>The service collection.</returns>
|
||||
public static IServiceCollection AddAuthenticationCore(this IServiceCollection services)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
services.TryAddScoped<IAuthenticationService, AuthenticationService>();
|
||||
services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>(); // Can be replaced with scoped ones that use DbContext
|
||||
services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();
|
||||
services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add core authentication services needed for <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <param name="configureOptions">Used to configure the <see cref="AuthenticationOptions"/>.</param>
|
||||
/// <returns>The service collection.</returns>
|
||||
public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) {
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
if (configureOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configureOptions));
|
||||
}
|
||||
|
||||
services.AddAuthenticationCore();
|
||||
services.Configure(configureOptions);
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to capture path info so redirects can be computed properly within an app.Map().
|
||||
/// </summary>
|
||||
public class AuthenticationFeature : IAuthenticationFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The original path base.
|
||||
/// </summary>
|
||||
public PathString OriginalPathBase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The original path.
|
||||
/// </summary>
|
||||
public PathString OriginalPath { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// 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;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IAuthenticationHandlerProvider"/>.
|
||||
/// </summary>
|
||||
public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="schemes">The <see cref="IAuthenticationHandlerProvider"/>.</param>
|
||||
public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes)
|
||||
{
|
||||
Schemes = schemes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthenticationHandlerProvider"/>.
|
||||
/// </summary>
|
||||
public IAuthenticationSchemeProvider Schemes { get; }
|
||||
|
||||
// handler instance cache, need to initialize once per request
|
||||
private Dictionary<string, IAuthenticationHandler> _handlerMap = new Dictionary<string, IAuthenticationHandler>(StringComparer.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the handler instance that will be used.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme being handled.</param>
|
||||
/// <returns>The handler instance.</returns>
|
||||
public async Task<IAuthenticationHandler> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements <see cref="IAuthenticationSchemeProvider"/>.
|
||||
/// </summary>
|
||||
public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="options">The <see cref="AuthenticationOptions"/> options.</param>
|
||||
public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> 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<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal);
|
||||
private List<AuthenticationScheme> _requestHandlers = new List<AuthenticationScheme>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultAuthenticationScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultAuthenticationScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultAuthenticationScheme);
|
||||
}
|
||||
if (_map.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_map.Values.First());
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties, ChallengeBehavior)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultChallengeScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties, ChallengeBehavior)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultChallengeScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultChallengeScheme);
|
||||
}
|
||||
if (_map.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_map.Values.First());
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignInScheme"/>.
|
||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.</returns>
|
||||
public Task<AuthenticationScheme> GetDefaultSignInSchemeAsync()
|
||||
{
|
||||
if (_options.DefaultSignInScheme != null)
|
||||
{
|
||||
return GetSchemeAsync(_options.DefaultSignInScheme);
|
||||
}
|
||||
if (_map.Count == 1)
|
||||
{
|
||||
return Task.FromResult(_map.Values.First());
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="AuthenticationScheme"/> matching the name, or null.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme.</param>
|
||||
/// <returns>The scheme or null if not found.</returns>
|
||||
public Task<AuthenticationScheme> GetSchemeAsync(string name)
|
||||
{
|
||||
if (_map.ContainsKey(name))
|
||||
{
|
||||
return Task.FromResult(_map[name]);
|
||||
}
|
||||
return Task.FromResult<AuthenticationScheme>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the schemes in priority order for request handling.
|
||||
/// </summary>
|
||||
/// <returns>The schemes in priority order for request handling</returns>
|
||||
public Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync()
|
||||
{
|
||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_requestHandlers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a scheme for use by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The scheme.</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a scheme, preventing it from being used by <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the authenticationScheme being removed.</param>
|
||||
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<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
||||
{
|
||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements <see cref="IAuthenticationService"/>.
|
||||
/// </summary>
|
||||
public class AuthenticationService : IAuthenticationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="schemes">The <see cref="IAuthenticationSchemeProvider"/>.</param>
|
||||
/// <param name="handlers">The <see cref="IAuthenticationRequestHandler"/>.</param>
|
||||
/// <param name="transform">The The <see cref="IClaimsTransformation"/>.</param>
|
||||
public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform)
|
||||
{
|
||||
Schemes = schemes;
|
||||
Handlers = handlers;
|
||||
Transform = transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to lookup AuthenticationSchemes.
|
||||
/// </summary>
|
||||
public IAuthenticationSchemeProvider Schemes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to resolve IAuthenticationHandler instances.
|
||||
/// </summary>
|
||||
public IAuthenticationHandlerProvider Handlers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for claims transformation.
|
||||
/// </summary>
|
||||
public IClaimsTransformation Transform { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate for the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public virtual async Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
|
||||
{
|
||||
if (scheme == null)
|
||||
{
|
||||
var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync();
|
||||
scheme = defaultScheme?.Name;
|
||||
if (scheme == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found.");
|
||||
}
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to authenticate for the scheme: {scheme}");
|
||||
}
|
||||
|
||||
var authContext = new AuthenticateContext(context, scheme);
|
||||
var result = await handler.AuthenticateAsync(authContext);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
var transformed = await Transform.TransformAsync(result.Principal);
|
||||
return AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Challenge the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <param name="behavior">The <see cref="ChallengeBehavior"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
public virtual async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties, ChallengeBehavior behavior)
|
||||
{
|
||||
if (scheme == null)
|
||||
{
|
||||
var defaultChallengeScheme = await Schemes.GetDefaultChallengeSchemeAsync();
|
||||
scheme = defaultChallengeScheme?.Name;
|
||||
if (scheme == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultChallengeScheme found.");
|
||||
}
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}");
|
||||
}
|
||||
|
||||
var challengeContext = new ChallengeContext(context, scheme, properties, behavior);
|
||||
await handler.ChallengeAsync(challengeContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sign a principal in for the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/> to sign in.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
public virtual async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
{
|
||||
if (principal == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(principal));
|
||||
}
|
||||
|
||||
if (scheme == null)
|
||||
{
|
||||
var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync();
|
||||
scheme = defaultScheme?.Name;
|
||||
if (scheme == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignInScheme found.");
|
||||
}
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}");
|
||||
}
|
||||
|
||||
var signInContext = new SignInContext(context, scheme, principal, properties);
|
||||
await handler.SignInAsync(signInContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sign out the specified authentication scheme.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The name of the authentication scheme.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <returns>A task.</returns>
|
||||
public virtual async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||
{
|
||||
if (string.IsNullOrEmpty(scheme))
|
||||
{
|
||||
throw new ArgumentException(nameof(scheme));
|
||||
}
|
||||
|
||||
var handler = await Handlers.GetHandlerAsync(context, scheme);
|
||||
if (handler == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No authentication handler is configured to handle the scheme: {scheme}");
|
||||
}
|
||||
|
||||
var signOutContext = new SignOutContext(context, scheme, properties);
|
||||
await handler.SignOutAsync(signOutContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\build\common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core common types used by the various authentication middleware components.</Description>
|
||||
<TargetFrameworks>netstandard1.3;net46</TargetFrameworks>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Authentication.Abstractions\Microsoft.AspNetCore.Authentication.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Http\Microsoft.AspNetCore.Http.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Http.Extensions\Microsoft.AspNetCore.Http.Extensions.csproj" />
|
||||
<PackageReference Include="Microsoft.Extensions.TaskCache.Sources" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Default claims transformation is a no-op.
|
||||
/// </summary>
|
||||
public class NoopClaimsTransformation : IClaimsTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the principal unchanged.
|
||||
/// </summary>
|
||||
/// <param name="principal">The user.</param>
|
||||
/// <returns>The principal unchanged.</returns>
|
||||
public virtual Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
|
||||
{
|
||||
return Task.FromResult(principal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\build\common.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.0;net46</TargetFrameworks>
|
||||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Authentication.Core\Microsoft.AspNetCore.Authentication.Core.csproj" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// 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<AuthenticationToken>();
|
||||
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<AuthenticationToken>();
|
||||
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<AuthenticationToken>();
|
||||
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<AuthenticationToken>();
|
||||
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<AuthenticationToken>();
|
||||
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());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue