Merge remote-tracking branch 'Security/rybrande/masterToSrc' into rybrande/Mondo22ToMaster
This commit is contained in:
commit
7aefd16eed
|
|
@ -30,3 +30,4 @@ project.lock.json
|
|||
/.vs/
|
||||
.vscode/
|
||||
global.json
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.2' ">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">$(MicrosoftNETCoreAppPackageVersion)</RuntimeFrameworkVersion>
|
||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
||||
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
|
||||
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
ASP.NET Security
|
||||
========
|
||||
ASP.NET Security [Archived]
|
||||
===========================
|
||||
|
||||
AppVeyor: [](https://ci.appveyor.com/project/aspnetci/Security/branch/dev)
|
||||
|
||||
Travis: [](https://travis-ci.org/aspnet/Security)
|
||||
**This GitHub project has been archived.** Ongoing development on this project can be found in <https://github.com/aspnet/AspNetCore>.
|
||||
|
||||
Contains the security and authorization middlewares for ASP.NET Core.
|
||||
|
||||
|
|
@ -14,4 +12,4 @@ A list of community projects related to authentication and security for ASP.NET
|
|||
ASP.NET Security will not include Basic Authentication middleware due to its potential insecurity and performance problems. If you host under IIS you can enable it via IIS configuration.
|
||||
|
||||
|
||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
|
||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [AspNetCore](https://github.com/aspnet/AspNetCore) repo.
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authen
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WsFedSample", "samples\WsFedSample\WsFedSample.csproj", "{5EC2E398-E46A-430D-8E4B-E91C8FC3E800}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{55052FE3-F8C2-4E6C-97B0-C02ED1DBEA62}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Security.Performance", "benchmarks\Microsoft.AspNetCore.Security.Performance\Microsoft.AspNetCore.Security.Performance.csproj", "{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -517,6 +521,22 @@ Global
|
|||
{5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|x86.Build.0 = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -549,6 +569,7 @@ Global
|
|||
{24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
|
||||
{B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
|
||||
{5EC2E398-E46A-430D-8E4B-E91C8FC3E800} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
|
||||
{556C4FAA-F4B1-4EA9-8921-CB1DF7D94C2A} = {55052FE3-F8C2-4E6C-97B0-C02ED1DBEA62}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {ABF8089E-43D0-4010-84A7-7A9DCFE49357}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Security
|
||||
{
|
||||
public class AuthorizationMiddlewareBenchmark
|
||||
{
|
||||
private AuthorizationMiddleware _authorizationMiddleware;
|
||||
private DefaultHttpContext _httpContextNoEndpoint;
|
||||
private DefaultHttpContext _httpContextHasEndpoint;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
|
||||
_authorizationMiddleware = new AuthorizationMiddleware((context) => Task.CompletedTask, policyProvider);
|
||||
|
||||
_httpContextNoEndpoint = new DefaultHttpContext();
|
||||
|
||||
var feature = new EndpointFeature
|
||||
{
|
||||
Endpoint = new Endpoint((context) => Task.CompletedTask, EndpointMetadataCollection.Empty, "Test endpoint")
|
||||
};
|
||||
_httpContextHasEndpoint = new DefaultHttpContext();
|
||||
_httpContextHasEndpoint.Features.Set<IEndpointFeature>(feature);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task Invoke_NoEndpoint_NoAuthorization()
|
||||
{
|
||||
return _authorizationMiddleware.Invoke(_httpContextNoEndpoint);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task Invoke_HasEndpoint_NoAuthorization()
|
||||
{
|
||||
return _authorizationMiddleware.Invoke(_httpContextHasEndpoint);
|
||||
}
|
||||
|
||||
private class EndpointFeature : IEndpointFeature
|
||||
{
|
||||
public Endpoint Endpoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Security
|
||||
{
|
||||
public class AuthorizationPolicyBenchmark
|
||||
{
|
||||
private DefaultAuthorizationPolicyProvider _policyProvider;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public Task CombineAsync()
|
||||
{
|
||||
return AuthorizationPolicy.CombineAsync(_policyProvider, Array.Empty<IAuthorizeData>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>Microsoft.AspNetCore.Security</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Authorization.Policy\Microsoft.AspNetCore.Authorization.Policy.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" PrivateAssets="All" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1 @@
|
|||
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
Compile the solution in Release mode (so binaries are available in release)
|
||||
|
||||
To run a specific benchmark add it as parameter.
|
||||
```
|
||||
dotnet run -c Release --framework <tfm> <benchmark_name>
|
||||
```
|
||||
|
||||
To run all benchmarks use '*' as the name.
|
||||
```
|
||||
dotnet run -c Release --framework <tfm> *
|
||||
```
|
||||
|
||||
If you run without any parameters, you'll be offered the list of all benchmarks and get to choose.
|
||||
```
|
||||
dotnet run -c Release --framework <tfm>
|
||||
```
|
||||
|
|
@ -3,50 +3,54 @@
|
|||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview2-20181004.6</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationAbstractionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
||||
<MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreDataProtectionPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDataProtectionPackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.14.2</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>
|
||||
<MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>5.2.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>
|
||||
<MicrosoftIdentityModelProtocolsWsFederationPackageVersion>5.2.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview3-27001-02</MicrosoftNETCoreApp22PackageVersion>
|
||||
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>3.0.0-build-20181114.5</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationAbstractionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreAuthenticationAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreDataProtectionPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreDataProtectionPackageVersion>
|
||||
<MicrosoftAspNetCoreDiagnosticsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreHttpPackageVersion>
|
||||
<MicrosoftAspNetCoreRoutingPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreRoutingPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestHostPackageVersion>3.0.0-alpha1-10742</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.19.8</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>
|
||||
<MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>5.3.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>
|
||||
<MicrosoftIdentityModelProtocolsWsFederationPackageVersion>5.3.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion>
|
||||
<MicrosoftNETCoreAppPackageVersion>3.0.0-preview1-26907-05</MicrosoftNETCoreAppPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||
<MicrosoftOwinSecurityCookiesPackageVersion>3.0.1</MicrosoftOwinSecurityCookiesPackageVersion>
|
||||
<MicrosoftOwinSecurityPackageVersion>3.0.1</MicrosoftOwinSecurityPackageVersion>
|
||||
<MicrosoftOwinTestingPackageVersion>3.0.1</MicrosoftOwinTestingPackageVersion>
|
||||
<MoqPackageVersion>4.10.0</MoqPackageVersion>
|
||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
||||
<SystemIdentityModelTokensJwtPackageVersion>5.2.0</SystemIdentityModelTokensJwtPackageVersion>
|
||||
<SystemIdentityModelTokensJwtPackageVersion>5.3.0</SystemIdentityModelTokensJwtPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Package Versions: Pinned" />
|
||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||
<PropertyGroup Label="Package Versions: Pinned" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
<Project>
|
||||
<Import Project="dependencies.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.Owin.Security.Interop.Test\*.csproj" Condition="'$(OS)' != 'Windows_NT'" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
||||
<LineupPackageVersion>2.2.0-*</LineupPackageVersion>
|
||||
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp22PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreAppPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>aspnet5-JwtBearerSample-20151210102827</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -64,5 +64,6 @@
|
|||
<script src="App/Scripts/userDataCtrl.js"></script>
|
||||
<script src="App/Scripts/todoListCtrl.js"></script>
|
||||
<script src="App/Scripts/todoListSvc.js"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>aspnet5-OpenIdConnectSample-20151210110318</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>aspnet5-OpenIdConnectSample-20151210110318</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace OpenIdConnectSample
|
|||
o.ResponseType = OpenIdConnectResponseType.CodeIdToken;
|
||||
o.SaveTokens = true;
|
||||
o.GetClaimsFromUserInfoEndpoint = true;
|
||||
o.AccessDeniedPath = "/access-denied-from-remote";
|
||||
|
||||
o.ClaimActions.MapAllExcept("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce");
|
||||
|
||||
|
|
@ -126,6 +127,16 @@ namespace OpenIdConnectSample
|
|||
return;
|
||||
}
|
||||
|
||||
if (context.Request.Path.Equals("/access-denied-from-remote"))
|
||||
{
|
||||
await WriteHtmlAsync(response, async res =>
|
||||
{
|
||||
await res.WriteAsync($"<h1>Access Denied error received from the remote authorization server</h1>");
|
||||
await res.WriteAsync("<a class=\"btn btn-default\" href=\"/\">Home</a>");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.Request.Path.Equals("/Account/AccessDenied"))
|
||||
{
|
||||
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>aspnet5-SocialSample-20151210111056</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -422,7 +422,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
var returnUrl = properties.RedirectUri;
|
||||
if (string.IsNullOrEmpty(returnUrl))
|
||||
{
|
||||
returnUrl = OriginalPathBase + Request.Path + Request.QueryString;
|
||||
returnUrl = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
var accessDeniedUri = Options.AccessDeniedPath + QueryString.Create(Options.ReturnUrlParameter, returnUrl);
|
||||
var redirectContext = new RedirectContext<CookieAuthenticationOptions>(Context, Scheme, Options, properties, BuildRedirectUri(accessDeniedUri));
|
||||
|
|
@ -434,7 +434,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
var redirectUri = properties.RedirectUri;
|
||||
if (string.IsNullOrEmpty(redirectUri))
|
||||
{
|
||||
redirectUri = OriginalPathBase + Request.Path + Request.QueryString;
|
||||
redirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
|
||||
var loginUri = Options.LoginPath + QueryString.Create(Options.ReturnUrlParameter, redirectUri);
|
||||
|
|
|
|||
|
|
@ -147,68 +147,5 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
/// </para>
|
||||
/// </summary>
|
||||
public TimeSpan ExpireTimeSpan { get; set; }
|
||||
|
||||
#region Obsolete API
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Name"/> on <see cref="Cookie"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Determines the cookie name used to persist the identity. The default value is ".AspNetCore.Cookies".
|
||||
/// This value should be changed if you change the name of the AuthenticationScheme, especially if your
|
||||
/// system uses the cookie authentication handler multiple times.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Name) + ".")]
|
||||
public string CookieName { get => Cookie.Name; set => Cookie.Name = value; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Domain"/> on <see cref="Cookie"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Determines the domain used to create the cookie. Is not provided by default.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Domain) + ".")]
|
||||
public string CookieDomain { get => Cookie.Domain; set => Cookie.Domain = value; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Path"/> on <see cref="Cookie"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Determines the path used to create the cookie. The default value is "/" for highest browser compatibility.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Path) + ".")]
|
||||
public string CookiePath { get => Cookie.Path; set => Cookie.Path = value; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.HttpOnly"/> on <see cref="Cookie"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Determines if the browser should allow the cookie to be accessed by client-side javascript. The
|
||||
/// default is true, which means the cookie will only be passed to http requests and is not made available
|
||||
/// to script on the page.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.HttpOnly) + ".")]
|
||||
public bool CookieHttpOnly { get => Cookie.HttpOnly; set => Cookie.HttpOnly = value; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.SecurePolicy"/> on <see cref="Cookie"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Determines if the cookie should only be transmitted on HTTPS request. The default is to limit the cookie
|
||||
/// to HTTPS requests if the page which is doing the SignIn is also HTTPS. If you have an HTTPS sign in page
|
||||
/// and portions of your site are HTTP you may need to change this value.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.SecurePolicy) + ".")]
|
||||
public CookieSecurePolicy CookieSecure { get => Cookie.SecurePolicy; set => Cookie.SecurePolicy = value; }
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to use cookie based authentication.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<DefineConstants>$(DefineConstants);SECURITY</DefineConstants>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
[
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public Microsoft.AspNetCore.Http.CookieSecurePolicy get_CookieSecure()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Boolean get_CookieHttpOnly()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.String get_CookieDomain()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.String get_CookieName()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.String get_CookiePath()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Void set_CookieDomain(System.String value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Void set_CookieHttpOnly(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Void set_CookieName(System.String value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Void set_CookiePath(System.String value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions",
|
||||
"MemberId": "public System.Void set_CookieSecure(Microsoft.AspNetCore.Http.CookieSecurePolicy value)",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support Facebook's OAuth 2.0 authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core contains middleware to support Google's OpenId and OAuth 2.0 authentication workflows.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
{
|
||||
private OpenIdConnectConfiguration _configuration;
|
||||
|
||||
public JwtBearerHandler(IOptionsMonitor<JwtBearerOptions> options, ILoggerFactory logger, UrlEncoder encoder, IDataProtectionProvider dataProtection, ISystemClock clock)
|
||||
public JwtBearerHandler(IOptionsMonitor<JwtBearerOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
|
||||
: base(options, logger, encoder, clock)
|
||||
{ }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to receive an OpenID Connect bearer token.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
[
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler : Microsoft.AspNetCore.Authentication.AuthenticationHandler<Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions>",
|
||||
"MemberId": "public .ctor(Microsoft.Extensions.Options.IOptionsMonitor<Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions> options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.DataProtection.IDataProtectionProvider dataProtection, Microsoft.AspNetCore.Authentication.ISystemClock clock)",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support the Microsoft Account authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support any standard OAuth 2.0 authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -63,6 +63,16 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
var error = query["error"];
|
||||
if (!StringValues.IsNullOrEmpty(error))
|
||||
{
|
||||
// Note: access_denied errors are special protocol errors indicating the user didn't
|
||||
// approve the authorization demand requested by the remote authorization server.
|
||||
// Since it's a frequent scenario (that is not caused by incorrect configuration),
|
||||
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
|
||||
// Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
|
||||
if (StringValues.Equals(error, "access_denied"))
|
||||
{
|
||||
return await HandleAccessDeniedErrorAsync(properties);
|
||||
}
|
||||
|
||||
var failureMessage = new StringBuilder();
|
||||
failureMessage.Append(error);
|
||||
var errorDescription = query["error_description"];
|
||||
|
|
@ -194,7 +204,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
{
|
||||
if (string.IsNullOrEmpty(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = CurrentUri;
|
||||
properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
|
||||
// OAuth2 10.12 CSRF
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support the OpenID Connect authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
properties.RedirectUri = BuildRedirectUriIfRelative(Options.SignedOutRedirectUri);
|
||||
if (string.IsNullOrWhiteSpace(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = CurrentUri;
|
||||
properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
}
|
||||
Logger.PostSignOutRedirect(properties.RedirectUri);
|
||||
|
|
@ -312,7 +312,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
// 2. CurrentUri if RedirectUri is not set)
|
||||
if (string.IsNullOrEmpty(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = CurrentUri;
|
||||
properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
Logger.PostAuthenticationLocalRedirect(properties.RedirectUri);
|
||||
|
||||
|
|
@ -520,6 +520,16 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
// if any of the error fields are set, throw error null
|
||||
if (!string.IsNullOrEmpty(authorizationResponse.Error))
|
||||
{
|
||||
// Note: access_denied errors are special protocol errors indicating the user didn't
|
||||
// approve the authorization demand requested by the remote authorization server.
|
||||
// Since it's a frequent scenario (that is not caused by incorrect configuration),
|
||||
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
|
||||
// Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
|
||||
if (string.Equals(authorizationResponse.Error, "access_denied", StringComparison.Ordinal))
|
||||
{
|
||||
return await HandleAccessDeniedErrorAsync(properties);
|
||||
}
|
||||
|
||||
return HandleRequestResult.Fail(CreateOpenIdConnectProtocolException(authorizationResponse, response: null), properties);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support Twitter's OAuth 1.0 authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -55,12 +55,14 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
|
||||
var properties = requestToken.Properties;
|
||||
|
||||
// REVIEW: see which of these are really errors
|
||||
|
||||
var denied = query["denied"];
|
||||
if (!StringValues.IsNullOrEmpty(denied))
|
||||
{
|
||||
return HandleRequestResult.Fail("The user denied permissions.", properties);
|
||||
// Note: denied errors are special protocol errors indicating the user didn't
|
||||
// approve the authorization demand requested by the remote authorization server.
|
||||
// Since it's a frequent scenario (that is not caused by incorrect configuration),
|
||||
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
|
||||
return await HandleAccessDeniedErrorAsync(properties);
|
||||
}
|
||||
|
||||
var returnedToken = query["oauth_token"];
|
||||
|
|
@ -130,7 +132,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
{
|
||||
if (string.IsNullOrEmpty(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = CurrentUri;
|
||||
properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
|
||||
// If CallbackConfirmed is false, this will throw
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
// 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.Globalization;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support the WsFederation authentication workflow.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Authentication.WsFederation
|
|||
// Save the original challenge URI so we can redirect back to it when we're done.
|
||||
if (string.IsNullOrEmpty(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = CurrentUri;
|
||||
properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
|
||||
}
|
||||
|
||||
var wsFederationMessage = new WsFederationMessage()
|
||||
|
|
|
|||
|
|
@ -46,48 +46,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
return builder;
|
||||
}
|
||||
|
||||
[Obsolete("AddScheme is obsolete. Use AddAuthentication().AddScheme instead.")]
|
||||
public static IServiceCollection AddScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, string displayName, Action<AuthenticationSchemeBuilder> configureScheme, Action<TOptions> configureOptions)
|
||||
where TOptions : AuthenticationSchemeOptions, new()
|
||||
where THandler : AuthenticationHandler<TOptions>
|
||||
{
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.AddScheme(authenticationScheme, scheme => {
|
||||
scheme.HandlerType = typeof(THandler);
|
||||
scheme.DisplayName = displayName;
|
||||
configureScheme?.Invoke(scheme);
|
||||
});
|
||||
});
|
||||
if (configureOptions != null)
|
||||
{
|
||||
services.Configure(authenticationScheme, configureOptions);
|
||||
}
|
||||
services.AddTransient<THandler>();
|
||||
return services;
|
||||
}
|
||||
|
||||
[Obsolete("AddScheme is obsolete. Use AddAuthentication().AddScheme instead.")]
|
||||
public static IServiceCollection AddScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, Action<TOptions> configureOptions)
|
||||
where TOptions : AuthenticationSchemeOptions, new()
|
||||
where THandler : AuthenticationHandler<TOptions>
|
||||
=> services.AddScheme<TOptions, THandler>(authenticationScheme, displayName: null, configureScheme: null, configureOptions: configureOptions);
|
||||
|
||||
[Obsolete("AddScheme is obsolete. Use AddAuthentication().AddScheme instead.")]
|
||||
public static IServiceCollection AddScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, string displayName, Action<TOptions> configureOptions)
|
||||
where TOptions : AuthenticationSchemeOptions, new()
|
||||
where THandler : AuthenticationHandler<TOptions>
|
||||
=> services.AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureScheme: null, configureOptions: configureOptions);
|
||||
|
||||
[Obsolete("AddScheme is obsolete. Use AddAuthentication().AddScheme instead.")]
|
||||
public static IServiceCollection AddRemoteScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, string displayName, Action<TOptions> configureOptions)
|
||||
where TOptions : RemoteAuthenticationOptions, new()
|
||||
where THandler : RemoteAuthenticationHandler<TOptions>
|
||||
{
|
||||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, EnsureSignInScheme<TOptions>>());
|
||||
return services.AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureScheme: null, configureOptions: configureOptions);
|
||||
}
|
||||
|
||||
// Used to ensure that there's always a sign in scheme
|
||||
private class EnsureSignInScheme<TOptions> : IPostConfigureOptions<TOptions> where TOptions : RemoteAuthenticationOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
// 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>
|
||||
/// Provides access denied failure context information to handler providers.
|
||||
/// </summary>
|
||||
public class AccessDeniedContext : HandleRequestContext<RemoteAuthenticationOptions>
|
||||
{
|
||||
public AccessDeniedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
RemoteAuthenticationOptions options)
|
||||
: base(context, scheme, options)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the endpoint path the user agent will be redirected to.
|
||||
/// By default, this property is set to <see cref="RemoteAuthenticationOptions.AccessDeniedPath"/>.
|
||||
/// </summary>
|
||||
public PathString AccessDeniedPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional state values for the authentication session.
|
||||
/// </summary>
|
||||
public AuthenticationProperties Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the return URL that will be flowed up to the access denied page.
|
||||
/// If <see cref="ReturnUrlParameter"/> is not set, this property is not used.
|
||||
/// </summary>
|
||||
public string ReturnUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter name that will be used to flow the return URL.
|
||||
/// By default, this property is set to <see cref="RemoteAuthenticationOptions.ReturnUrlParameter"/>.
|
||||
/// </summary>
|
||||
public string ReturnUrlParameter { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,18 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
{
|
||||
public class RemoteAuthenticationEvents
|
||||
{
|
||||
public Func<AccessDeniedContext, Task> OnAccessDenied { get; set; } = context => Task.CompletedTask;
|
||||
public Func<RemoteFailureContext, Task> OnRemoteFailure { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
public Func<TicketReceivedContext, Task> OnTicketReceived { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when there is a remote failure
|
||||
/// Invoked when an access denied error was returned by the remote server.
|
||||
/// </summary>
|
||||
public virtual Task AccessDenied(AccessDeniedContext context) => OnAccessDenied(context);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when there is a remote failure.
|
||||
/// </summary>
|
||||
public virtual Task RemoteFailure(RemoteFailureContext context) => OnRemoteFailure(context);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,17 +7,20 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
internal static class LoggingExtensions
|
||||
{
|
||||
private static Action<ILogger, string, Exception> _authSchemeAuthenticated;
|
||||
private static Action<ILogger, string, Exception> _authSchemeNotAuthenticated;
|
||||
private static Action<ILogger, string, string, Exception> _authSchemeNotAuthenticatedWithFailure;
|
||||
private static Action<ILogger, string, Exception> _authSchemeChallenged;
|
||||
private static Action<ILogger, string, Exception> _authSchemeForbidden;
|
||||
private static Action<ILogger, string, Exception> _remoteAuthenticationError;
|
||||
private static Action<ILogger, Exception> _signInHandled;
|
||||
private static Action<ILogger, Exception> _signInSkipped;
|
||||
private static Action<ILogger, string, Exception> _correlationPropertyNotFound;
|
||||
private static Action<ILogger, string, Exception> _correlationCookieNotFound;
|
||||
private static Action<ILogger, string, string, Exception> _unexpectedCorrelationCookieValue;
|
||||
private static readonly Action<ILogger, string, Exception> _authSchemeAuthenticated;
|
||||
private static readonly Action<ILogger, string, Exception> _authSchemeNotAuthenticated;
|
||||
private static readonly Action<ILogger, string, string, Exception> _authSchemeNotAuthenticatedWithFailure;
|
||||
private static readonly Action<ILogger, string, Exception> _authSchemeChallenged;
|
||||
private static readonly Action<ILogger, string, Exception> _authSchemeForbidden;
|
||||
private static readonly Action<ILogger, string, Exception> _remoteAuthenticationError;
|
||||
private static readonly Action<ILogger, Exception> _signInHandled;
|
||||
private static readonly Action<ILogger, Exception> _signInSkipped;
|
||||
private static readonly Action<ILogger, string, Exception> _correlationPropertyNotFound;
|
||||
private static readonly Action<ILogger, string, Exception> _correlationCookieNotFound;
|
||||
private static readonly Action<ILogger, string, string, Exception> _unexpectedCorrelationCookieValue;
|
||||
private static readonly Action<ILogger, Exception> _accessDeniedError;
|
||||
private static readonly Action<ILogger, Exception> _accessDeniedContextHandled;
|
||||
private static readonly Action<ILogger, Exception> _accessDeniedContextSkipped;
|
||||
|
||||
static LoggingExtensions()
|
||||
{
|
||||
|
|
@ -65,6 +68,18 @@ namespace Microsoft.Extensions.Logging
|
|||
eventId: 16,
|
||||
logLevel: LogLevel.Warning,
|
||||
formatString: "The correlation cookie value '{CorrelationCookieName}' did not match the expected value '{CorrelationCookieValue}'.");
|
||||
_accessDeniedError = LoggerMessage.Define(
|
||||
eventId: 17,
|
||||
logLevel: LogLevel.Information,
|
||||
formatString: "Access was denied by the resource owner or by the remote server.");
|
||||
_accessDeniedContextHandled = LoggerMessage.Define(
|
||||
eventId: 18,
|
||||
logLevel: LogLevel.Debug,
|
||||
formatString: "The AccessDenied event returned Handled.");
|
||||
_accessDeniedContextSkipped = LoggerMessage.Define(
|
||||
eventId: 19,
|
||||
logLevel: LogLevel.Debug,
|
||||
formatString: "The AccessDenied event returned Skipped.");
|
||||
}
|
||||
|
||||
public static void AuthenticationSchemeAuthenticated(this ILogger logger, string authenticationScheme)
|
||||
|
|
@ -121,5 +136,20 @@ namespace Microsoft.Extensions.Logging
|
|||
{
|
||||
_unexpectedCorrelationCookieValue(logger, cookieName, cookieValue, null);
|
||||
}
|
||||
|
||||
public static void AccessDeniedError(this ILogger logger)
|
||||
{
|
||||
_accessDeniedError(logger, null);
|
||||
}
|
||||
|
||||
public static void AccessDeniedContextHandled(this ILogger logger)
|
||||
{
|
||||
_accessDeniedContextHandled(logger, null);
|
||||
}
|
||||
|
||||
public static void AccessDeniedContextSkipped(this ILogger logger)
|
||||
{
|
||||
_accessDeniedContextSkipped(logger, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core common types used by the various authentication middleware components.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
@ -241,5 +242,48 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual async Task<HandleRequestResult> HandleAccessDeniedErrorAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Logger.AccessDeniedError();
|
||||
var context = new AccessDeniedContext(Context, Scheme, Options)
|
||||
{
|
||||
AccessDeniedPath = Options.AccessDeniedPath,
|
||||
Properties = properties,
|
||||
ReturnUrl = properties?.RedirectUri,
|
||||
ReturnUrlParameter = Options.ReturnUrlParameter
|
||||
};
|
||||
await Events.AccessDenied(context);
|
||||
|
||||
if (context.Result != null)
|
||||
{
|
||||
if (context.Result.Handled)
|
||||
{
|
||||
Logger.AccessDeniedContextHandled();
|
||||
}
|
||||
else if (context.Result.Skipped)
|
||||
{
|
||||
Logger.AccessDeniedContextSkipped();
|
||||
}
|
||||
|
||||
return context.Result;
|
||||
}
|
||||
|
||||
// If an access denied endpoint was specified, redirect the user agent.
|
||||
// Otherwise, invoke the RemoteFailure event for further processing.
|
||||
if (context.AccessDeniedPath.HasValue)
|
||||
{
|
||||
string uri = context.AccessDeniedPath;
|
||||
if (!string.IsNullOrEmpty(context.ReturnUrlParameter) && !string.IsNullOrEmpty(context.ReturnUrl))
|
||||
{
|
||||
uri = QueryHelpers.AddQueryString(uri, context.ReturnUrlParameter, context.ReturnUrl);
|
||||
}
|
||||
Response.Redirect(uri);
|
||||
|
||||
return HandleRequestResult.Handle();
|
||||
}
|
||||
|
||||
return HandleRequestResult.Fail("Access was denied by the resource owner or by the remote server.", properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -89,6 +89,22 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public PathString CallbackPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the optional path the user agent is redirected to if the user
|
||||
/// doesn't approve the authorization demand requested by the remote server.
|
||||
/// This property is not set by default. In this case, an exception is thrown
|
||||
/// if an access_denied response is returned by the remote authorization server.
|
||||
/// </summary>
|
||||
public PathString AccessDeniedPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the parameter used to convey the original location
|
||||
/// of the user before the remote challenge was triggered up to the access denied page.
|
||||
/// This property is only used when the <see cref="AccessDeniedPath"/> is explicitly specified.
|
||||
/// </summary>
|
||||
// Note: this deliberately matches the default parameter name used by the cookie handler.
|
||||
public string ReturnUrlParameter { get; set; } = "ReturnUrl";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication scheme corresponding to the middleware
|
||||
/// responsible of persisting user's identity after a successful authentication.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
|
||||
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRemoteScheme<T0, T1>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.String authenticationScheme, System.String displayName, System.Action<T0> configureOptions) where T0 : Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions, new() where T1 : Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<T0>",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
|
||||
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScheme<T0, T1>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.String authenticationScheme, System.Action<T0> configureOptions) where T0 : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() where T1 : Microsoft.AspNetCore.Authentication.AuthenticationHandler<T0>",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
|
||||
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScheme<T0, T1>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.String authenticationScheme, System.String displayName, System.Action<Microsoft.AspNetCore.Authentication.AuthenticationSchemeBuilder> configureScheme, System.Action<T0> configureOptions) where T0 : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() where T1 : Microsoft.AspNetCore.Authentication.AuthenticationHandler<T0>",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
|
||||
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScheme<T0, T1>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.String authenticationScheme, System.String displayName, System.Action<T0> configureOptions) where T0 : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() where T1 : Microsoft.AspNetCore.Authentication.AuthenticationHandler<T0>",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
|
|
@ -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.Authorization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to add authorization capabilities to an HTTP application pipeline.
|
||||
/// </summary>
|
||||
public static class AuthorizationAppBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the <see cref="AuthorizationMiddleware"/> to the specified <see cref="IApplicationBuilder"/>, which enables authorization capabilities.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public static IApplicationBuilder UseAuthorization(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(app));
|
||||
}
|
||||
|
||||
return app.UseMiddleware<AuthorizationMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
public static class AuthorizationEndpointConventionBuilderExtensions
|
||||
{
|
||||
public static IEndpointConventionBuilder RequireAuthorization(this IEndpointConventionBuilder builder, params IAuthorizeData[] authorizeData)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (authorizeData == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(authorizeData));
|
||||
}
|
||||
|
||||
builder.Apply(endpointBuilder =>
|
||||
{
|
||||
foreach (var data in authorizeData)
|
||||
{
|
||||
endpointBuilder.Metadata.Add(data);
|
||||
}
|
||||
});
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static IEndpointConventionBuilder RequireAuthorization(this IEndpointConventionBuilder builder, params string[] policyNames)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (policyNames == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(policyNames));
|
||||
}
|
||||
|
||||
return builder.RequireAuthorization(policyNames.Select(n => new AuthorizeAttribute(n)).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization.Policy;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Endpoints;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization
|
||||
{
|
||||
public class AuthorizationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IAuthorizationPolicyProvider _policyProvider;
|
||||
|
||||
public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
|
||||
{
|
||||
if (next == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(next));
|
||||
}
|
||||
|
||||
if (policyProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(policyProvider));
|
||||
}
|
||||
|
||||
_next = next;
|
||||
_policyProvider = policyProvider;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var endpoint = context.GetEndpoint();
|
||||
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
|
||||
var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
|
||||
if (policy == null)
|
||||
{
|
||||
await _next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Policy evaluator has transient lifetime so it fetched from request services instead of injecting in constructor
|
||||
var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
|
||||
|
||||
var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context);
|
||||
|
||||
// Allow Anonymous skips all authorization
|
||||
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
|
||||
{
|
||||
await _next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that the resource will be null if there is no matched endpoint
|
||||
var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource: endpoint);
|
||||
|
||||
if (authorizeResult.Challenged)
|
||||
{
|
||||
if (policy.AuthenticationSchemes.Any())
|
||||
{
|
||||
foreach (var scheme in policy.AuthenticationSchemes)
|
||||
{
|
||||
await context.ChallengeAsync(scheme);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.ChallengeAsync();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (authorizeResult.Forbidden)
|
||||
{
|
||||
if (policy.AuthenticationSchemes.Any())
|
||||
{
|
||||
foreach (var scheme in policy.AuthenticationSchemes)
|
||||
{
|
||||
await context.ForbidAsync(scheme);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.ForbidAsync();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core authorization policy helper classes.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591;NU1605</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authorization</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="$(MicrosoftAspNetCoreAuthenticationAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(MicrosoftAspNetCoreRoutingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsSecurityHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,25 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
public bool InvokeHandlersAfterFailure { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default authorization policy.
|
||||
/// Gets or sets the default authorization policy. Defaults to require authenticated users.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default policy is to require any authenticated user.
|
||||
/// The default policy used when evaluating <see cref="IAuthorizeData"/> with no policy name specified.
|
||||
/// </remarks>
|
||||
public AuthorizationPolicy DefaultPolicy { get; set; } = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the required authorization policy. Defaults to null.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default the required policy is null.
|
||||
///
|
||||
/// If a required policy has been specified then it is always evaluated, even if there are no
|
||||
/// <see cref="IAuthorizeData"/> instances for a resource. If a resource has <see cref="IAuthorizeData"/>
|
||||
/// then they are evaluated together with the required policy.
|
||||
/// </remarks>
|
||||
public AuthorizationPolicy RequiredPolicy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Add an authorization policy with the provided name.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -120,46 +120,74 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
throw new ArgumentNullException(nameof(authorizeData));
|
||||
}
|
||||
|
||||
var policyBuilder = new AuthorizationPolicyBuilder();
|
||||
var any = false;
|
||||
foreach (var authorizeDatum in authorizeData)
|
||||
// Avoid allocating enumerator if the data is known to be empty
|
||||
var skipEnumeratingData = false;
|
||||
if (authorizeData is IList<IAuthorizeData> dataList)
|
||||
{
|
||||
any = true;
|
||||
var useDefaultPolicy = true;
|
||||
if (!string.IsNullOrWhiteSpace(authorizeDatum.Policy))
|
||||
skipEnumeratingData = dataList.Count == 0;
|
||||
}
|
||||
|
||||
AuthorizationPolicyBuilder policyBuilder = null;
|
||||
if (!skipEnumeratingData)
|
||||
{
|
||||
foreach (var authorizeDatum in authorizeData)
|
||||
{
|
||||
var policy = await policyProvider.GetPolicyAsync(authorizeDatum.Policy);
|
||||
if (policy == null)
|
||||
if (policyBuilder == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatException_AuthorizationPolicyNotFound(authorizeDatum.Policy));
|
||||
policyBuilder = new AuthorizationPolicyBuilder();
|
||||
}
|
||||
policyBuilder.Combine(policy);
|
||||
useDefaultPolicy = false;
|
||||
}
|
||||
var rolesSplit = authorizeDatum.Roles?.Split(',');
|
||||
if (rolesSplit != null && rolesSplit.Any())
|
||||
{
|
||||
var trimmedRolesSplit = rolesSplit.Where(r => !string.IsNullOrWhiteSpace(r)).Select(r => r.Trim());
|
||||
policyBuilder.RequireRole(trimmedRolesSplit);
|
||||
useDefaultPolicy = false;
|
||||
}
|
||||
var authTypesSplit = authorizeDatum.AuthenticationSchemes?.Split(',');
|
||||
if (authTypesSplit != null && authTypesSplit.Any())
|
||||
{
|
||||
foreach (var authType in authTypesSplit)
|
||||
|
||||
var useDefaultPolicy = true;
|
||||
if (!string.IsNullOrWhiteSpace(authorizeDatum.Policy))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(authType))
|
||||
var policy = await policyProvider.GetPolicyAsync(authorizeDatum.Policy);
|
||||
if (policy == null)
|
||||
{
|
||||
policyBuilder.AuthenticationSchemes.Add(authType.Trim());
|
||||
throw new InvalidOperationException(Resources.FormatException_AuthorizationPolicyNotFound(authorizeDatum.Policy));
|
||||
}
|
||||
policyBuilder.Combine(policy);
|
||||
useDefaultPolicy = false;
|
||||
}
|
||||
|
||||
var rolesSplit = authorizeDatum.Roles?.Split(',');
|
||||
if (rolesSplit != null && rolesSplit.Any())
|
||||
{
|
||||
var trimmedRolesSplit = rolesSplit.Where(r => !string.IsNullOrWhiteSpace(r)).Select(r => r.Trim());
|
||||
policyBuilder.RequireRole(trimmedRolesSplit);
|
||||
useDefaultPolicy = false;
|
||||
}
|
||||
|
||||
var authTypesSplit = authorizeDatum.AuthenticationSchemes?.Split(',');
|
||||
if (authTypesSplit != null && authTypesSplit.Any())
|
||||
{
|
||||
foreach (var authType in authTypesSplit)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(authType))
|
||||
{
|
||||
policyBuilder.AuthenticationSchemes.Add(authType.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useDefaultPolicy)
|
||||
{
|
||||
policyBuilder.Combine(await policyProvider.GetDefaultPolicyAsync());
|
||||
|
||||
if (useDefaultPolicy)
|
||||
{
|
||||
policyBuilder.Combine(await policyProvider.GetDefaultPolicyAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
return any ? policyBuilder.Build() : null;
|
||||
|
||||
var requiredPolicy = await policyProvider.GetRequiredPolicyAsync();
|
||||
if (requiredPolicy != null)
|
||||
{
|
||||
if (policyBuilder == null)
|
||||
{
|
||||
policyBuilder = new AuthorizationPolicyBuilder();
|
||||
}
|
||||
|
||||
policyBuilder.Combine(requiredPolicy);
|
||||
}
|
||||
|
||||
return policyBuilder?.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,16 +96,16 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="claimType">The claim type required.</param>
|
||||
/// <param name="requiredValues">Values the claim must process one or more of for evaluation to succeed.</param>
|
||||
/// <param name="allowedValues">Values the claim must process one or more of for evaluation to succeed.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] requiredValues)
|
||||
public AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues)
|
||||
{
|
||||
if (claimType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claimType));
|
||||
}
|
||||
|
||||
return RequireClaim(claimType, (IEnumerable<string>)requiredValues);
|
||||
return RequireClaim(claimType, (IEnumerable<string>)allowedValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -113,16 +113,16 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="claimType">The claim type required.</param>
|
||||
/// <param name="requiredValues">Values the claim must process one or more of for evaluation to succeed.</param>
|
||||
/// <param name="allowedValues">Values the claim must process one or more of for evaluation to succeed.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnumerable<string> requiredValues)
|
||||
public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnumerable<string> allowedValues)
|
||||
{
|
||||
if (claimType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(claimType));
|
||||
}
|
||||
|
||||
Requirements.Add(new ClaimsAuthorizationRequirement(claimType, requiredValues));
|
||||
Requirements.Add(new ClaimsAuthorizationRequirement(claimType, allowedValues));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// Adds a <see cref="RolesAuthorizationRequirement"/>
|
||||
/// to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="roles">The roles required.</param>
|
||||
/// <param name="roles">The allowed roles.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public AuthorizationPolicyBuilder RequireRole(params string[] roles)
|
||||
{
|
||||
|
|
@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// Adds a <see cref="RolesAuthorizationRequirement"/>
|
||||
/// to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="roles">The roles required.</param>
|
||||
/// <param name="roles">The allowed roles.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public AuthorizationPolicyBuilder RequireRole(IEnumerable<string> roles)
|
||||
{
|
||||
|
|
@ -247,4 +247,4 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
return new AuthorizationPolicy(Requirements, AuthenticationSchemes.Distinct());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,15 +39,5 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// Gets or sets a comma delimited list of schemes from which user information is constructed.
|
||||
/// </summary>
|
||||
public string AuthenticationSchemes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a comma delimited list of schemes from which user information is constructed.
|
||||
/// </summary>
|
||||
[Obsolete("Use AuthenticationSchemes instead.", error: false)]
|
||||
public string ActiveAuthenticationSchemes
|
||||
{
|
||||
get => AuthenticationSchemes;
|
||||
set => AuthenticationSchemes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
public class DefaultAuthorizationPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
private readonly AuthorizationOptions _options;
|
||||
private Task<AuthorizationPolicy> _cachedDefaultPolicy;
|
||||
private Task<AuthorizationPolicy> _cachedRequiredPolicy;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DefaultAuthorizationPolicyProvider"/>.
|
||||
|
|
@ -35,7 +37,26 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// <returns>The default authorization policy.</returns>
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
|
||||
{
|
||||
return Task.FromResult(_options.DefaultPolicy);
|
||||
return GetCachedPolicy(ref _cachedDefaultPolicy, _options.DefaultPolicy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the required authorization policy.
|
||||
/// </summary>
|
||||
/// <returns>The required authorization policy.</returns>
|
||||
public Task<AuthorizationPolicy> GetRequiredPolicyAsync()
|
||||
{
|
||||
return GetCachedPolicy(ref _cachedRequiredPolicy, _options.RequiredPolicy);
|
||||
}
|
||||
|
||||
private Task<AuthorizationPolicy> GetCachedPolicy(ref Task<AuthorizationPolicy> cachedPolicy, AuthorizationPolicy currentPolicy)
|
||||
{
|
||||
var local = cachedPolicy;
|
||||
if (local == null || local.Result != currentPolicy)
|
||||
{
|
||||
cachedPolicy = local = Task.FromResult(currentPolicy);
|
||||
}
|
||||
return local;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -22,5 +22,11 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
/// </summary>
|
||||
/// <returns>The default authorization policy.</returns>
|
||||
Task<AuthorizationPolicy> GetDefaultPolicyAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the required authorization policy.
|
||||
/// </summary>
|
||||
/// <returns>The required authorization policy.</returns>
|
||||
Task<AuthorizationPolicy> GetRequiredPolicyAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Commonly used types:
|
||||
Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute
|
||||
Microsoft.AspNetCore.Authorization.AuthorizeAttribute</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authorization</PackageTags>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core cookie policy classes to control the behavior of cookies.</Description>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore</PackageTags>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
<Project>
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DeveloperBuildTestTfms>netcoreapp2.2</DeveloperBuildTestTfms>
|
||||
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
|
||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' ">$(StandardTestTfms)</StandardTestTfms>
|
||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ using System.Security.Principal;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -22,431 +21,16 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.Cookies
|
||||
{
|
||||
public class CookieTests
|
||||
public class CookieTests : SharedAuthenticationTests<CookieAuthenticationOptions>
|
||||
{
|
||||
private TestClock _clock = new TestClock();
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
protected override string DefaultScheme => CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(CookieAuthenticationHandler);
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<CookieAuthenticationOptions> configure)
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddCookie(o => o.ForwardDefault = "auth1");
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, forwardDefault.SignOutCount);
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, forwardDefault.SignInCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignIn = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, specific.SignInCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, selector.SignOutCount);
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, selector.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, forwardDefault.SignOutCount);
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, forwardDefault.SignInCount);
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddCookie(o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, specific.SignOutCount);
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddCookie();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("CookieAuthenticationHandler", scheme.HandlerType.Name);
|
||||
Assert.Null(scheme.DisplayName);
|
||||
services.AddCookie(configure);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
// 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.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -20,478 +11,40 @@ using Microsoft.AspNetCore.TestHost;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Facebook
|
||||
{
|
||||
public class FacebookTests
|
||||
public class FacebookTests : RemoteAuthenticationTests<FacebookOptions>
|
||||
{
|
||||
private void ConfigureDefaults(FacebookOptions o)
|
||||
protected override string DefaultScheme => FacebookDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(FacebookHandler);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<FacebookOptions> configure)
|
||||
{
|
||||
services.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
configure.Invoke(o);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void ConfigureDefaults(FacebookOptions o)
|
||||
{
|
||||
o.AppId = "whatever";
|
||||
o.AppSecret = "whatever";
|
||||
o.SignInScheme = "auth1";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = FacebookDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddFacebook(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(
|
||||
app => { },
|
||||
services => services.AddAuthentication().AddFacebook(o =>
|
||||
{
|
||||
o.AppId = "whatever";
|
||||
o.AppSecret = "whatever";
|
||||
o.SignInScheme = FacebookDefaults.AuthenticationScheme;
|
||||
}),
|
||||
async context =>
|
||||
{
|
||||
await context.ChallengeAsync("Facebook");
|
||||
return true;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelfUsingDefaultScheme()
|
||||
{
|
||||
var server = CreateServer(
|
||||
app => { },
|
||||
services => services.AddAuthentication(o => o.DefaultScheme = FacebookDefaults.AuthenticationScheme).AddFacebook(o =>
|
||||
{
|
||||
o.AppId = "whatever";
|
||||
o.AppSecret = "whatever";
|
||||
}),
|
||||
async context =>
|
||||
{
|
||||
await context.ChallengeAsync("Facebook");
|
||||
return true;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelfUsingDefaultSignInScheme()
|
||||
{
|
||||
var server = CreateServer(
|
||||
app => { },
|
||||
services => services.AddAuthentication(o => o.DefaultSignInScheme = FacebookDefaults.AuthenticationScheme).AddFacebook(o =>
|
||||
{
|
||||
o.AppId = "whatever";
|
||||
o.AppSecret = "whatever";
|
||||
}),
|
||||
async context =>
|
||||
{
|
||||
await context.ChallengeAsync("Facebook");
|
||||
return true;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddFacebook();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(FacebookDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("FacebookHandler", scheme.HandlerType.Name);
|
||||
Assert.Equal(FacebookDefaults.AuthenticationScheme, scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowsIfAppIdMissing()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -20,433 +10,42 @@ using Microsoft.AspNetCore.WebUtilities;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Google
|
||||
{
|
||||
public class GoogleTests
|
||||
public class GoogleTests : RemoteAuthenticationTests<GoogleOptions>
|
||||
{
|
||||
private void ConfigureDefaults(GoogleOptions o)
|
||||
protected override string DefaultScheme => GoogleDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(GoogleHandler);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<GoogleOptions> configure)
|
||||
{
|
||||
services.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
configure.Invoke(o);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void ConfigureDefaults(GoogleOptions o)
|
||||
{
|
||||
o.ClientId = "whatever";
|
||||
o.ClientSecret = "whatever";
|
||||
o.SignInScheme = "auth1";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = GoogleDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddGoogle(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ClientId = "Test Id";
|
||||
o.ClientSecret = "Test Secret";
|
||||
o.SignInScheme = GoogleDefaults.AuthenticationScheme;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddGoogle();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(GoogleDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("GoogleHandler", scheme.HandlerType.Name);
|
||||
Assert.Equal(GoogleDefaults.AuthenticationScheme, scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillTriggerRedirection()
|
||||
{
|
||||
|
|
@ -758,6 +357,70 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
Assert.Equal("The oauth state was missing or invalid.", error.GetBaseException().Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task ReplyPathWithAccessDeniedErrorFails(bool redirect)
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ClientId = "Test Id";
|
||||
o.ClientSecret = "Test Secret";
|
||||
o.StateDataFormat = new TestStateDataFormat();
|
||||
o.Events = redirect ? new OAuthEvents()
|
||||
{
|
||||
OnAccessDenied = ctx =>
|
||||
{
|
||||
ctx.Response.Redirect("/error?FailureMessage=AccessDenied");
|
||||
ctx.HandleResponse();
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
} : new OAuthEvents();
|
||||
});
|
||||
var sendTask = server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
|
||||
".AspNetCore.Correlation.Google.correlationId=N");
|
||||
if (redirect)
|
||||
{
|
||||
var transaction = await sendTask;
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Equal("/error?FailureMessage=AccessDenied", transaction.Response.Headers.GetValues("Location").First());
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = await Assert.ThrowsAnyAsync<Exception>(() => sendTask);
|
||||
Assert.Equal("Access was denied by the resource owner or by the remote server.", error.GetBaseException().Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplyPathWithAccessDeniedError_AllowsCustomizingPath()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ClientId = "Test Id";
|
||||
o.ClientSecret = "Test Secret";
|
||||
o.StateDataFormat = new TestStateDataFormat();
|
||||
o.AccessDeniedPath = "/access-denied";
|
||||
o.Events = new OAuthEvents()
|
||||
{
|
||||
OnAccessDenied = ctx =>
|
||||
{
|
||||
Assert.Equal("/access-denied", ctx.AccessDeniedPath.Value);
|
||||
Assert.Equal("http://testhost/redirect", ctx.ReturnUrl);
|
||||
Assert.Equal("ReturnUrl", ctx.ReturnUrlParameter);
|
||||
ctx.AccessDeniedPath = "/custom-denied-page";
|
||||
ctx.ReturnUrl = "http://www.google.com/";
|
||||
ctx.ReturnUrlParameter = "rurl";
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
});
|
||||
var transaction = await server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
|
||||
".AspNetCore.Correlation.Google.correlationId=N");
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Equal("/custom-denied-page?rurl=http%3A%2F%2Fwww.google.com%2F", transaction.Response.Headers.GetValues("Location").First());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
|
|
@ -779,7 +442,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
} : new OAuthEvents();
|
||||
});
|
||||
var sendTask = server.SendAsync("https://example.com/signin-google?error=OMG&error_description=SoBad&error_uri=foobar&state=protected_state",
|
||||
".AspNetCore.Correlation.Google.corrilationId=N");
|
||||
".AspNetCore.Correlation.Google.correlationId=N");
|
||||
if (redirect)
|
||||
{
|
||||
var transaction = await sendTask;
|
||||
|
|
@ -1606,7 +1269,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
Assert.Equal("protected_state", protectedText);
|
||||
var properties = new AuthenticationProperties(new Dictionary<string, string>()
|
||||
{
|
||||
{ ".xsrf", "corrilationId" },
|
||||
{ ".xsrf", "correlationId" },
|
||||
{ "testkey", "testvalue" }
|
||||
});
|
||||
properties.RedirectUri = "http://testhost/redirect";
|
||||
|
|
|
|||
|
|
@ -1,6 +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 Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
|
|
@ -11,428 +17,30 @@ using System.Security.Claims;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
public class JwtBearerTests
|
||||
public class JwtBearerTests : SharedAuthenticationTests<JwtBearerOptions>
|
||||
{
|
||||
protected override string DefaultScheme => JwtBearerDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(JwtBearerHandler);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<JwtBearerOptions> configure)
|
||||
{
|
||||
services.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
configure.Invoke(o);
|
||||
});
|
||||
}
|
||||
|
||||
private void ConfigureDefaults(JwtBearerOptions o)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddJwtBearer(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddJwtBearer();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(JwtBearerDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("JwtBearerHandler", scheme.HandlerType.Name);
|
||||
Assert.Null(scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BearerTokenValidation()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -16,438 +7,44 @@ using Microsoft.AspNetCore.DataProtection;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
|
||||
{
|
||||
public class MicrosoftAccountTests
|
||||
public class MicrosoftAccountTests : RemoteAuthenticationTests<MicrosoftAccountOptions>
|
||||
{
|
||||
private void ConfigureDefaults(MicrosoftAccountOptions o)
|
||||
protected override string DefaultScheme => MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(MicrosoftAccountHandler);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<MicrosoftAccountOptions> configure)
|
||||
{
|
||||
services.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
configure.Invoke(o);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void ConfigureDefaults(MicrosoftAccountOptions o)
|
||||
{
|
||||
o.ClientId = "whatever";
|
||||
o.ClientSecret = "whatever";
|
||||
o.SignInScheme = "auth1";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddMicrosoftAccount(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ClientId = "Test Id";
|
||||
o.ClientSecret = "Test Secret";
|
||||
o.SignInScheme = MicrosoftAccountDefaults.AuthenticationScheme;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddMicrosoftAccount();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(MicrosoftAccountDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("MicrosoftAccountHandler", scheme.HandlerType.Name);
|
||||
Assert.Equal(MicrosoftAccountDefaults.AuthenticationScheme, scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillTriggerApplyRedirectEvent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,447 +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.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public class OAuthTests
|
||||
public class OAuthTests : RemoteAuthenticationTests<OAuthOptions>
|
||||
{
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
protected override string DefaultScheme => OAuthDefaults.DisplayName;
|
||||
protected override Type HandlerType => typeof(OAuthHandler<OAuthOptions>);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<OAuthOptions> configure)
|
||||
{
|
||||
services.AddOAuth(DefaultScheme, o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.SignInScheme = "auth1";
|
||||
o.ForwardDefault = "auth1";
|
||||
configure.Invoke(o);
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.SignInScheme = "auth1";
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.SignInScheme = "auth1";
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.DefaultSignInScheme = "auth1";
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = "default";
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddOAuth("default", o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(
|
||||
services => services.AddAuthentication().AddOAuth("weeblie", o =>
|
||||
{
|
||||
o.SignInScheme = "weeblie";
|
||||
o.ClientId = "whatever";
|
||||
o.ClientSecret = "whatever";
|
||||
o.CallbackPath = "/whatever";
|
||||
o.AuthorizationEndpoint = "/whatever";
|
||||
o.TokenEndpoint = "/whatever";
|
||||
}));
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddOAuth("oauth", o => { });
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync("oauth");
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("OAuthHandler`1", scheme.HandlerType.Name);
|
||||
Assert.Equal(OAuthDefaults.DisplayName, scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -654,7 +241,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
Assert.Contains("scope=baz%20qux", res.Headers.Location.Query);
|
||||
}
|
||||
|
||||
private void ConfigureDefaults(OAuthOptions o)
|
||||
protected override void ConfigureDefaults(OAuthOptions o)
|
||||
{
|
||||
o.ClientId = "Test Id";
|
||||
o.ClientSecret = "secret";
|
||||
|
|
@ -664,6 +251,101 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
o.CallbackPath = "/oauth-callback";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleRequestAsync_RedirectsToAccessDeniedPathWhenExplicitlySet()
|
||||
{
|
||||
var server = CreateServer(
|
||||
s => s.AddAuthentication().AddOAuth(
|
||||
"Weblie",
|
||||
opt =>
|
||||
{
|
||||
opt.ClientId = "Test Id";
|
||||
opt.ClientSecret = "secret";
|
||||
opt.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
opt.AuthorizationEndpoint = "https://example.com/provider/login";
|
||||
opt.TokenEndpoint = "https://example.com/provider/token";
|
||||
opt.CallbackPath = "/oauth-callback";
|
||||
opt.AccessDeniedPath = "/access-denied";
|
||||
opt.StateDataFormat = new TestStateDataFormat();
|
||||
opt.Events.OnRemoteFailure = context => throw new InvalidOperationException("This event should not be called.");
|
||||
}));
|
||||
|
||||
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
|
||||
".AspNetCore.Correlation.Weblie.correlationId=N");
|
||||
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Equal("/access-denied?ReturnUrl=http%3A%2F%2Ftesthost%2Fredirect", transaction.Response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleRequestAsync_InvokesAccessDeniedEvent()
|
||||
{
|
||||
var server = CreateServer(
|
||||
s => s.AddAuthentication().AddOAuth(
|
||||
"Weblie",
|
||||
opt =>
|
||||
{
|
||||
opt.ClientId = "Test Id";
|
||||
opt.ClientSecret = "secret";
|
||||
opt.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
opt.AuthorizationEndpoint = "https://example.com/provider/login";
|
||||
opt.TokenEndpoint = "https://example.com/provider/token";
|
||||
opt.CallbackPath = "/oauth-callback";
|
||||
opt.StateDataFormat = new TestStateDataFormat();
|
||||
opt.Events = new OAuthEvents()
|
||||
{
|
||||
OnAccessDenied = context =>
|
||||
{
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
context.HandleResponse();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
|
||||
".AspNetCore.Correlation.Weblie.correlationId=N");
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
|
||||
Assert.Null(transaction.Response.Headers.Location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleRequestAsync_InvokesRemoteFailureEventWhenAccessDeniedPathIsNotExplicitlySet()
|
||||
{
|
||||
var server = CreateServer(
|
||||
s => s.AddAuthentication().AddOAuth(
|
||||
"Weblie",
|
||||
opt =>
|
||||
{
|
||||
opt.ClientId = "Test Id";
|
||||
opt.ClientSecret = "secret";
|
||||
opt.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
opt.AuthorizationEndpoint = "https://example.com/provider/login";
|
||||
opt.TokenEndpoint = "https://example.com/provider/token";
|
||||
opt.CallbackPath = "/oauth-callback";
|
||||
opt.StateDataFormat = new TestStateDataFormat();
|
||||
opt.Events = new OAuthEvents()
|
||||
{
|
||||
OnRemoteFailure = context =>
|
||||
{
|
||||
Assert.Equal("Access was denied by the resource owner or by the remote server.", context.Failure.Message);
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
context.HandleResponse();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
|
||||
".AspNetCore.Correlation.Weblie.correlationId=N");
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
|
||||
Assert.Null(transaction.Response.Headers.Location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoteAuthenticationFailed_OAuthError_IncludesProperties()
|
||||
{
|
||||
|
|
@ -683,7 +365,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
{
|
||||
OnRemoteFailure = context =>
|
||||
{
|
||||
Assert.Contains("declined", context.Failure.Message);
|
||||
Assert.Contains("custom_error", context.Failure.Message);
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
context.HandleResponse();
|
||||
|
|
@ -692,8 +374,8 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
};
|
||||
}));
|
||||
|
||||
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=declined&state=protected_state",
|
||||
".AspNetCore.Correlation.Weblie.corrilationId=N");
|
||||
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=custom_error&state=protected_state",
|
||||
".AspNetCore.Correlation.Weblie.correlationId=N");
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
|
||||
Assert.Null(transaction.Response.Headers.Location);
|
||||
|
|
@ -736,7 +418,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
Assert.Equal("protected_state", protectedText);
|
||||
var properties = new AuthenticationProperties(new Dictionary<string, string>()
|
||||
{
|
||||
{ ".xsrf", "corrilationId" },
|
||||
{ ".xsrf", "correlationId" },
|
||||
{ "testkey", "testvalue" }
|
||||
});
|
||||
properties.RedirectUri = "http://testhost/redirect";
|
||||
|
|
|
|||
|
|
@ -783,6 +783,52 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
events.ValidateExpectations();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnAccessDenied_Skip_NoMoreEventsRun()
|
||||
{
|
||||
var events = new ExpectedOidcEvents()
|
||||
{
|
||||
ExpectMessageReceived = true,
|
||||
ExpectAccessDenied = true
|
||||
};
|
||||
events.OnAccessDenied = context =>
|
||||
{
|
||||
context.SkipHandler();
|
||||
return Task.FromResult(0);
|
||||
};
|
||||
var server = CreateServer(events, AppWritePath);
|
||||
|
||||
var response = await PostAsync(server, "signin-oidc", "error=access_denied&state=protected_state");
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("/signin-oidc", await response.Content.ReadAsStringAsync());
|
||||
events.ValidateExpectations();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnAccessDenied_Handled_NoMoreEventsRun()
|
||||
{
|
||||
var events = new ExpectedOidcEvents()
|
||||
{
|
||||
ExpectMessageReceived = true,
|
||||
ExpectAccessDenied = true
|
||||
};
|
||||
events.OnAccessDenied = context =>
|
||||
{
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.HandleResponse();
|
||||
context.Response.StatusCode = StatusCodes.Status202Accepted;
|
||||
return Task.FromResult(0);
|
||||
};
|
||||
var server = CreateServer(events, AppNotImpl);
|
||||
|
||||
var response = await PostAsync(server, "signin-oidc", "error=access_denied&state=protected_state");
|
||||
|
||||
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
|
||||
Assert.Equal("", await response.Content.ReadAsStringAsync());
|
||||
events.ValidateExpectations();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnRemoteFailure_Skip_NoMoreEventsRun()
|
||||
{
|
||||
|
|
@ -1099,6 +1145,9 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
public bool ExpectTokenValidated { get; set; }
|
||||
public bool InvokedTokenValidated { get; set; }
|
||||
|
||||
public bool ExpectAccessDenied { get; set; }
|
||||
public bool InvokedAccessDenied { get; set; }
|
||||
|
||||
public bool ExpectRemoteFailure { get; set; }
|
||||
public bool InvokedRemoteFailure { get; set; }
|
||||
|
||||
|
|
@ -1168,6 +1217,12 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
return base.TicketReceived(context);
|
||||
}
|
||||
|
||||
public override Task AccessDenied(AccessDeniedContext context)
|
||||
{
|
||||
InvokedAccessDenied = true;
|
||||
return base.AccessDenied(context);
|
||||
}
|
||||
|
||||
public override Task RemoteFailure(RemoteFailureContext context)
|
||||
{
|
||||
InvokedRemoteFailure = true;
|
||||
|
|
@ -1201,6 +1256,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
Assert.Equal(ExpectUserInfoReceived, InvokedUserInfoReceived);
|
||||
Assert.Equal(ExpectAuthenticationFailed, InvokeAuthenticationFailed);
|
||||
Assert.Equal(ExpectTicketReceived, InvokedTicketReceived);
|
||||
Assert.Equal(ExpectAccessDenied, InvokedAccessDenied);
|
||||
Assert.Equal(ExpectRemoteFailure, InvokedRemoteFailure);
|
||||
Assert.Equal(ExpectRedirectForSignOut, InvokedRedirectForSignOut);
|
||||
Assert.Equal(ExpectRemoteSignOut, InvokedRemoteSignOut);
|
||||
|
|
@ -1248,7 +1304,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
private Task<HttpResponseMessage> PostAsync(TestServer server, string path, string form)
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var cookie = ".AspNetCore.Correlation." + OpenIdConnectDefaults.AuthenticationScheme + ".corrilationId=N";
|
||||
var cookie = ".AspNetCore.Correlation." + OpenIdConnectDefaults.AuthenticationScheme + ".correlationId=N";
|
||||
client.DefaultRequestHeaders.Add("Cookie", cookie);
|
||||
return client.PostAsync("signin-oidc",
|
||||
new StringContent(form, Encoding.ASCII, "application/x-www-form-urlencoded"));
|
||||
|
|
@ -1273,7 +1329,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
|
|||
Assert.Equal("protected_state", protectedText);
|
||||
var properties = new AuthenticationProperties(new Dictionary<string, string>()
|
||||
{
|
||||
{ ".xsrf", "corrilationId" },
|
||||
{ ".xsrf", "correlationId" },
|
||||
{ OpenIdConnectDefaults.RedirectUriForCodePropertiesKey, "redirect_uri" },
|
||||
{ "testkey", "testvalue" }
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
// 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.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
public abstract class RemoteAuthenticationTests<TOptions> : SharedAuthenticationTests<TOptions> where TOptions : RemoteAuthenticationOptions
|
||||
{
|
||||
protected override string DisplayName => DefaultScheme;
|
||||
|
||||
private TestServer CreateServer(Action<TOptions> configureOptions, Func<HttpContext, Task> testpath = null, bool isDefault = true)
|
||||
=> CreateServerWithServices(s =>
|
||||
{
|
||||
var builder = s.AddAuthentication();
|
||||
if (isDefault)
|
||||
{
|
||||
s.Configure<AuthenticationOptions>(o => o.DefaultScheme = DefaultScheme);
|
||||
}
|
||||
RegisterAuth(builder, configureOptions);
|
||||
s.AddSingleton<ISystemClock>(Clock);
|
||||
}, testpath);
|
||||
|
||||
|
||||
protected virtual TestServer CreateServerWithServices(Action<IServiceCollection> configureServices, Func<HttpContext, Task> testpath = null)
|
||||
{
|
||||
//private static TestServer CreateServer(Action<IApplicationBuilder> configure, Action<IServiceCollection> configureServices, Func<HttpContext, Task<bool>> handler)
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (testpath != null)
|
||||
{
|
||||
await testpath(context);
|
||||
}
|
||||
await next();
|
||||
});
|
||||
})
|
||||
.ConfigureServices(configureServices);
|
||||
return new TestServer(builder);
|
||||
}
|
||||
|
||||
protected abstract void ConfigureDefaults(TOptions o);
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(
|
||||
o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.SignInScheme = DefaultScheme;
|
||||
},
|
||||
context => context.ChallengeAsync(DefaultScheme));
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelfUsingDefaultScheme()
|
||||
{
|
||||
var server = CreateServer(
|
||||
o => o.SignInScheme = null,
|
||||
context => context.ChallengeAsync(DefaultScheme),
|
||||
isDefault: true);
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelfUsingDefaultSignInScheme()
|
||||
{
|
||||
var server = CreateServerWithServices(
|
||||
services =>
|
||||
{
|
||||
var builder = services.AddAuthentication(o => o.DefaultSignInScheme = DefaultScheme);
|
||||
RegisterAuth(builder, o => o.SignInScheme = null);
|
||||
},
|
||||
context => context.ChallengeAsync(DefaultScheme));
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,510 @@
|
|||
// 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.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
public abstract class SharedAuthenticationTests<TOptions> where TOptions : AuthenticationSchemeOptions
|
||||
{
|
||||
protected TestClock Clock { get; } = new TestClock();
|
||||
|
||||
protected abstract string DefaultScheme { get; }
|
||||
protected virtual string DisplayName { get; }
|
||||
protected abstract Type HandlerType { get; }
|
||||
|
||||
protected virtual bool SupportsSignIn { get => true; }
|
||||
protected virtual bool SupportsSignOut { get => true; }
|
||||
|
||||
protected abstract void RegisterAuth(AuthenticationBuilder services, Action<TOptions> configure);
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
});
|
||||
RegisterAuth(builder, o => o.ForwardDefault = "auth1");
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
if (SupportsSignOut)
|
||||
{
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, forwardDefault.SignOutCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
if (SupportsSignIn)
|
||||
{
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, forwardDefault.SignInCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInWinsOverDefault()
|
||||
{
|
||||
if (SupportsSignIn)
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignIn = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, specific.SignInCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutWinsOverDefault()
|
||||
{
|
||||
if (SupportsSignOut)
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
if (SupportsSignOut)
|
||||
{
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, selector.SignOutCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
if (SupportsSignIn)
|
||||
{
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, selector.SignInCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
if (SupportsSignOut)
|
||||
{
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, forwardDefault.SignOutCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
if (SupportsSignIn)
|
||||
{
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, forwardDefault.SignInCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
var builder = services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = DefaultScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
});
|
||||
RegisterAuth(builder, o =>
|
||||
{
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
if (SupportsSignOut)
|
||||
{
|
||||
await context.SignOutAsync();
|
||||
Assert.Equal(1, specific.SignOutCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
if (SupportsSignIn)
|
||||
{
|
||||
await context.SignInAsync(new ClaimsPrincipal());
|
||||
Assert.Equal(1, specific.SignInCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var builder = services.AddAuthentication();
|
||||
RegisterAuth(builder, o => { });
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(DefaultScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal(HandlerType, scheme.HandlerType);
|
||||
Assert.Equal(DisplayName, scheme.DisplayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
|
@ -7,440 +13,33 @@ using System.Net.Http;
|
|||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.Tests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Twitter
|
||||
{
|
||||
public class TwitterTests
|
||||
public class TwitterTests : RemoteAuthenticationTests<TwitterOptions>
|
||||
{
|
||||
private void ConfigureDefaults(TwitterOptions o)
|
||||
protected override string DefaultScheme => TwitterDefaults.AuthenticationScheme;
|
||||
protected override Type HandlerType => typeof(TwitterHandler);
|
||||
protected override bool SupportsSignIn { get => false; }
|
||||
protected override bool SupportsSignOut { get => false; }
|
||||
|
||||
protected override void RegisterAuth(AuthenticationBuilder services, Action<TwitterOptions> configure)
|
||||
{
|
||||
services.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
configure.Invoke(o);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void ConfigureDefaults(TwitterOptions o)
|
||||
{
|
||||
o.ConsumerKey = "whatever";
|
||||
o.ConsumerSecret = "whatever";
|
||||
o.SignInScheme = "auth1";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanForwardDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("auth1", "auth1");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
});
|
||||
|
||||
var forwardDefault = new TestHandler();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignInThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSignOutThrows()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardSignOut = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardForbidWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardAuthenticateWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardChallengeWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardChallenge = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ForwardSelectorWinsOverDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, selector.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, selector.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, selector.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullForwardSelectorUsesDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => null;
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, forwardDefault.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, forwardDefault.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, forwardDefault.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
Assert.Equal(0, specific.AuthenticateCount);
|
||||
Assert.Equal(0, specific.ForbidCount);
|
||||
Assert.Equal(0, specific.ChallengeCount);
|
||||
Assert.Equal(0, specific.SignInCount);
|
||||
Assert.Equal(0, specific.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SpecificForwardWinsOverSelectorAndDefault()
|
||||
{
|
||||
var services = new ServiceCollection().AddLogging();
|
||||
services.AddAuthentication(o =>
|
||||
{
|
||||
o.DefaultScheme = TwitterDefaults.AuthenticationScheme;
|
||||
o.AddScheme<TestHandler2>("auth1", "auth1");
|
||||
o.AddScheme<TestHandler3>("selector", "selector");
|
||||
o.AddScheme<TestHandler>("specific", "specific");
|
||||
})
|
||||
.AddTwitter(o =>
|
||||
{
|
||||
ConfigureDefaults(o);
|
||||
o.ForwardDefault = "auth1";
|
||||
o.ForwardDefaultSelector = _ => "selector";
|
||||
o.ForwardAuthenticate = "specific";
|
||||
o.ForwardChallenge = "specific";
|
||||
o.ForwardSignIn = "specific";
|
||||
o.ForwardSignOut = "specific";
|
||||
o.ForwardForbid = "specific";
|
||||
});
|
||||
|
||||
var specific = new TestHandler();
|
||||
services.AddSingleton(specific);
|
||||
var forwardDefault = new TestHandler2();
|
||||
services.AddSingleton(forwardDefault);
|
||||
var selector = new TestHandler3();
|
||||
services.AddSingleton(selector);
|
||||
|
||||
var sp = services.BuildServiceProvider();
|
||||
var context = new DefaultHttpContext();
|
||||
context.RequestServices = sp;
|
||||
|
||||
await context.AuthenticateAsync();
|
||||
Assert.Equal(1, specific.AuthenticateCount);
|
||||
|
||||
await context.ForbidAsync();
|
||||
Assert.Equal(1, specific.ForbidCount);
|
||||
|
||||
await context.ChallengeAsync();
|
||||
Assert.Equal(1, specific.ChallengeCount);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
|
||||
|
||||
Assert.Equal(0, forwardDefault.AuthenticateCount);
|
||||
Assert.Equal(0, forwardDefault.ForbidCount);
|
||||
Assert.Equal(0, forwardDefault.ChallengeCount);
|
||||
Assert.Equal(0, forwardDefault.SignInCount);
|
||||
Assert.Equal(0, forwardDefault.SignOutCount);
|
||||
Assert.Equal(0, selector.AuthenticateCount);
|
||||
Assert.Equal(0, selector.ForbidCount);
|
||||
Assert.Equal(0, selector.ChallengeCount);
|
||||
Assert.Equal(0, selector.SignInCount);
|
||||
Assert.Equal(0, selector.SignOutCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySignInSchemeCannotBeSetToSelf()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ConsumerKey = "Test Consumer Key";
|
||||
o.ConsumerSecret = "Test Consumer Secret";
|
||||
o.SignInScheme = TwitterDefaults.AuthenticationScheme;
|
||||
});
|
||||
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => server.SendAsync("https://example.com/challenge"));
|
||||
Assert.Contains("cannot be set to itself", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifySchemeDefaults()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAuthentication().AddTwitter();
|
||||
var sp = services.BuildServiceProvider();
|
||||
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
var scheme = await schemeProvider.GetSchemeAsync(TwitterDefaults.AuthenticationScheme);
|
||||
Assert.NotNull(scheme);
|
||||
Assert.Equal("TwitterHandler", scheme.HandlerType.Name);
|
||||
Assert.Equal(TwitterDefaults.AuthenticationScheme, scheme.DisplayName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillTriggerApplyRedirectEvent()
|
||||
{
|
||||
|
|
@ -575,6 +174,94 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
Assert.Contains("https://api.twitter.com/oauth/authenticate?oauth_token=", location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleRequestAsync_RedirectsToAccessDeniedPathWhenExplicitlySet()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ConsumerKey = "Test Consumer Key";
|
||||
o.ConsumerSecret = "Test Consumer Secret";
|
||||
o.BackchannelHttpHandler = new TestHttpMessageHandler
|
||||
{
|
||||
Sender = BackchannelRequestToken
|
||||
};
|
||||
o.AccessDeniedPath = "/access-denied";
|
||||
o.Events.OnRemoteFailure = context => throw new InvalidOperationException("This event should not be called.");
|
||||
},
|
||||
async context =>
|
||||
{
|
||||
var properties = new AuthenticationProperties();
|
||||
properties.Items["testkey"] = "testvalue";
|
||||
await context.ChallengeAsync("Twitter", properties);
|
||||
return true;
|
||||
});
|
||||
var transaction = await server.SendAsync("http://example.com/challenge");
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
var location = transaction.Response.Headers.Location.AbsoluteUri;
|
||||
Assert.Contains("https://api.twitter.com/oauth/authenticate?oauth_token=", location);
|
||||
Assert.True(transaction.Response.Headers.TryGetValues(HeaderNames.SetCookie, out var setCookie));
|
||||
Assert.True(SetCookieHeaderValue.TryParseList(setCookie.ToList(), out var setCookieValues));
|
||||
Assert.Single(setCookieValues);
|
||||
var setCookieValue = setCookieValues.Single();
|
||||
var cookie = new CookieHeaderValue(setCookieValue.Name, setCookieValue.Value);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "/signin-twitter?denied=ABCDEFG");
|
||||
request.Headers.Add(HeaderNames.Cookie, cookie.ToString());
|
||||
var client = server.CreateClient();
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.Equal("/access-denied?ReturnUrl=%2Fchallenge", response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BadCallbackCallsAccessDeniedWithState()
|
||||
{
|
||||
var server = CreateServer(o =>
|
||||
{
|
||||
o.ConsumerKey = "Test Consumer Key";
|
||||
o.ConsumerSecret = "Test Consumer Secret";
|
||||
o.BackchannelHttpHandler = new TestHttpMessageHandler
|
||||
{
|
||||
Sender = BackchannelRequestToken
|
||||
};
|
||||
o.Events = new TwitterEvents()
|
||||
{
|
||||
OnAccessDenied = context =>
|
||||
{
|
||||
Assert.NotNull(context.Properties);
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
context.HandleResponse();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
},
|
||||
async context =>
|
||||
{
|
||||
var properties = new AuthenticationProperties();
|
||||
properties.Items["testkey"] = "testvalue";
|
||||
await context.ChallengeAsync("Twitter", properties);
|
||||
return true;
|
||||
});
|
||||
var transaction = await server.SendAsync("http://example.com/challenge");
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
var location = transaction.Response.Headers.Location.AbsoluteUri;
|
||||
Assert.Contains("https://api.twitter.com/oauth/authenticate?oauth_token=", location);
|
||||
Assert.True(transaction.Response.Headers.TryGetValues(HeaderNames.SetCookie, out var setCookie));
|
||||
Assert.True(SetCookieHeaderValue.TryParseList(setCookie.ToList(), out var setCookieValues));
|
||||
Assert.Single(setCookieValues);
|
||||
var setCookieValue = setCookieValues.Single();
|
||||
var cookie = new CookieHeaderValue(setCookieValue.Name, setCookieValue.Value);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "/signin-twitter?denied=ABCDEFG");
|
||||
request.Headers.Add(HeaderNames.Cookie, cookie.ToString());
|
||||
var client = server.CreateClient();
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BadCallbackCallsRemoteAuthFailedWithState()
|
||||
{
|
||||
|
|
@ -591,7 +278,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
OnRemoteFailure = context =>
|
||||
{
|
||||
Assert.NotNull(context.Failure);
|
||||
Assert.Equal("The user denied permissions.", context.Failure.Message);
|
||||
Assert.Equal("Access was denied by the resource owner or by the remote server.", context.Failure.Message);
|
||||
Assert.NotNull(context.Properties);
|
||||
Assert.Equal("testvalue", context.Properties.Items["testkey"]);
|
||||
context.Response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
|
|
|
|||
|
|
@ -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 System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization.Test.TestObjects;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Builder.Internal;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Endpoints;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization.Test
|
||||
{
|
||||
public class AuthorizationAppBuilderExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task UseAuthorization_RegistersMiddleware()
|
||||
{
|
||||
// Arrange
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
var services = CreateServices(authenticationService);
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
var appFunc = app.Build();
|
||||
|
||||
var endpoint = new Endpoint(
|
||||
null,
|
||||
new EndpointMetadataCollection(new AuthorizeAttribute()),
|
||||
"Test endpoint");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.RequestServices = services;
|
||||
httpContext.SetEndpoint(endpoint);
|
||||
|
||||
// Act
|
||||
await appFunc(httpContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(authenticationService.ChallengeCalled);
|
||||
}
|
||||
|
||||
private IServiceProvider CreateServices(IAuthenticationService authenticationService)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddAuthorization(options => { });
|
||||
services.AddAuthorizationPolicyEvaluator();
|
||||
services.AddLogging();
|
||||
services.AddSingleton(authenticationService);
|
||||
|
||||
var serviceProvder = services.BuildServiceProvider();
|
||||
|
||||
return serviceProvder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Builder;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization.Test
|
||||
{
|
||||
public class AuthorizationEndpointConventionBuilderExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void RequireAuthorization_IAuthorizeData()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestEndpointConventionBuilder();
|
||||
var metadata = new AuthorizeAttribute();
|
||||
|
||||
// Act
|
||||
builder.RequireAuthorization(metadata);
|
||||
|
||||
// Assert
|
||||
var convention = Assert.Single(builder.Conventions);
|
||||
|
||||
var endpointModel = new RouteEndpointModel((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);
|
||||
convention(endpointModel);
|
||||
|
||||
Assert.Equal(metadata, Assert.Single(endpointModel.Metadata));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequireAuthorization_PolicyName()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestEndpointConventionBuilder();
|
||||
|
||||
// Act
|
||||
builder.RequireAuthorization("policy");
|
||||
|
||||
// Assert
|
||||
var convention = Assert.Single(builder.Conventions);
|
||||
|
||||
var endpointModel = new RouteEndpointModel((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);
|
||||
convention(endpointModel);
|
||||
|
||||
Assert.Equal("policy", Assert.IsAssignableFrom<IAuthorizeData>(Assert.Single(endpointModel.Metadata)).Policy);
|
||||
}
|
||||
|
||||
private class TestEndpointConventionBuilder : IEndpointConventionBuilder
|
||||
{
|
||||
public IList<Action<EndpointModel>> Conventions { get; } = new List<Action<EndpointModel>>();
|
||||
|
||||
public void Apply(Action<EndpointModel> convention)
|
||||
{
|
||||
Conventions.Add(convention);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,459 @@
|
|||
// 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.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||
using Microsoft.AspNetCore.Authorization.Test.TestObjects;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Endpoints;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization.Test
|
||||
{
|
||||
public class AuthorizationMiddlewareTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task NoEndpoint_AnonymousUser_Allows()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoEndpointWithRequired_AnonymousUser_Challenges()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetRequiredPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithoutAuth_AnonymousUser_Allows()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint());
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithRequiredWithoutAuth_AnonymousUser_Challenges()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
policyProvider.Setup(p => p.GetRequiredPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint());
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithAuth_AnonymousUser_Challenges()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.True(authenticationService.ChallengeCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithAuth_AnonymousUser_ChallengePerScheme()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().AddAuthenticationSchemes("schema1", "schema2").Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.Equal(2, authenticationService.ChallengeCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnAuthorizationAsync_WillCallPolicyProvider()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
var getPolicyCount = 0;
|
||||
var getRequiredPolicyCount = 0;
|
||||
policyProvider.Setup(p => p.GetPolicyAsync(It.IsAny<string>())).ReturnsAsync(policy)
|
||||
.Callback(() => getPolicyCount++);
|
||||
policyProvider.Setup(p => p.GetRequiredPolicyAsync()).ReturnsAsync(policy)
|
||||
.Callback(() => getRequiredPolicyCount++);
|
||||
var next = new TestRequestDelegate();
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint(new AuthorizeAttribute("whatever")));
|
||||
|
||||
// Act & Assert
|
||||
await middleware.Invoke(context);
|
||||
Assert.Equal(1, getPolicyCount);
|
||||
Assert.Equal(1, getRequiredPolicyCount);
|
||||
Assert.Equal(1, next.CalledCount);
|
||||
|
||||
await middleware.Invoke(context);
|
||||
Assert.Equal(2, getPolicyCount);
|
||||
Assert.Equal(2, getRequiredPolicyCount);
|
||||
Assert.Equal(2, next.CalledCount);
|
||||
|
||||
await middleware.Invoke(context);
|
||||
Assert.Equal(3, getPolicyCount);
|
||||
Assert.Equal(3, getRequiredPolicyCount);
|
||||
Assert.Equal(3, next.CalledCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_ValidClaimShouldNotFail()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireClaim("Permission", "CanViewPage").Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()));
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithAuthAndAllowAnonymous_AnonymousUser_Allows()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(anonymous: true, endpoint: CreateEndpoint(new AuthorizeAttribute(), new AllowAnonymousAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
Assert.False(authenticationService.ChallengeCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasEndpointWithAuth_AuthenticatedUser_Allows()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
Assert.False(authenticationService.ChallengeCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_AuthSchemesFailShouldSetEmptyPrincipalOnContext()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder("Fails").RequireAuthenticatedUser().Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.NotNull(context.User?.Identity);
|
||||
Assert.True(authenticationService.AuthenticateCalled);
|
||||
Assert.True(authenticationService.ChallengeCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_SingleValidClaimShouldSucceed()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireClaim("Permission", "CanViewComment", "CanViewPage").Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()));
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(next.Called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AuthZResourceShouldBeEndpoint()
|
||||
{
|
||||
// Arrange
|
||||
object resource = null;
|
||||
var policy = new AuthorizationPolicyBuilder().RequireAssertion(c =>
|
||||
{
|
||||
resource = c.Resource;
|
||||
return true;
|
||||
}).Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var endpoint = CreateEndpoint(new AuthorizeAttribute());
|
||||
var context = GetHttpContext(endpoint: endpoint);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(endpoint, resource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_RequireUnknownRoleShouldForbid()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireRole("Wut").Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.False(authenticationService.ChallengeCalled);
|
||||
Assert.True(authenticationService.ForbidCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_RequireUnknownRole_ForbidPerScheme()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder().RequireRole("Wut").AddAuthenticationSchemes("Basic", "Bearer").Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.Equal(2, authenticationService.ForbidCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_InvalidClaimShouldForbid()
|
||||
{
|
||||
// Arrange
|
||||
var policy = new AuthorizationPolicyBuilder()
|
||||
.RequireClaim("Permission", "CanViewComment")
|
||||
.Build();
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy);
|
||||
var next = new TestRequestDelegate();
|
||||
var authenticationService = new TestAuthenticationService();
|
||||
|
||||
var middleware = CreateMiddleware(next.Invoke, policyProvider.Object);
|
||||
var context = GetHttpContext(endpoint: CreateEndpoint(new AuthorizeAttribute()), authenticationService: authenticationService);
|
||||
|
||||
// Act
|
||||
await middleware.Invoke(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(next.Called);
|
||||
Assert.False(authenticationService.ChallengeCalled);
|
||||
Assert.True(authenticationService.ForbidCalled);
|
||||
}
|
||||
|
||||
private AuthorizationMiddleware CreateMiddleware(RequestDelegate requestDelegate = null, IAuthorizationPolicyProvider policyProvider = null)
|
||||
{
|
||||
requestDelegate = requestDelegate ?? ((context) => Task.CompletedTask);
|
||||
|
||||
return new AuthorizationMiddleware(requestDelegate, policyProvider);
|
||||
}
|
||||
|
||||
private Endpoint CreateEndpoint(params object[] metadata)
|
||||
{
|
||||
return new Endpoint(context => Task.CompletedTask, new EndpointMetadataCollection(metadata), "Test endpoint");
|
||||
}
|
||||
|
||||
private HttpContext GetHttpContext(
|
||||
bool anonymous = false,
|
||||
Action<IServiceCollection> registerServices = null,
|
||||
Endpoint endpoint = null,
|
||||
IAuthenticationService authenticationService = null)
|
||||
{
|
||||
var basicPrincipal = new ClaimsPrincipal(
|
||||
new ClaimsIdentity(
|
||||
new Claim[] {
|
||||
new Claim("Permission", "CanViewPage"),
|
||||
new Claim(ClaimTypes.Role, "Administrator"),
|
||||
new Claim(ClaimTypes.Role, "User"),
|
||||
new Claim(ClaimTypes.NameIdentifier, "John")},
|
||||
"Basic"));
|
||||
|
||||
var validUser = basicPrincipal;
|
||||
|
||||
var bearerIdentity = new ClaimsIdentity(
|
||||
new Claim[] {
|
||||
new Claim("Permission", "CupBearer"),
|
||||
new Claim(ClaimTypes.Role, "Token"),
|
||||
new Claim(ClaimTypes.NameIdentifier, "John Bear")},
|
||||
"Bearer");
|
||||
|
||||
validUser.AddIdentity(bearerIdentity);
|
||||
|
||||
// ServiceProvider
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
authenticationService = authenticationService ?? Mock.Of<IAuthenticationService>();
|
||||
|
||||
serviceCollection.AddSingleton(authenticationService);
|
||||
serviceCollection.AddOptions();
|
||||
serviceCollection.AddLogging();
|
||||
serviceCollection.AddAuthorization();
|
||||
serviceCollection.AddAuthorizationPolicyEvaluator();
|
||||
registerServices?.Invoke(serviceCollection);
|
||||
|
||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
|
||||
//// HttpContext
|
||||
var httpContext = new DefaultHttpContext();
|
||||
if (endpoint != null)
|
||||
{
|
||||
httpContext.SetEndpoint(endpoint);
|
||||
}
|
||||
httpContext.RequestServices = serviceProvider;
|
||||
if (!anonymous)
|
||||
{
|
||||
httpContext.User = validUser;
|
||||
}
|
||||
|
||||
return httpContext;
|
||||
}
|
||||
|
||||
private class TestRequestDelegate
|
||||
{
|
||||
private readonly int _statusCode;
|
||||
|
||||
public bool Called => CalledCount > 0;
|
||||
public int CalledCount { get; private set; }
|
||||
|
||||
public TestRequestDelegate(int statusCode = 200)
|
||||
{
|
||||
_statusCode = statusCode;
|
||||
}
|
||||
|
||||
public Task Invoke(HttpContext context)
|
||||
{
|
||||
CalledCount++;
|
||||
context.Response.StatusCode = _statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1025,6 +1025,11 @@ namespace Microsoft.AspNetCore.Authorization.Test
|
|||
return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetRequiredPolicyAsync()
|
||||
{
|
||||
return Task.FromResult<AuthorizationPolicy>(null);
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
|
||||
{
|
||||
return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
|
||||
|
|
@ -1059,6 +1064,11 @@ namespace Microsoft.AspNetCore.Authorization.Test
|
|||
return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetRequiredPolicyAsync()
|
||||
{
|
||||
return Task.FromResult<AuthorizationPolicy>(null);
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
|
||||
{
|
||||
return Task.FromResult(new AuthorizationPolicyBuilder().RequireClaim(policyName).Build());
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);NU1605</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -11,8 +12,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
||||
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization.Test.TestObjects
|
||||
{
|
||||
public class TestAuthenticationService : IAuthenticationService
|
||||
{
|
||||
public bool ChallengeCalled => ChallengeCount > 0;
|
||||
public bool ForbidCalled => ForbidCount > 0;
|
||||
public bool AuthenticateCalled => AuthenticateCount > 0;
|
||||
|
||||
public int ChallengeCount { get; private set; }
|
||||
public int ForbidCount { get; private set; }
|
||||
public int AuthenticateCount { get; private set; }
|
||||
|
||||
public Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
|
||||
{
|
||||
AuthenticateCount++;
|
||||
|
||||
var identity = context.User.Identities.SingleOrDefault(i => i.AuthenticationType == scheme);
|
||||
if (identity != null)
|
||||
{
|
||||
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), scheme)));
|
||||
}
|
||||
|
||||
return Task.FromResult(AuthenticateResult.Fail("Denied"));
|
||||
}
|
||||
|
||||
public Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||
{
|
||||
ChallengeCount++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||
{
|
||||
ForbidCount++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
// 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.
|
||||
|
||||
/* See https://github.com/aspnet/AspNetCore/issues/4074.
|
||||
|
||||
This test is was disabled as a part of changing frameworks. This test will need to be re-written using separate .NET Core and .NET Framework processes.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -330,3 +334,4 @@ namespace Microsoft.Owin.Security.Interop
|
|||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net461</TargetFramework>
|
||||
<!-- Temporarily disables tests for this project. They need to be refactored now that aspnetcore only supports netcoreapp3.0. -->
|
||||
<IsTestProject>false</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Authentication.Cookies\Microsoft.AspNetCore.Authentication.Cookies.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Owin.Security.Interop\Microsoft.Owin.Security.Interop.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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.Linq;
|
||||
using System.Security.Claims;
|
||||
|
|
@ -87,5 +89,6 @@ namespace Microsoft.Owin.Security.Interop.Test
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>2.2.0</VersionPrefix>
|
||||
<VersionSuffix>rtm</VersionSuffix>
|
||||
<VersionPrefix>3.0.0</VersionPrefix>
|
||||
<VersionSuffix>alpha1</VersionSuffix>
|
||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
|
||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
|
||||
<BuildNumber Condition="'$(BuildNumber)' == ''">t000</BuildNumber>
|
||||
|
|
|
|||
Loading…
Reference in New Issue