diff --git a/src/Security/.gitignore b/src/Security/.gitignore
new file mode 100644
index 0000000000..d5717b3f3f
--- /dev/null
+++ b/src/Security/.gitignore
@@ -0,0 +1,32 @@
+[Oo]bj/
+[Bb]in/
+TestResults/
+.nuget/
+_ReSharper.*/
+packages/
+artifacts/
+PublishProfiles/
+*.user
+*.suo
+*.cache
+*.docstates
+_ReSharper.*
+nuget.exe
+*net45.csproj
+*net451.csproj
+*k10.csproj
+*.psess
+*.vsp
+*.pidb
+*.userprefs
+*DS_Store
+*.ncrunchsolution
+*.*sdf
+*.ipch
+*.sln.ide
+project.lock.json
+.build/
+.testPublish/
+/.vs/
+.vscode/
+global.json
diff --git a/src/Security/Directory.Build.props b/src/Security/Directory.Build.props
new file mode 100644
index 0000000000..adbda10ef8
--- /dev/null
+++ b/src/Security/Directory.Build.props
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+ Microsoft ASP.NET Core
+ https://github.com/aspnet/Security
+ git
+ $(MSBuildThisFileDirectory)
+ $(MSBuildThisFileDirectory)build\Key.snk
+ true
+ true
+ true
+
+
diff --git a/src/Security/Directory.Build.targets b/src/Security/Directory.Build.targets
new file mode 100644
index 0000000000..53b3f6e1da
--- /dev/null
+++ b/src/Security/Directory.Build.targets
@@ -0,0 +1,7 @@
+
+
+ $(MicrosoftNETCoreApp20PackageVersion)
+ $(MicrosoftNETCoreApp21PackageVersion)
+ $(NETStandardLibrary20PackageVersion)
+
+
diff --git a/src/Security/NuGetPackageVerifier.json b/src/Security/NuGetPackageVerifier.json
new file mode 100644
index 0000000000..974eb365c9
--- /dev/null
+++ b/src/Security/NuGetPackageVerifier.json
@@ -0,0 +1,13 @@
+{
+ "adx-nonshipping": {
+ "rules": [],
+ "packages": {
+ "Microsoft.AspNetCore.ChunkingCookieManager.Sources": {}
+ }
+ },
+ "Default": {
+ "rules": [
+ "DefaultCompositeRule"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/Security/README.md b/src/Security/README.md
new file mode 100644
index 0000000000..e8e64c2936
--- /dev/null
+++ b/src/Security/README.md
@@ -0,0 +1,17 @@
+ASP.NET Security
+========
+
+AppVeyor: [](https://ci.appveyor.com/project/aspnetci/Security/branch/dev)
+
+Travis: [](https://travis-ci.org/aspnet/Security)
+
+Contains the security and authorization middlewares for ASP.NET Core.
+
+A list of community projects related to authentication and security for ASP.NET Core are listed in the [documentation](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/community).
+
+### Notes
+
+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.
diff --git a/src/Security/Security.sln b/src/Security/Security.sln
new file mode 100644
index 0000000000..3df759651b
--- /dev/null
+++ b/src/Security/Security.sln
@@ -0,0 +1,556 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2027
+MinimumVisualStudioVersion = 15.0.26730.03
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9F-44F5-8131-EA5CAC053652}"
+ ProjectSection(SolutionItems) = preProject
+ src\Directory.Build.props = src\Directory.Build.props
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CookieSample", "samples\CookieSample\CookieSample.csproj", "{558C2C2A-AED8-49DE-BB60-D5F8AE06C714}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7BF11F3A-60B6-4796-B504-579C67FFBA34}"
+ ProjectSection(SolutionItems) = preProject
+ test\Directory.Build.props = test\Directory.Build.props
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialSample", "samples\SocialSample\SocialSample.csproj", "{8C73D216-332D-41D8-BFD0-45BC4BC36552}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CookieSessionSample", "samples\CookieSessionSample\CookieSessionSample.csproj", "{19711880-46DA-4A26-9E0F-9B2E41D27651}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenIdConnectSample", "samples\OpenIdConnectSample\OpenIdConnectSample.csproj", "{BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Cookies", "src\Microsoft.AspNetCore.Authentication.Cookies\Microsoft.AspNetCore.Authentication.Cookies.csproj", "{FC152CC4-054B-457E-8D91-389C5DE3C561}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication", "src\Microsoft.AspNetCore.Authentication\Microsoft.AspNetCore.Authentication.csproj", "{BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Facebook", "src\Microsoft.AspNetCore.Authentication.Facebook\Microsoft.AspNetCore.Authentication.Facebook.csproj", "{EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Google", "src\Microsoft.AspNetCore.Authentication.Google\Microsoft.AspNetCore.Authentication.Google.csproj", "{76579C39-B829-490D-B8BE-1BD35FE8412E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.OpenIdConnect", "src\Microsoft.AspNetCore.Authentication.OpenIdConnect\Microsoft.AspNetCore.Authentication.OpenIdConnect.csproj", "{35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.MicrosoftAccount", "src\Microsoft.AspNetCore.Authentication.MicrosoftAccount\Microsoft.AspNetCore.Authentication.MicrosoftAccount.csproj", "{ACB45E19-F520-4D0C-8916-B0CEB9C017FE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Twitter", "src\Microsoft.AspNetCore.Authentication.Twitter\Microsoft.AspNetCore.Authentication.Twitter.csproj", "{0330FFF6-B4B5-42DD-8C99-26A789569000}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.OAuth", "src\Microsoft.AspNetCore.Authentication.OAuth\Microsoft.AspNetCore.Authentication.OAuth.csproj", "{1657C79E-7755-4AEE-9D61-571295B69A30}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Test", "test\Microsoft.AspNetCore.Authentication.Test\Microsoft.AspNetCore.Authentication.Test.csproj", "{8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization.Test", "test\Microsoft.AspNetCore.Authorization.Test\Microsoft.AspNetCore.Authorization.Test.csproj", "{7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization", "src\Microsoft.AspNetCore.Authorization\Microsoft.AspNetCore.Authorization.csproj", "{6AB3E514-5894-4131-9399-DC7D5284ADDB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.CookiePolicy", "src\Microsoft.AspNetCore.CookiePolicy\Microsoft.AspNetCore.CookiePolicy.csproj", "{86183DC3-02A8-4A68-8B60-71ECEC066E79}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.CookiePolicy.Test", "test\Microsoft.AspNetCore.CookiePolicy.Test\Microsoft.AspNetCore.CookiePolicy.Test.csproj", "{1790E052-646F-4529-B90E-6FEA95520D69}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.JwtBearer", "src\Microsoft.AspNetCore.Authentication.JwtBearer\Microsoft.AspNetCore.Authentication.JwtBearer.csproj", "{2755BFE5-7421-4A31-A644-F817DF5CAA98}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JwtBearerSample", "samples\JwtBearerSample\JwtBearerSample.csproj", "{D399B84F-591B-4E98-92BA-B0F63E7B6957}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Owin.Security.Interop", "src\Microsoft.Owin.Security.Interop\Microsoft.Owin.Security.Interop.csproj", "{A7922DD8-09F1-43E4-938B-CC523EA08898}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Owin.Security.Interop.Test", "test\Microsoft.Owin.Security.Interop.Test\Microsoft.Owin.Security.Interop.Test.csproj", "{A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenIdConnect.AzureAdSample", "samples\OpenIdConnect.AzureAdSample\OpenIdConnect.AzureAdSample.csproj", "{3A7AD414-EBDE-4F92-B307-4E8F19B6117E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ChunkingCookieManager.Sources.Test", "test\Microsoft.AspNetCore.ChunkingCookieManager.Sources.Test\Microsoft.AspNetCore.ChunkingCookieManager.Sources.Test.csproj", "{51563775-C659-4907-9BAF-9995BAB87D01}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{86BD08B1-F978-4F58-9982-2A017807F01C}"
+ ProjectSection(SolutionItems) = preProject
+ build\dependencies.props = build\dependencies.props
+ Directory.Build.props = Directory.Build.props
+ Directory.Build.targets = Directory.Build.targets
+ build\Key.snk = build\Key.snk
+ NuGet.config = NuGet.config
+ build\repo.props = build\repo.props
+ build\sources.props = build\sources.props
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization.Policy", "src\Microsoft.AspNetCore.Authorization.Policy\Microsoft.AspNetCore.Authorization.Policy.csproj", "{58194599-F07D-47A3-9DF2-E21A22C5EF9E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CookiePolicySample", "samples\CookiePolicySample\CookiePolicySample.csproj", "{24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.WsFederation", "src\Microsoft.AspNetCore.Authentication.WsFederation\Microsoft.AspNetCore.Authentication.WsFederation.csproj", "{B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WsFedSample", "samples\WsFedSample\WsFedSample.csproj", "{5EC2E398-E46A-430D-8E4B-E91C8FC3E800}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|x64.Build.0 = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Any CPU.Build.0 = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x64.ActiveCfg = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x64.Build.0 = Release|Any CPU
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714}.Release|x86.ActiveCfg = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|x64.Build.0 = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|x64.ActiveCfg = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|x64.Build.0 = Release|Any CPU
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552}.Release|x86.ActiveCfg = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|x64.Build.0 = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|x64.ActiveCfg = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|x64.Build.0 = Release|Any CPU
+ {19711880-46DA-4A26-9E0F-9B2E41D27651}.Release|x86.ActiveCfg = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|x64.Build.0 = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Debug|x86.Build.0 = Debug|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|x64.ActiveCfg = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|x64.Build.0 = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|x86.ActiveCfg = Release|Any CPU
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B}.Release|x86.Build.0 = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|x64.Build.0 = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Debug|x86.Build.0 = Debug|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|x64.ActiveCfg = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|x64.Build.0 = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|x86.ActiveCfg = Release|Any CPU
+ {FC152CC4-054B-457E-8D91-389C5DE3C561}.Release|x86.Build.0 = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|x64.Build.0 = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Debug|x86.Build.0 = Debug|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|x64.ActiveCfg = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|x64.Build.0 = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|x86.ActiveCfg = Release|Any CPU
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB}.Release|x86.Build.0 = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|x64.Build.0 = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Debug|x86.Build.0 = Debug|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|x64.ActiveCfg = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|x64.Build.0 = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|x86.ActiveCfg = Release|Any CPU
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A}.Release|x86.Build.0 = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|x64.Build.0 = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Debug|x86.Build.0 = Debug|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|x64.ActiveCfg = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|x64.Build.0 = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|x86.ActiveCfg = Release|Any CPU
+ {76579C39-B829-490D-B8BE-1BD35FE8412E}.Release|x86.Build.0 = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|x64.Build.0 = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Debug|x86.Build.0 = Debug|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|x64.ActiveCfg = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|x64.Build.0 = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|x86.ActiveCfg = Release|Any CPU
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A}.Release|x86.Build.0 = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|x64.Build.0 = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Debug|x86.Build.0 = Debug|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|x64.ActiveCfg = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|x64.Build.0 = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|x86.ActiveCfg = Release|Any CPU
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE}.Release|x86.Build.0 = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|x64.Build.0 = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Debug|x86.Build.0 = Debug|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|x64.ActiveCfg = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|x64.Build.0 = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|x86.ActiveCfg = Release|Any CPU
+ {0330FFF6-B4B5-42DD-8C99-26A789569000}.Release|x86.Build.0 = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|x64.Build.0 = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Debug|x86.Build.0 = Debug|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|x64.ActiveCfg = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|x64.Build.0 = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|x86.ActiveCfg = Release|Any CPU
+ {1657C79E-7755-4AEE-9D61-571295B69A30}.Release|x86.Build.0 = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x64.Build.0 = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Debug|x86.Build.0 = Debug|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x64.ActiveCfg = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x64.Build.0 = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x86.ActiveCfg = Release|Any CPU
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B}.Release|x86.Build.0 = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|x64.Build.0 = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Debug|x86.Build.0 = Debug|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|x64.ActiveCfg = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|x64.Build.0 = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|x86.ActiveCfg = Release|Any CPU
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2}.Release|x86.Build.0 = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|x64.Build.0 = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Debug|x86.Build.0 = Debug|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|x64.ActiveCfg = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|x64.Build.0 = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|x86.ActiveCfg = Release|Any CPU
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB}.Release|x86.Build.0 = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|x64.Build.0 = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Debug|x86.Build.0 = Debug|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|Any CPU.Build.0 = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|x64.ActiveCfg = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|x64.Build.0 = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|x86.ActiveCfg = Release|Any CPU
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79}.Release|x86.Build.0 = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|x64.Build.0 = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Debug|x86.Build.0 = Debug|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|x64.ActiveCfg = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|x64.Build.0 = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|x86.ActiveCfg = Release|Any CPU
+ {1790E052-646F-4529-B90E-6FEA95520D69}.Release|x86.Build.0 = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|x64.Build.0 = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Debug|x86.Build.0 = Debug|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|x64.ActiveCfg = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|x64.Build.0 = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|x86.ActiveCfg = Release|Any CPU
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98}.Release|x86.Build.0 = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|x64.Build.0 = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Debug|x86.Build.0 = Debug|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|x64.ActiveCfg = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|x64.Build.0 = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|x86.ActiveCfg = Release|Any CPU
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957}.Release|x86.Build.0 = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|x64.Build.0 = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Debug|x86.Build.0 = Debug|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|x64.ActiveCfg = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|x64.Build.0 = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|x86.ActiveCfg = Release|Any CPU
+ {A7922DD8-09F1-43E4-938B-CC523EA08898}.Release|x86.Build.0 = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|x64.Build.0 = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Debug|x86.Build.0 = Debug|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|x64.ActiveCfg = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|x64.Build.0 = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|x86.ActiveCfg = Release|Any CPU
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24}.Release|x86.Build.0 = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|x64.Build.0 = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Debug|x86.Build.0 = Debug|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|x64.ActiveCfg = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|x64.Build.0 = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|x86.ActiveCfg = Release|Any CPU
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E}.Release|x86.Build.0 = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|x64.Build.0 = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Debug|x86.Build.0 = Debug|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|Any CPU.Build.0 = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|x64.ActiveCfg = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|x64.Build.0 = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|x86.ActiveCfg = Release|Any CPU
+ {51563775-C659-4907-9BAF-9995BAB87D01}.Release|x86.Build.0 = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|x64.Build.0 = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Debug|x86.Build.0 = Debug|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|x64.ActiveCfg = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|x64.Build.0 = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|x86.ActiveCfg = Release|Any CPU
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E}.Release|x86.Build.0 = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|x64.Build.0 = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Debug|x86.Build.0 = Debug|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|x64.ActiveCfg = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|x64.Build.0 = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|x86.ActiveCfg = Release|Any CPU
+ {24A28F5D-E5A9-4CA8-B0D2-924A1F8BE14E}.Release|x86.Build.0 = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|x64.Build.0 = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Debug|x86.Build.0 = Debug|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|x64.ActiveCfg = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|x64.Build.0 = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|x86.ActiveCfg = Release|Any CPU
+ {B1FC6AAF-9BF2-4CDA-84A2-AA8BF7603F29}.Release|x86.Build.0 = Release|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|x64.Build.0 = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Debug|x86.Build.0 = Debug|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {5EC2E398-E46A-430D-8E4B-E91C8FC3E800}.Release|x64.ActiveCfg = Release|Any CPU
+ {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
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {558C2C2A-AED8-49DE-BB60-D5F8AE06C714} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {8C73D216-332D-41D8-BFD0-45BC4BC36552} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {19711880-46DA-4A26-9E0F-9B2E41D27651} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {BEF0F5C3-EF4E-4649-9C49-D5E279A3CA2B} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {FC152CC4-054B-457E-8D91-389C5DE3C561} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {BC0D4B56-1A5B-4D88-AFBF-68C0F2D545FB} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {EEAAEE68-607B-4E33-AF3E-45C66B4DBA5A} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {76579C39-B829-490D-B8BE-1BD35FE8412E} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {35115D55-B69E-46D4-BB33-C9E9E6EC5E7A} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {ACB45E19-F520-4D0C-8916-B0CEB9C017FE} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {0330FFF6-B4B5-42DD-8C99-26A789569000} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {1657C79E-7755-4AEE-9D61-571295B69A30} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {8DA26CD1-1302-4CFD-9270-9FA1B7C6138B} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
+ {7AF5AD96-EB6E-4D0E-8ABE-C0B543C0F4C2} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
+ {6AB3E514-5894-4131-9399-DC7D5284ADDB} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {86183DC3-02A8-4A68-8B60-71ECEC066E79} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {1790E052-646F-4529-B90E-6FEA95520D69} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
+ {2755BFE5-7421-4A31-A644-F817DF5CAA98} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {D399B84F-591B-4E98-92BA-B0F63E7B6957} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {A7922DD8-09F1-43E4-938B-CC523EA08898} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {A2B5DC39-68D5-4145-A8CC-6AEAB7D33A24} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
+ {3A7AD414-EBDE-4F92-B307-4E8F19B6117E} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
+ {51563775-C659-4907-9BAF-9995BAB87D01} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
+ {58194599-F07D-47A3-9DF2-E21A22C5EF9E} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {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}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {ABF8089E-43D0-4010-84A7-7A9DCFE49357}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Security/build/Key.snk b/src/Security/build/Key.snk
new file mode 100644
index 0000000000..e10e4889c1
Binary files /dev/null and b/src/Security/build/Key.snk differ
diff --git a/src/Security/build/dependencies.props b/src/Security/build/dependencies.props
new file mode 100644
index 0000000000..828f9c7ab2
--- /dev/null
+++ b/src/Security/build/dependencies.props
@@ -0,0 +1,58 @@
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+
+
+
+
+ 2.1.3-rtm-15802
+ 3.14.2
+ 5.2.0
+ 5.2.0
+ 2.0.0
+ 2.1.2
+ 15.6.1
+ 3.0.1
+ 3.0.1
+ 3.0.1
+ 2.0.3
+ 11.0.2
+ 5.2.0
+ 0.8.0
+ 2.3.1
+ 2.4.0-beta.1.build3945
+
+
+
+
+
+
+
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.2
+ 2.1.2
+ 2.1.1
+ 2.1.1
+ 2.1.0
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+ 2.1.1
+
+
\ No newline at end of file
diff --git a/src/Security/build/repo.props b/src/Security/build/repo.props
new file mode 100644
index 0000000000..a4f86fb2f6
--- /dev/null
+++ b/src/Security/build/repo.props
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ Internal.AspNetCore.Universe.Lineup
+ 2.1.0-rc1-*
+ https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json
+
+
+
+
+
+
+
diff --git a/src/Security/build/sources.props b/src/Security/build/sources.props
new file mode 100644
index 0000000000..9215df9751
--- /dev/null
+++ b/src/Security/build/sources.props
@@ -0,0 +1,17 @@
+
+
+
+
+ $(DotNetRestoreSources)
+
+ $(RestoreSources);
+ https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
+
+
+ $(RestoreSources);
+ https://api.nuget.org/v3/index.json;
+
+
+
diff --git a/src/Security/samples/CookiePolicySample/CookiePolicySample.csproj b/src/Security/samples/CookiePolicySample/CookiePolicySample.csproj
new file mode 100644
index 0000000000..fb2e7d9172
--- /dev/null
+++ b/src/Security/samples/CookiePolicySample/CookiePolicySample.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net461;netcoreapp2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/CookiePolicySample/Program.cs b/src/Security/samples/CookiePolicySample/Program.cs
new file mode 100644
index 0000000000..3fc09a3db2
--- /dev/null
+++ b/src/Security/samples/CookiePolicySample/Program.cs
@@ -0,0 +1,26 @@
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace CookiePolicySample
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .ConfigureLogging(factory =>
+ {
+ factory.AddConsole();
+ factory.AddFilter("Microsoft", LogLevel.Trace);
+ })
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseIISIntegration()
+ .UseStartup()
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/src/Security/samples/CookiePolicySample/Properties/launchSettings.json b/src/Security/samples/CookiePolicySample/Properties/launchSettings.json
new file mode 100644
index 0000000000..38ca6fc37f
--- /dev/null
+++ b/src/Security/samples/CookiePolicySample/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:1788/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "CookieSample": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:12345",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/CookiePolicySample/Startup.cs b/src/Security/samples/CookiePolicySample/Startup.cs
new file mode 100644
index 0000000000..7ce9c2d2d2
--- /dev/null
+++ b/src/Security/samples/CookiePolicySample/Startup.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Net.Http.Headers;
+
+namespace CookiePolicySample
+{
+ public class Startup
+ {
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
+ .AddCookie();
+ services.Configure(options =>
+ {
+ options.CheckConsentNeeded = context => context.Request.PathBase.Equals("/NeedsConsent");
+
+ options.OnAppendCookie = context => { };
+ });
+ }
+
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseCookiePolicy();
+ app.UseAuthentication();
+
+ app.Map("/NeedsConsent", NestedApp);
+ app.Map("/NeedsNoConsent", NestedApp);
+ NestedApp(app);
+ }
+
+ private void NestedApp(IApplicationBuilder app)
+ {
+ app.Run(async context =>
+ {
+ var path = context.Request.Path;
+ switch (path)
+ {
+ case "/Login":
+ var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "bob") },
+ CookieAuthenticationDefaults.AuthenticationScheme));
+ await context.SignInAsync(user);
+ break;
+ case "/Logout":
+ await context.SignOutAsync();
+ break;
+ case "/CreateTempCookie":
+ context.Response.Cookies.Append("Temp", "1");
+ break;
+ case "/RemoveTempCookie":
+ context.Response.Cookies.Delete("Temp");
+ break;
+ case "/GrantConsent":
+ context.Features.Get().GrantConsent();
+ break;
+ case "/WithdrawConsent":
+ context.Features.Get().WithdrawConsent();
+ break;
+ }
+
+ // TODO: Debug log when cookie is suppressed
+
+ await HomePage(context);
+ });
+ }
+
+ private async Task HomePage(HttpContext context)
+ {
+ var response = context.Response;
+ var cookies = context.Request.Cookies;
+ response.ContentType = "text/html";
+ await response.WriteAsync("\r\n");
+
+ await response.WriteAsync($"Home \r\n");
+ await response.WriteAsync($"Login \r\n");
+ await response.WriteAsync($"Logout \r\n");
+ await response.WriteAsync($"Create Temp Cookie \r\n");
+ await response.WriteAsync($"Remove Temp Cookie \r\n");
+ await response.WriteAsync($"Grant Consent \r\n");
+ await response.WriteAsync($"Withdraw Consent \r\n");
+ await response.WriteAsync(" \r\n");
+ await response.WriteAsync($"Needs Consent \r\n");
+ await response.WriteAsync($"Needs No Consent \r\n");
+ await response.WriteAsync(" \r\n");
+
+ var feature = context.Features.Get();
+ await response.WriteAsync($"Consent: \r\n");
+ await response.WriteAsync($" - IsNeeded: {feature.IsConsentNeeded} \r\n");
+ await response.WriteAsync($" - Has: {feature.HasConsent} \r\n");
+ await response.WriteAsync($" - Can Track: {feature.CanTrack} \r\n");
+ await response.WriteAsync(" \r\n");
+
+ await response.WriteAsync($"{cookies.Count} Request Cookies: \r\n");
+ foreach (var cookie in cookies)
+ {
+ await response.WriteAsync($" - {cookie.Key} = {cookie.Value} \r\n");
+ }
+ await response.WriteAsync(" \r\n");
+
+ var responseCookies = response.Headers[HeaderNames.SetCookie];
+ await response.WriteAsync($"{responseCookies.Count} Response Cookies: \r\n");
+ foreach (var cookie in responseCookies)
+ {
+ await response.WriteAsync($" - {cookie} \r\n");
+ }
+
+ await response.WriteAsync("");
+ }
+ }
+}
diff --git a/src/Security/samples/CookieSample/CookieSample.csproj b/src/Security/samples/CookieSample/CookieSample.csproj
new file mode 100644
index 0000000000..193137b861
--- /dev/null
+++ b/src/Security/samples/CookieSample/CookieSample.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net461;netcoreapp2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/CookieSample/Program.cs b/src/Security/samples/CookieSample/Program.cs
new file mode 100644
index 0000000000..3f40d3194b
--- /dev/null
+++ b/src/Security/samples/CookieSample/Program.cs
@@ -0,0 +1,26 @@
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace CookieSample
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .ConfigureLogging(factory =>
+ {
+ factory.AddConsole();
+ factory.AddFilter("Console", level => level >= LogLevel.Information);
+ })
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseIISIntegration()
+ .UseStartup()
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/src/Security/samples/CookieSample/Properties/launchSettings.json b/src/Security/samples/CookieSample/Properties/launchSettings.json
new file mode 100644
index 0000000000..38ca6fc37f
--- /dev/null
+++ b/src/Security/samples/CookieSample/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:1788/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "CookieSample": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:12345",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/CookieSample/Startup.cs b/src/Security/samples/CookieSample/Startup.cs
new file mode 100644
index 0000000000..a91791070a
--- /dev/null
+++ b/src/Security/samples/CookieSample/Startup.cs
@@ -0,0 +1,45 @@
+using System.Linq;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace CookieSample
+{
+ public class Startup
+ {
+ public void ConfigureServices(IServiceCollection services)
+ {
+ // This can be removed after https://github.com/aspnet/IISIntegration/issues/371
+ services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ }).AddCookie();
+ }
+
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseAuthentication();
+
+ app.Run(async context =>
+ {
+ if (!context.User.Identities.Any(identity => identity.IsAuthenticated))
+ {
+ var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "bob") }, CookieAuthenticationDefaults.AuthenticationScheme));
+ await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello First timer");
+ return;
+ }
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello old timer");
+ });
+ }
+ }
+}
diff --git a/src/Security/samples/CookieSessionSample/CookieSessionSample.csproj b/src/Security/samples/CookieSessionSample/CookieSessionSample.csproj
new file mode 100644
index 0000000000..6241edd667
--- /dev/null
+++ b/src/Security/samples/CookieSessionSample/CookieSessionSample.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net461;netcoreapp2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/CookieSessionSample/MemoryCacheTicketStore.cs b/src/Security/samples/CookieSessionSample/MemoryCacheTicketStore.cs
new file mode 100644
index 0000000000..ebb660361b
--- /dev/null
+++ b/src/Security/samples/CookieSessionSample/MemoryCacheTicketStore.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.Extensions.Caching.Memory;
+
+namespace CookieSessionSample
+{
+ public class MemoryCacheTicketStore : ITicketStore
+ {
+ private const string KeyPrefix = "AuthSessionStore-";
+ private IMemoryCache _cache;
+
+ public MemoryCacheTicketStore()
+ {
+ _cache = new MemoryCache(new MemoryCacheOptions());
+ }
+
+ public async Task StoreAsync(AuthenticationTicket ticket)
+ {
+ var guid = Guid.NewGuid();
+ var key = KeyPrefix + guid.ToString();
+ await RenewAsync(key, ticket);
+ return key;
+ }
+
+ public Task RenewAsync(string key, AuthenticationTicket ticket)
+ {
+ var options = new MemoryCacheEntryOptions();
+ var expiresUtc = ticket.Properties.ExpiresUtc;
+ if (expiresUtc.HasValue)
+ {
+ options.SetAbsoluteExpiration(expiresUtc.Value);
+ }
+ options.SetSlidingExpiration(TimeSpan.FromHours(1)); // TODO: configurable.
+
+ _cache.Set(key, ticket, options);
+
+ return Task.FromResult(0);
+ }
+
+ public Task RetrieveAsync(string key)
+ {
+ AuthenticationTicket ticket;
+ _cache.TryGetValue(key, out ticket);
+ return Task.FromResult(ticket);
+ }
+
+ public Task RemoveAsync(string key)
+ {
+ _cache.Remove(key);
+ return Task.FromResult(0);
+ }
+ }
+}
diff --git a/src/Security/samples/CookieSessionSample/Program.cs b/src/Security/samples/CookieSessionSample/Program.cs
new file mode 100644
index 0000000000..1a19850e64
--- /dev/null
+++ b/src/Security/samples/CookieSessionSample/Program.cs
@@ -0,0 +1,26 @@
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace CookieSessionSample
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .ConfigureLogging(factory =>
+ {
+ factory.AddConsole();
+ factory.AddFilter("Console", level => level >= LogLevel.Information);
+ })
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseIISIntegration()
+ .UseStartup()
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/src/Security/samples/CookieSessionSample/Properties/launchSettings.json b/src/Security/samples/CookieSessionSample/Properties/launchSettings.json
new file mode 100644
index 0000000000..25de3e478e
--- /dev/null
+++ b/src/Security/samples/CookieSessionSample/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:1790/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "CookieSessionSample": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:12345",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/CookieSessionSample/Startup.cs b/src/Security/samples/CookieSessionSample/Startup.cs
new file mode 100644
index 0000000000..f7b8f2bb88
--- /dev/null
+++ b/src/Security/samples/CookieSessionSample/Startup.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace CookieSessionSample
+{
+ public class Startup
+ {
+ public void ConfigureServices(IServiceCollection services)
+ {
+ // This can be removed after https://github.com/aspnet/IISIntegration/issues/371
+ services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ }).AddCookie(o => o.SessionStore = new MemoryCacheTicketStore());
+ }
+
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseAuthentication();
+
+ app.Run(async context =>
+ {
+ if (!context.User.Identities.Any(identity => identity.IsAuthenticated))
+ {
+ // Make a large identity
+ var claims = new List(1001);
+ claims.Add(new Claim(ClaimTypes.Name, "bob"));
+ for (int i = 0; i < 1000; i++)
+ {
+ claims.Add(new Claim(ClaimTypes.Role, "SomeRandomGroup" + i, ClaimValueTypes.String, "IssuedByBob", "OriginalIssuerJoe"));
+ }
+
+ await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
+ new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)));
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello First timer");
+ return;
+ }
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello old timer");
+ });
+ }
+ }
+}
diff --git a/src/Security/samples/JwtBearerSample/JwtBearerSample.csproj b/src/Security/samples/JwtBearerSample/JwtBearerSample.csproj
new file mode 100644
index 0000000000..84b436581a
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/JwtBearerSample.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net461;netcoreapp2.1
+ aspnet5-JwtBearerSample-20151210102827
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/JwtBearerSample/Program.cs b/src/Security/samples/JwtBearerSample/Program.cs
new file mode 100644
index 0000000000..44d2fe0c4f
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/Program.cs
@@ -0,0 +1,21 @@
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+
+namespace JwtBearerSample
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .UseKestrel()
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseIISIntegration()
+ .UseStartup()
+ .Build();
+
+ host.Run();
+ }
+ }
+}
diff --git a/src/Security/samples/JwtBearerSample/Properties/launchSettings.json b/src/Security/samples/JwtBearerSample/Properties/launchSettings.json
new file mode 100644
index 0000000000..6922375c98
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:42023",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "JwtBearer": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:42023",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/Startup.cs b/src/Security/samples/JwtBearerSample/Startup.cs
new file mode 100644
index 0000000000..8c4a63cad6
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/Startup.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.ExceptionServices;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Net.Http.Headers;
+using Newtonsoft.Json.Linq;
+
+namespace JwtBearerSample
+{
+ public class Startup
+ {
+ public Startup(IHostingEnvironment env)
+ {
+ Environment = env;
+
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(env.ContentRootPath);
+
+ if (env.IsDevelopment())
+ {
+ // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
+ builder.AddUserSecrets();
+ }
+
+ builder.AddEnvironmentVariables();
+ Configuration = builder.Build();
+ }
+
+ public IConfiguration Configuration { get; set; }
+
+ public IHostingEnvironment Environment { get; set; }
+
+ // Shared between users in memory
+ public IList Todos { get; } = new List();
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+ .AddJwtBearer(o =>
+ {
+ // You also need to update /wwwroot/app/scripts/app.js
+ o.Authority = Configuration["oidc:authority"];
+ o.Audience = Configuration["oidc:clientid"];
+ });
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseDeveloperExceptionPage();
+
+ app.UseDefaultFiles();
+ app.UseStaticFiles();
+
+ app.UseAuthentication();
+
+ // [Authorize] would usually handle this
+ app.Use(async (context, next) =>
+ {
+ // Use this if there are multiple authentication schemes
+ var authResult = await context.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
+ if (authResult.Succeeded && authResult.Principal.Identity.IsAuthenticated)
+ {
+ await next();
+ }
+ else if (authResult.Failure != null)
+ {
+ // Rethrow, let the exception page handle it.
+ ExceptionDispatchInfo.Capture(authResult.Failure).Throw();
+ }
+ else
+ {
+ await context.ChallengeAsync();
+ }
+ });
+
+ // MVC would usually handle this:
+ app.Map("/api/TodoList", todoApp =>
+ {
+ todoApp.Run(async context =>
+ {
+ var response = context.Response;
+ if (context.Request.Method.Equals("POST", System.StringComparison.OrdinalIgnoreCase))
+ {
+ var reader = new StreamReader(context.Request.Body);
+ var body = await reader.ReadToEndAsync();
+ var obj = JObject.Parse(body);
+ var todo = new Todo() { Description = obj["Description"].Value(), Owner = context.User.Identity.Name };
+ Todos.Add(todo);
+ }
+ else
+ {
+ response.ContentType = "application/json";
+ response.Headers[HeaderNames.CacheControl] = "no-cache";
+ var json = JToken.FromObject(Todos);
+ await response.WriteAsync(json.ToString());
+ }
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/Todo.cs b/src/Security/samples/JwtBearerSample/Todo.cs
new file mode 100644
index 0000000000..3ddf40414e
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/Todo.cs
@@ -0,0 +1,8 @@
+namespace JwtBearerSample
+{
+ public class Todo
+ {
+ public string Description { get; set; }
+ public string Owner { get; set; }
+ }
+}
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/app.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/app.js
new file mode 100644
index 0000000000..b45cb760b2
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/app.js
@@ -0,0 +1,28 @@
+'use strict';
+angular.module('todoApp', ['ngRoute','AdalAngular'])
+.config(['$routeProvider', '$httpProvider', 'adalAuthenticationServiceProvider', function ($routeProvider, $httpProvider, adalProvider) {
+
+ $routeProvider.when("/Home", {
+ controller: "homeCtrl",
+ templateUrl: "/App/Views/Home.html",
+ }).when("/TodoList", {
+ controller: "todoListCtrl",
+ templateUrl: "/App/Views/TodoList.html",
+ requireADLogin: true,
+ }).when("/UserData", {
+ controller: "userDataCtrl",
+ templateUrl: "/App/Views/UserData.html",
+ }).otherwise({ redirectTo: "/Home" });
+
+ adalProvider.init(
+ {
+ instance: 'https://login.microsoftonline.com/',
+ tenant: 'tratcheroutlook.onmicrosoft.com',
+ clientId: '63a87a83-64b9-4ac1-b2c5-092126f8474f',
+ extraQueryParameter: 'nux=1',
+ // cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
+ },
+ $httpProvider
+ );
+
+}]);
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/homeCtrl.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/homeCtrl.js
new file mode 100644
index 0000000000..09a3beae53
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/homeCtrl.js
@@ -0,0 +1,13 @@
+'use strict';
+angular.module('todoApp')
+.controller('homeCtrl', ['$scope', 'adalAuthenticationService','$location', function ($scope, adalService, $location) {
+ $scope.login = function () {
+ adalService.login();
+ };
+ $scope.logout = function () {
+ adalService.logOut();
+ };
+ $scope.isActive = function (viewLocation) {
+ return viewLocation === $location.path();
+ };
+}]);
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/indexCtrl.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/indexCtrl.js
new file mode 100644
index 0000000000..baaa4b2421
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/indexCtrl.js
@@ -0,0 +1,5 @@
+'use strict';
+angular.module('todoApp')
+.controller('indexCtrl', ['$scope', 'adalAuthenticationService', function ($scope, adalService) {
+
+}]);
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListCtrl.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListCtrl.js
new file mode 100644
index 0000000000..7dbd4f29ca
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListCtrl.js
@@ -0,0 +1,71 @@
+'use strict';
+angular.module('todoApp')
+.controller('todoListCtrl', ['$scope', '$location', 'todoListSvc', 'adalAuthenticationService', function ($scope, $location, todoListSvc, adalService) {
+ $scope.error = "";
+ $scope.loadingMessage = "Loading...";
+ $scope.todoList = null;
+ $scope.editingInProgress = false;
+ $scope.newTodoCaption = "";
+
+
+ $scope.editInProgressTodo = {
+ Description: "",
+ ID: 0
+ };
+
+
+
+ $scope.editSwitch = function (todo) {
+ todo.edit = !todo.edit;
+ if (todo.edit) {
+ $scope.editInProgressTodo.Description = todo.Description;
+ $scope.editInProgressTodo.ID = todo.ID;
+ $scope.editingInProgress = true;
+ } else {
+ $scope.editingInProgress = false;
+ }
+ };
+
+ $scope.populate = function () {
+ todoListSvc.getItems().success(function (results) {
+ $scope.todoList = results;
+ $scope.loadingMessage = "";
+ }).error(function (err) {
+ $scope.error = err;
+ $scope.loadingMessage = "";
+ })
+ };
+ $scope.delete = function (id) {
+ todoListSvc.deleteItem(id).success(function (results) {
+ $scope.loadingMessage = "";
+ $scope.populate();
+ }).error(function (err) {
+ $scope.error = err;
+ $scope.loadingMessage = "";
+ })
+ };
+ $scope.update = function (todo) {
+ todoListSvc.putItem($scope.editInProgressTodo).success(function (results) {
+ $scope.loadingMsg = "";
+ $scope.populate();
+ $scope.editSwitch(todo);
+ }).error(function (err) {
+ $scope.error = err;
+ $scope.loadingMessage = "";
+ })
+ };
+ $scope.add = function () {
+
+ todoListSvc.postItem({
+ 'Description': $scope.newTodoCaption,
+ 'Owner': adalService.userInfo.userName
+ }).success(function (results) {
+ $scope.loadingMsg = "";
+ $scope.newTodoCaption = "";
+ $scope.populate();
+ }).error(function (err) {
+ $scope.error = err;
+ $scope.loadingMsg = "";
+ })
+ };
+}]);
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListSvc.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListSvc.js
new file mode 100644
index 0000000000..87d0641084
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/todoListSvc.js
@@ -0,0 +1,24 @@
+'use strict';
+angular.module('todoApp')
+.factory('todoListSvc', ['$http', function ($http) {
+ return {
+ getItems : function(){
+ return $http.get('/api/TodoList');
+ },
+ getItem : function(id){
+ return $http.get('/api/TodoList/' + id);
+ },
+ postItem : function(item){
+ return $http.post('/api/TodoList/',item);
+ },
+ putItem : function(item){
+ return $http.put('/api/TodoList/', item);
+ },
+ deleteItem : function(id){
+ return $http({
+ method: 'DELETE',
+ url: '/api/TodoList/' + id
+ });
+ }
+ };
+}]);
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/userDataCtrl.js b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/userDataCtrl.js
new file mode 100644
index 0000000000..1b2511fdcc
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Scripts/userDataCtrl.js
@@ -0,0 +1,6 @@
+'use strict';
+angular.module('todoApp')
+.controller('userDataCtrl', ['$scope', 'adalAuthenticationService', function ($scope, adalService) {
+
+
+}]);
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Views/Home.html b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/Home.html
new file mode 100644
index 0000000000..49f14e1d5b
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/Home.html
@@ -0,0 +1,3 @@
+
+ home sweet home
+
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Views/TodoList.html b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/TodoList.html
new file mode 100644
index 0000000000..8ade518a5c
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/TodoList.html
@@ -0,0 +1,24 @@
+
+
{{error}}
+
{{loadingMessage}}
+
+
+
+
+
+
+
+
+
+
+
+
{{item.Description}}
+
+
+
{{item.Owner}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/App/Views/UserData.html b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/UserData.html
new file mode 100644
index 0000000000..cacd57edb9
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/App/Views/UserData.html
@@ -0,0 +1,23 @@
+
+
+ Id_token content
+
+
{{userInfo.userName}}
+
aud:{{userInfo.profile.aud}}
+
iss:{{userInfo.profile.iss}}
+
iat:{{userInfo.profile.iat}}
+
nbf:{{userInfo.profile.nbf}}
+
exp:{{userInfo.profile.exp}}
+
ver:{{userInfo.profile.ver}}
+
tid:{{userInfo.profile.tid}}
+
amr:{{userInfo.profile.amr}}
+
oid:{{userInfo.profile.oid}}
+
upn:{{userInfo.profile.upn}}
+
unique_name:{{userInfo.profile.unique_name}}
+
sub:{{userInfo.profile.sub}}
+
family_name:{{userInfo.profile.family_name}}
+
given_name:{{userInfo.profile.given_name}}
+
pwd_exp:{{userInfo.profile.pwd_exp}}
+
pwd_url:{{userInfo.profile.pwd_url}}
+
+
\ No newline at end of file
diff --git a/src/Security/samples/JwtBearerSample/wwwroot/index.html b/src/Security/samples/JwtBearerSample/wwwroot/index.html
new file mode 100644
index 0000000000..f71dccb693
--- /dev/null
+++ b/src/Security/samples/JwtBearerSample/wwwroot/index.html
@@ -0,0 +1,68 @@
+
+
+
+ Todo List: a SPA sample demonstrating Azure AD and ADAL JS
+
+
+
+
+
+
+
");
+ try
+ {
+ // Use ADAL to get the right token
+ var authContext = new AuthenticationContext(Authority, AuthPropertiesTokenCache.ForApiCalls(context, CookieAuthenticationDefaults.AuthenticationScheme));
+ var credential = new ClientCredential(ClientId, ClientSecret);
+ string userObjectID = context.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
+ var result = await authContext.AcquireTokenSilentAsync(Resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
+
+ await response.WriteAsync($"
");
+ }
+
+ private static string HtmlEncode(string content) =>
+ string.IsNullOrEmpty(content) ? string.Empty : HtmlEncoder.Default.Encode(content);
+ }
+}
+
diff --git a/src/Security/samples/OpenIdConnectSample/OpenIdConnectSample.csproj b/src/Security/samples/OpenIdConnectSample/OpenIdConnectSample.csproj
new file mode 100644
index 0000000000..23e87d4f2a
--- /dev/null
+++ b/src/Security/samples/OpenIdConnectSample/OpenIdConnectSample.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net461;netcoreapp2.1
+ aspnet5-OpenIdConnectSample-20151210110318
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/OpenIdConnectSample/Program.cs b/src/Security/samples/OpenIdConnectSample/Program.cs
new file mode 100644
index 0000000000..87e7755084
--- /dev/null
+++ b/src/Security/samples/OpenIdConnectSample/Program.cs
@@ -0,0 +1,59 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+
+namespace OpenIdConnectSample
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ var host = new WebHostBuilder()
+ .ConfigureLogging(factory =>
+ {
+ factory.AddConsole();
+ factory.AddDebug();
+ factory.AddFilter("Console", level => level >= LogLevel.Information);
+ factory.AddFilter("Debug", level => level >= LogLevel.Information);
+ })
+ .UseKestrel(options =>
+ {
+ options.Listen(IPAddress.Loopback, 44318, listenOptions =>
+ {
+ // Configure SSL
+ var serverCertificate = LoadCertificate();
+ listenOptions.UseHttps(serverCertificate);
+ });
+ })
+ .UseContentRoot(Directory.GetCurrentDirectory())
+ .UseIISIntegration()
+ .UseStartup()
+ .Build();
+
+ host.Run();
+ }
+
+ private static X509Certificate2 LoadCertificate()
+ {
+ var assembly = typeof(Startup).GetTypeInfo().Assembly;
+ var embeddedFileProvider = new EmbeddedFileProvider(assembly, "OpenIdConnectSample");
+ var certificateFileInfo = embeddedFileProvider.GetFileInfo("compiler/resources/cert.pfx");
+ using (var certificateStream = certificateFileInfo.CreateReadStream())
+ {
+ byte[] certificatePayload;
+ using (var memoryStream = new MemoryStream())
+ {
+ certificateStream.CopyTo(memoryStream);
+ certificatePayload = memoryStream.ToArray();
+ }
+
+ return new X509Certificate2(certificatePayload, "testPassword");
+ }
+ }
+ }
+}
diff --git a/src/Security/samples/OpenIdConnectSample/Properties/launchSettings.json b/src/Security/samples/OpenIdConnectSample/Properties/launchSettings.json
new file mode 100644
index 0000000000..058fa4c5dd
--- /dev/null
+++ b/src/Security/samples/OpenIdConnectSample/Properties/launchSettings.json
@@ -0,0 +1,28 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:42023",
+ "sslPort": 44318
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "https://localhost:44318/",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "OpenIdConnectSample": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:44318/",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/samples/OpenIdConnectSample/Readme.md b/src/Security/samples/OpenIdConnectSample/Readme.md
new file mode 100644
index 0000000000..846e3f8e6a
--- /dev/null
+++ b/src/Security/samples/OpenIdConnectSample/Readme.md
@@ -0,0 +1,44 @@
+# How to set up the sample locally
+
+The OpenIdConnect sample supports multilpe authentication providers. In these instruction, we will explore how to set up this sample with both Azure Active Directory and Google Identity Platform.
+
+## Determine your development environment and a few key variables
+
+This sample is configured to run on port __44318__ locally. In Visual Studio, the setting is carried out in `.\properties\launchSettings.json`. When the application is run from command line, the URL is coded in `Program.cs`.
+
+If the application is run from command line or terminal, environment variable ASPNETCORE_ENVIRONMENT should be set to DEVELOPMENT to enable user secret.
+
+## Configure the Authorization server
+
+### Configure with Azure Active Directory
+
+1. Set up a new Azure Active Directory (AAD) in your Azure Subscription.
+2. Open the newly created AAD in Azure web portal.
+3. Navigate to the Applications tab.
+4. Add a new Application to the AAD. Set the "Sign-on URL" to sample application's URL.
+5. Naigate to the Application, and click the Configure tab.
+6. Find and save the "Client Id".
+7. Add a new key in the "Keys" section. Save value of the key, which is the "Client Secret".
+8. Click the "View Endpoints" on the drawer, a dialog will shows six endpoint URLs. Copy the "OAuth 2.0 Authorization Endpoint" to a text editor and remove the "/oauth2/authorize" from the string. The remaining part is the __authority URL__. It looks like `https://login.microsoftonline.com/`.
+
+### Configure with Google Identity Platform
+
+1. Create a new project through [Google APIs](https://console.developers.google.com).
+2. In the sidebar choose "Credentials".
+3. Navigate to "OAuth consent screen" tab, fill in the project name and save.
+4. Navigate to "Credentials" tab. Click "Create credentials". Choose "OAuth client ID".
+5. Select "Web application" as the application type. Fill in the "Authorized redirect URIs" with `https://localhost:44318/signin-oidc`.
+6. Save the "Client ID" and "Client Secret" shown in the dialog.
+7. The "Authority URL" for Google Authentication is `https://accounts.google.com/`.
+
+## Configure the sample application
+
+1. Restore the application.
+2. Set user secrets:
+
+ ```
+dotnet user-secrets set oidc:clientid
+dotnet user-secrets set oidc:clientsecret
+dotnet user-secrets set oidc:authority
+```
+
diff --git a/src/Security/samples/OpenIdConnectSample/Startup.cs b/src/Security/samples/OpenIdConnectSample/Startup.cs
new file mode 100644
index 0000000000..1aa7625cb0
--- /dev/null
+++ b/src/Security/samples/OpenIdConnectSample/Startup.cs
@@ -0,0 +1,297 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Authentication.OpenIdConnect;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Protocols.OpenIdConnect;
+using Newtonsoft.Json.Linq;
+
+namespace OpenIdConnectSample
+{
+ public class Startup
+ {
+ public Startup(IHostingEnvironment env)
+ {
+ Environment = env;
+
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(env.ContentRootPath);
+
+ if (env.IsDevelopment())
+ {
+ // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
+ builder.AddUserSecrets();
+ }
+
+ builder.AddEnvironmentVariables();
+ Configuration = builder.Build();
+ }
+
+ public IConfiguration Configuration { get; set; }
+
+ public IHostingEnvironment Environment { get; set; }
+
+ public void ConfigureServices(IServiceCollection services)
+ {
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
+
+ services.AddAuthentication(sharedOptions =>
+ {
+ sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
+ })
+ .AddCookie()
+ .AddOpenIdConnect(o =>
+ {
+ o.ClientId = Configuration["oidc:clientid"];
+ o.ClientSecret = Configuration["oidc:clientsecret"]; // for code flow
+ o.Authority = Configuration["oidc:authority"];
+
+ o.ResponseType = OpenIdConnectResponseType.CodeIdToken;
+ o.SaveTokens = true;
+ o.GetClaimsFromUserInfoEndpoint = true;
+
+ o.ClaimActions.MapAllExcept("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce");
+
+ o.Events = new OpenIdConnectEvents()
+ {
+ OnAuthenticationFailed = c =>
+ {
+ c.HandleResponse();
+
+ c.Response.StatusCode = 500;
+ c.Response.ContentType = "text/plain";
+ if (Environment.IsDevelopment())
+ {
+ // Debug only, in production do not share exceptions with the remote host.
+ return c.Response.WriteAsync(c.Exception.ToString());
+ }
+ return c.Response.WriteAsync("An error occurred processing your authentication.");
+ }
+ };
+ });
+ }
+
+ public void Configure(IApplicationBuilder app, IOptionsMonitor optionsMonitor)
+ {
+ app.UseDeveloperExceptionPage();
+ app.UseAuthentication();
+
+ app.Run(async context =>
+ {
+ var response = context.Response;
+
+ if (context.Request.Path.Equals("/signedout"))
+ {
+ await WriteHtmlAsync(response, async res =>
+ {
+ await res.WriteAsync($"
");
+ await res.WriteAsync(HtmlEncoder.Default.Encode(payload.ToString()).Replace(",", ", ") + " ");
+ });
+
+ return;
+ }
+
+ if (context.Request.Path.Equals("/login-challenge"))
+ {
+ // Challenge the user authentication, and force a login prompt by overwriting the
+ // "prompt". This could be used for example to require the user to re-enter their
+ // credentials at the authentication provider, to add an extra confirmation layer.
+ await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new OpenIdConnectChallengeProperties()
+ {
+ Prompt = "login",
+
+ // it is also possible to specify different scopes, e.g.
+ // Scope = new string[] { "openid", "profile", "other" }
+ });
+
+ return;
+ }
+
+ await WriteHtmlAsync(response, async res =>
+ {
+ await res.WriteAsync($"
Hello Authenticated User {HtmlEncode(user.Identity.Name)}
");
+ }
+
+ private static string HtmlEncode(string content) =>
+ string.IsNullOrEmpty(content) ? string.Empty : HtmlEncoder.Default.Encode(content);
+ }
+}
diff --git a/src/Security/samples/WsFedSample/WsFedSample.csproj b/src/Security/samples/WsFedSample/WsFedSample.csproj
new file mode 100644
index 0000000000..bc3a59f10e
--- /dev/null
+++ b/src/Security/samples/WsFedSample/WsFedSample.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net461;netcoreapp2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Security/samples/WsFedSample/compiler/resources/cert.pfx b/src/Security/samples/WsFedSample/compiler/resources/cert.pfx
new file mode 100644
index 0000000000..7118908c2d
Binary files /dev/null and b/src/Security/samples/WsFedSample/compiler/resources/cert.pfx differ
diff --git a/src/Security/shared/Microsoft.AspNetCore.ChunkingCookieManager.Sources/ChunkingCookieManager.cs b/src/Security/shared/Microsoft.AspNetCore.ChunkingCookieManager.Sources/ChunkingCookieManager.cs
new file mode 100644
index 0000000000..42cc4e2f0f
--- /dev/null
+++ b/src/Security/shared/Microsoft.AspNetCore.ChunkingCookieManager.Sources/ChunkingCookieManager.cs
@@ -0,0 +1,309 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+
+// Keep the type public for Security repo as it would be a breaking change to change the accessor now.
+// Make this type internal for other repos as it could be used by multiple projects and having it public causes type conflicts.
+#if SECURITY
+namespace Microsoft.AspNetCore.Authentication.Cookies
+{
+ ///
+ /// This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them
+ /// from requests.
+ ///
+ public class ChunkingCookieManager : ICookieManager
+ {
+#else
+namespace Microsoft.AspNetCore.Internal
+{
+ ///
+ /// This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them
+ /// from requests.
+ ///
+ internal class ChunkingCookieManager
+ {
+#endif
+ ///
+ /// The default maximum size of characters in a cookie to send back to the client.
+ ///
+ public const int DefaultChunkSize = 4050;
+
+ private const string ChunkKeySuffix = "C";
+ private const string ChunkCountPrefix = "chunks-";
+
+ public ChunkingCookieManager()
+ {
+ // Lowest common denominator. Safari has the lowest known limit (4093), and we leave little extra just in case.
+ // See http://browsercookielimits.x64.me/.
+ // Leave at least 40 in case CookiePolicy tries to add 'secure', 'samesite=strict' and/or 'httponly'.
+ ChunkSize = DefaultChunkSize;
+ }
+
+ ///
+ /// The maximum size of cookie to send back to the client. If a cookie exceeds this size it will be broken down into multiple
+ /// cookies. Set this value to null to disable this behavior. The default is 4090 characters, which is supported by all
+ /// common browsers.
+ ///
+ /// Note that browsers may also have limits on the total size of all cookies per domain, and on the number of cookies per domain.
+ ///
+ public int? ChunkSize { get; set; }
+
+ ///
+ /// Throw if not all chunks of a cookie are available on a request for re-assembly.
+ ///
+ public bool ThrowForPartialCookies { get; set; }
+
+ // Parse the "chunks-XX" to determine how many chunks there should be.
+ private static int ParseChunksCount(string value)
+ {
+ if (value != null && value.StartsWith(ChunkCountPrefix, StringComparison.Ordinal))
+ {
+ var chunksCountString = value.Substring(ChunkCountPrefix.Length);
+ int chunksCount;
+ if (int.TryParse(chunksCountString, NumberStyles.None, CultureInfo.InvariantCulture, out chunksCount))
+ {
+ return chunksCount;
+ }
+ }
+ return 0;
+ }
+
+ ///
+ /// Get the reassembled cookie. Non chunked cookies are returned normally.
+ /// Cookies with missing chunks just have their "chunks-XX" header returned.
+ ///
+ ///
+ ///
+ /// The reassembled cookie, if any, or null.
+ public string GetRequestCookie(HttpContext context, string key)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ var requestCookies = context.Request.Cookies;
+ var value = requestCookies[key];
+ var chunksCount = ParseChunksCount(value);
+ if (chunksCount > 0)
+ {
+ var chunks = new string[chunksCount];
+ for (var chunkId = 1; chunkId <= chunksCount; chunkId++)
+ {
+ var chunk = requestCookies[key + ChunkKeySuffix + chunkId.ToString(CultureInfo.InvariantCulture)];
+ if (string.IsNullOrEmpty(chunk))
+ {
+ if (ThrowForPartialCookies)
+ {
+ var totalSize = 0;
+ for (int i = 0; i < chunkId - 1; i++)
+ {
+ totalSize += chunks[i].Length;
+ }
+ throw new FormatException(
+ string.Format(
+ CultureInfo.CurrentCulture,
+ "The chunked cookie is incomplete. Only {0} of the expected {1} chunks were found, totaling {2} characters. A client size limit may have been exceeded.",
+ chunkId - 1,
+ chunksCount,
+ totalSize));
+ }
+ // Missing chunk, abort by returning the original cookie value. It may have been a false positive?
+ return value;
+ }
+
+ chunks[chunkId - 1] = chunk;
+ }
+
+ return string.Join(string.Empty, chunks);
+ }
+ return value;
+ }
+
+ ///
+ /// Appends a new response cookie to the Set-Cookie header. If the cookie is larger than the given size limit
+ /// then it will be broken down into multiple cookies as follows:
+ /// Set-Cookie: CookieName=chunks-3; path=/
+ /// Set-Cookie: CookieNameC1=Segment1; path=/
+ /// Set-Cookie: CookieNameC2=Segment2; path=/
+ /// Set-Cookie: CookieNameC3=Segment3; path=/
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if (options == null)
+ {
+ throw new ArgumentNullException(nameof(options));
+ }
+
+ var template = new SetCookieHeaderValue(key)
+ {
+ Domain = options.Domain,
+ Expires = options.Expires,
+ SameSite = (Net.Http.Headers.SameSiteMode)options.SameSite,
+ HttpOnly = options.HttpOnly,
+ Path = options.Path,
+ Secure = options.Secure,
+ };
+
+ var templateLength = template.ToString().Length;
+
+ value = value ?? string.Empty;
+
+ // Normal cookie
+ var responseCookies = context.Response.Cookies;
+ if (!ChunkSize.HasValue || ChunkSize.Value > templateLength + value.Length)
+ {
+ responseCookies.Append(key, value, options);
+ }
+ else if (ChunkSize.Value < templateLength + 10)
+ {
+ // 10 is the minimum data we want to put in an individual cookie, including the cookie chunk identifier "CXX".
+ // No room for data, we can't chunk the options and name
+ throw new InvalidOperationException("The cookie key and options are larger than ChunksSize, leaving no room for data.");
+ }
+ else
+ {
+ // Break the cookie down into multiple cookies.
+ // Key = CookieName, value = "Segment1Segment2Segment2"
+ // Set-Cookie: CookieName=chunks-3; path=/
+ // Set-Cookie: CookieNameC1="Segment1"; path=/
+ // Set-Cookie: CookieNameC2="Segment2"; path=/
+ // Set-Cookie: CookieNameC3="Segment3"; path=/
+ var dataSizePerCookie = ChunkSize.Value - templateLength - 3; // Budget 3 chars for the chunkid.
+ var cookieChunkCount = (int)Math.Ceiling(value.Length * 1.0 / dataSizePerCookie);
+
+ responseCookies.Append(key, ChunkCountPrefix + cookieChunkCount.ToString(CultureInfo.InvariantCulture), options);
+
+ var offset = 0;
+ for (var chunkId = 1; chunkId <= cookieChunkCount; chunkId++)
+ {
+ var remainingLength = value.Length - offset;
+ var length = Math.Min(dataSizePerCookie, remainingLength);
+ var segment = value.Substring(offset, length);
+ offset += length;
+
+ responseCookies.Append(key + ChunkKeySuffix + chunkId.ToString(CultureInfo.InvariantCulture), segment, options);
+ }
+ }
+ }
+
+ ///
+ /// Deletes the cookie with the given key by setting an expired state. If a matching chunked cookie exists on
+ /// the request, delete each chunk.
+ ///
+ ///
+ ///
+ ///
+ public void DeleteCookie(HttpContext context, string key, CookieOptions options)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+
+ if (options == null)
+ {
+ throw new ArgumentNullException(nameof(options));
+ }
+
+ var keys = new List();
+ keys.Add(key + "=");
+
+ var requestCookie = context.Request.Cookies[key];
+ var chunks = ParseChunksCount(requestCookie);
+ if (chunks > 0)
+ {
+ for (int i = 1; i <= chunks + 1; i++)
+ {
+ var subkey = key + ChunkKeySuffix + i.ToString(CultureInfo.InvariantCulture);
+ keys.Add(subkey + "=");
+ }
+ }
+
+ var domainHasValue = !string.IsNullOrEmpty(options.Domain);
+ var pathHasValue = !string.IsNullOrEmpty(options.Path);
+
+ Func rejectPredicate;
+ Func predicate = value => keys.Any(k => value.StartsWith(k, StringComparison.OrdinalIgnoreCase));
+ if (domainHasValue)
+ {
+ rejectPredicate = value => predicate(value) && value.IndexOf("domain=" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;
+ }
+ else if (pathHasValue)
+ {
+ rejectPredicate = value => predicate(value) && value.IndexOf("path=" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;
+ }
+ else
+ {
+ rejectPredicate = value => predicate(value);
+ }
+
+ var responseHeaders = context.Response.Headers;
+ var existingValues = responseHeaders[HeaderNames.SetCookie];
+ if (!StringValues.IsNullOrEmpty(existingValues))
+ {
+ responseHeaders[HeaderNames.SetCookie] = existingValues.Where(value => !rejectPredicate(value)).ToArray();
+ }
+
+ AppendResponseCookie(
+ context,
+ key,
+ string.Empty,
+ new CookieOptions()
+ {
+ Path = options.Path,
+ Domain = options.Domain,
+ SameSite = options.SameSite,
+ IsEssential = options.IsEssential,
+ Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
+ });
+
+ for (int i = 1; i <= chunks; i++)
+ {
+ AppendResponseCookie(
+ context,
+ key + "C" + i.ToString(CultureInfo.InvariantCulture),
+ string.Empty,
+ new CookieOptions()
+ {
+ Path = options.Path,
+ Domain = options.Domain,
+ SameSite = options.SameSite,
+ IsEssential = options.IsEssential,
+ Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
+ });
+ }
+ }
+ }
+}
diff --git a/src/Security/src/Directory.Build.props b/src/Security/src/Directory.Build.props
new file mode 100644
index 0000000000..1e0980f663
--- /dev/null
+++ b/src/Security/src/Directory.Build.props
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/Constants.cs b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/Constants.cs
new file mode 100644
index 0000000000..3aabf94c15
--- /dev/null
+++ b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/Constants.cs
@@ -0,0 +1,13 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace Microsoft.AspNetCore.Authentication.Cookies
+{
+ internal static class Constants
+ {
+ internal static class Headers
+ {
+ internal const string SetCookie = "Set-Cookie";
+ }
+ }
+}
diff --git a/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAppBuilderExtensions.cs b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAppBuilderExtensions.cs
new file mode 100644
index 0000000000..bdfd43c796
--- /dev/null
+++ b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAppBuilderExtensions.cs
@@ -0,0 +1,37 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.AspNetCore.Authentication.Cookies;
+
+namespace Microsoft.AspNetCore.Builder
+{
+ ///
+ /// Extension methods to add cookie authentication capabilities to an HTTP application pipeline.
+ ///
+ public static class CookieAppBuilderExtensions
+ {
+ ///
+ /// UseCookieAuthentication is obsolete. Configure Cookie authentication with AddAuthentication().AddCookie in ConfigureServices. See https://go.microsoft.com/fwlink/?linkid=845470 for more details.
+ ///
+ /// The to add the handler to.
+ /// A reference to this instance after the operation has completed.
+ [Obsolete("UseCookieAuthentication is obsolete. Configure Cookie authentication with AddAuthentication().AddCookie in ConfigureServices. See https://go.microsoft.com/fwlink/?linkid=845470 for more details.", error: true)]
+ public static IApplicationBuilder UseCookieAuthentication(this IApplicationBuilder app)
+ {
+ throw new NotSupportedException("This method is no longer supported, see https://go.microsoft.com/fwlink/?linkid=845470");
+ }
+
+ ///
+ /// UseCookieAuthentication is obsolete. Configure Cookie authentication with AddAuthentication().AddCookie in ConfigureServices. See https://go.microsoft.com/fwlink/?linkid=845470 for more details.
+ ///
+ /// The to add the handler to.
+ /// A that specifies options for the handler.
+ /// A reference to this instance after the operation has completed.
+ [Obsolete("UseCookieAuthentication is obsolete. Configure Cookie authentication with AddAuthentication().AddCookie in ConfigureServices. See https://go.microsoft.com/fwlink/?linkid=845470 for more details.", error: true)]
+ public static IApplicationBuilder UseCookieAuthentication(this IApplicationBuilder app, CookieAuthenticationOptions options)
+ {
+ throw new NotSupportedException("This method is no longer supported, see https://go.microsoft.com/fwlink/?linkid=845470");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationDefaults.cs b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationDefaults.cs
new file mode 100644
index 0000000000..700b607976
--- /dev/null
+++ b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationDefaults.cs
@@ -0,0 +1,46 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Authentication.Cookies
+{
+ ///
+ /// Default values related to cookie-based authentication handler
+ ///
+ public static class CookieAuthenticationDefaults
+ {
+ ///
+ /// The default value used for CookieAuthenticationOptions.AuthenticationScheme
+ ///
+ public const string AuthenticationScheme = "Cookies";
+
+ ///
+ /// The prefix used to provide a default CookieAuthenticationOptions.CookieName
+ ///
+ public static readonly string CookiePrefix = ".AspNetCore.";
+
+ ///
+ /// The default value used by CookieAuthenticationMiddleware for the
+ /// CookieAuthenticationOptions.LoginPath
+ ///
+ public static readonly PathString LoginPath = new PathString("/Account/Login");
+
+ ///
+ /// The default value used by CookieAuthenticationMiddleware for the
+ /// CookieAuthenticationOptions.LogoutPath
+ ///
+ public static readonly PathString LogoutPath = new PathString("/Account/Logout");
+
+ ///
+ /// The default value used by CookieAuthenticationMiddleware for the
+ /// CookieAuthenticationOptions.AccessDeniedPath
+ ///
+ public static readonly PathString AccessDeniedPath = new PathString("/Account/AccessDenied");
+
+ ///
+ /// The default value of the CookieAuthenticationOptions.ReturnUrlParameter
+ ///
+ public static readonly string ReturnUrlParameter = "ReturnUrl";
+ }
+}
diff --git a/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs
new file mode 100644
index 0000000000..b77a51ef4f
--- /dev/null
+++ b/src/Security/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs
@@ -0,0 +1,451 @@
+// 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.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Net.Http.Headers;
+
+namespace Microsoft.AspNetCore.Authentication.Cookies
+{
+ public class CookieAuthenticationHandler : SignInAuthenticationHandler
+ {
+ private const string HeaderValueNoCache = "no-cache";
+ private const string HeaderValueEpocDate = "Thu, 01 Jan 1970 00:00:00 GMT";
+ private const string SessionIdClaim = "Microsoft.AspNetCore.Authentication.Cookies-SessionId";
+
+ private bool _shouldRefresh;
+ private bool _signInCalled;
+ private bool _signOutCalled;
+
+ private DateTimeOffset? _refreshIssuedUtc;
+ private DateTimeOffset? _refreshExpiresUtc;
+ private string _sessionKey;
+ private Task _readCookieTask;
+ private AuthenticationTicket _refreshTicket;
+
+ public CookieAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
+ : base(options, logger, encoder, clock)
+ { }
+
+ ///
+ /// The handler calls methods on the events which give the application control at certain points where processing is occurring.
+ /// If it is not provided a default instance is supplied which does nothing when the methods are called.
+ ///
+ protected new CookieAuthenticationEvents Events
+ {
+ get { return (CookieAuthenticationEvents)base.Events; }
+ set { base.Events = value; }
+ }
+
+ protected override Task InitializeHandlerAsync()
+ {
+ // Cookies needs to finish the response
+ Context.Response.OnStarting(FinishResponseAsync);
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Creates a new instance of the events instance.
+ ///
+ /// A new instance of the events instance.
+ protected override Task