Merge the release/2.2 branch of aspnet/Identity

This commit is contained in:
Nate McMaster 2018-12-04 14:49:11 -08:00
commit 2c376ebc0c
No known key found for this signature in database
GPG Key ID: A778D9601BD78810
463 changed files with 94627 additions and 12799 deletions

View File

@ -15,6 +15,8 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Workaround microsoft/msbuild#3626 -->
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
</PropertyGroup>
</Project>

View File

@ -1,7 +1,10 @@
<Project>
<Project>
<PropertyGroup>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.2' ">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
</PropertyGroup>
</Project>

View File

@ -45,8 +45,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.targets = Directory.Build.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeWPFClient", "samples\NativeWPFClient\NativeWPFClient.csproj", "{39AA4E4D-5E62-4213-8641-BF8012D45DE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentitySample.DefaultUI", "samples\IdentitySample.DefaultUI\IdentitySample.DefaultUI.csproj", "{ACC75F4F-EA7D-49E0-A64C-9D4A3DFD5B8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.UI", "src\UI\Microsoft.AspNetCore.Identity.UI.csproj", "{894E102D-56D4-4B02-8F13-8781F4324C3E}"
@ -54,6 +52,15 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.DefaultUI.WebSite", "test\WebSites\Identity.DefaultUI.WebSite\Identity.DefaultUI.WebSite.csproj", "{CAE02AD2-F941-4ACB-B469-13EFF551BB74}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.FunctionalTests", "test\Identity.FunctionalTests\Microsoft.AspNetCore.Identity.FunctionalTests.csproj", "{B3616029-7DA6-4FB3-8722-D5AC69884B3F}"
ProjectSection(ProjectDependencies) = postProject
{894E102D-56D4-4B02-8F13-8781F4324C3E} = {894E102D-56D4-4B02-8F13-8781F4324C3E}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiAuthSample", "samples\ApiAuthSample\ApiAuthSample.csproj", "{7FA90737-4A2D-4BBB-8245-F6564D462FCB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ApiAuthorization.IdentityServer", "src\ApiAuth.IS\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj", "{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Test", "test\ApiAuth.IS.Test\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Test.csproj", "{ECFE11DD-1111-4557-8E28-42F8E9878823}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -335,28 +342,6 @@ Global
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.ReleaseNoWPF|x64.Build.0 = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.ReleaseNoWPF|x86.ActiveCfg = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.ReleaseNoWPF|x86.Build.0 = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|x64.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|x64.Build.0 = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|x86.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Debug|x86.Build.0 = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.DebugNoWPF|Any CPU.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.DebugNoWPF|x64.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.DebugNoWPF|x64.Build.0 = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.DebugNoWPF|x86.ActiveCfg = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.DebugNoWPF|x86.Build.0 = Debug|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|Any CPU.Build.0 = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|x64.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|x64.Build.0 = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|x86.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.Release|x86.Build.0 = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.ReleaseNoWPF|Any CPU.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.ReleaseNoWPF|x64.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.ReleaseNoWPF|x64.Build.0 = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.ReleaseNoWPF|x86.ActiveCfg = Release|Any CPU
{39AA4E4D-5E62-4213-8641-BF8012D45DE4}.ReleaseNoWPF|x86.Build.0 = Release|Any CPU
{ACC75F4F-EA7D-49E0-A64C-9D4A3DFD5B8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACC75F4F-EA7D-49E0-A64C-9D4A3DFD5B8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACC75F4F-EA7D-49E0-A64C-9D4A3DFD5B8A}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -423,8 +408,8 @@ Global
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.Release|x64.Build.0 = Release|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.Release|x86.ActiveCfg = Release|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.Release|x86.Build.0 = Release|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|Any CPU.ActiveCfg = Debug|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|Any CPU.Build.0 = Debug|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|Any CPU.ActiveCfg = Release|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|Any CPU.Build.0 = Release|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|x64.ActiveCfg = Debug|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|x64.Build.0 = Debug|Any CPU
{CAE02AD2-F941-4ACB-B469-13EFF551BB74}.ReleaseNoWPF|x86.ActiveCfg = Debug|Any CPU
@ -453,6 +438,78 @@ Global
{B3616029-7DA6-4FB3-8722-D5AC69884B3F}.ReleaseNoWPF|x64.Build.0 = Debug|Any CPU
{B3616029-7DA6-4FB3-8722-D5AC69884B3F}.ReleaseNoWPF|x86.ActiveCfg = Debug|Any CPU
{B3616029-7DA6-4FB3-8722-D5AC69884B3F}.ReleaseNoWPF|x86.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|x64.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|x64.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|x86.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Debug|x86.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|Any CPU.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|Any CPU.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|x64.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|x64.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|x86.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.DebugNoWPF|x86.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|Any CPU.Build.0 = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|x64.ActiveCfg = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|x64.Build.0 = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|x86.ActiveCfg = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.Release|x86.Build.0 = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|Any CPU.ActiveCfg = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|Any CPU.Build.0 = Release|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|x64.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|x64.Build.0 = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|x86.ActiveCfg = Debug|Any CPU
{7FA90737-4A2D-4BBB-8245-F6564D462FCB}.ReleaseNoWPF|x86.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|x64.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|x64.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Debug|x86.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|Any CPU.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|Any CPU.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|x64.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|x64.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|x86.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.DebugNoWPF|x86.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|Any CPU.Build.0 = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|x64.ActiveCfg = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|x64.Build.0 = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|x86.ActiveCfg = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.Release|x86.Build.0 = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|Any CPU.ActiveCfg = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|Any CPU.Build.0 = Release|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|x64.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|x64.Build.0 = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|x86.ActiveCfg = Debug|Any CPU
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4}.ReleaseNoWPF|x86.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|x64.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|x64.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|x86.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Debug|x86.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|Any CPU.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|Any CPU.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|x64.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|x64.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|x86.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.DebugNoWPF|x86.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|Any CPU.Build.0 = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|x64.ActiveCfg = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|x64.Build.0 = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|x86.ActiveCfg = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.Release|x86.Build.0 = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|Any CPU.ActiveCfg = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|Any CPU.Build.0 = Release|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|x64.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|x64.Build.0 = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|x86.ActiveCfg = Debug|Any CPU
{ECFE11DD-1111-4557-8E28-42F8E9878823}.ReleaseNoWPF|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -470,11 +527,13 @@ Global
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{FADA11FC-DC06-4832-A569-7B2374A6CD42} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{1F83D453-E094-4D28-BCFA-9E537ABB5AD6} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{39AA4E4D-5E62-4213-8641-BF8012D45DE4} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
{ACC75F4F-EA7D-49E0-A64C-9D4A3DFD5B8A} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
{894E102D-56D4-4B02-8F13-8781F4324C3E} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{CAE02AD2-F941-4ACB-B469-13EFF551BB74} = {1F83D453-E094-4D28-BCFA-9E537ABB5AD6}
{B3616029-7DA6-4FB3-8722-D5AC69884B3F} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{7FA90737-4A2D-4BBB-8245-F6564D462FCB} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
{590C70E2-FCCC-49C2-93F3-60B7AA0533A4} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{ECFE11DD-1111-4557-8E28-42F8E9878823} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B3F2A592-CCE0-40C2-8CA4-7B1293DED874}

View File

@ -1,319 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0F647068-6602-4E24-B1DC-8ED91481A50A}"
ProjectSection(SolutionItems) = preProject
src\Directory.Build.props = src\Directory.Build.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{52D59F18-62D2-4D17-8CF2-BE192445AF8E}"
ProjectSection(SolutionItems) = preProject
test\Directory.Build.props = test\Directory.Build.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity", "src\Identity\Microsoft.AspNetCore.Identity.csproj", "{1729302E-A58E-4652-B639-5B6B68DA2748}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.Test", "test\Identity.Test\Microsoft.AspNetCore.Identity.Test.csproj", "{2CF3927B-19E4-4866-9BAA-2C131580E7C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.InMemory.Test", "test\InMemory.Test\Microsoft.AspNetCore.Identity.InMemory.Test.csproj", "{65161409-C4C4-4D63-A73B-231FCFF4D503}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentitySample.Mvc", "samples\IdentitySample.Mvc\IdentitySample.Mvc.csproj", "{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test", "test\EF.Test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj", "{37236EA3-915D-46D5-997C-DF513C500E4B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test", "test\EF.InMemory.Test\Microsoft.AspNetCore.Identity.EntityFrameworkCore.InMemory.Test.csproj", "{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.EntityFrameworkCore", "src\EF\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj", "{4490894C-3572-4E63-86F1-EE5105CE8A06}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.Identity.AspNetCoreCompat", "src\AspNetCoreCompat\Microsoft.AspNet.Identity.AspNetCoreCompat.csproj", "{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.Specification.Tests", "src\Specification.Tests\Microsoft.AspNetCore.Identity.Specification.Tests.csproj", "{5608E828-DD54-4E2A-B73C-FC22268BE797}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Identity.Core", "src\Core\Microsoft.Extensions.Identity.Core.csproj", "{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Identity.Stores", "src\Stores\Microsoft.Extensions.Identity.Stores.csproj", "{FADA11FC-DC06-4832-A569-7B2374A6CD42}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2C657F6C-D8AD-4833-9C59-2301A16957BD}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentitySample.DefaultUI", "samples\IdentitySample.DefaultUI\IdentitySample.DefaultUI.csproj", "{D5FB2E24-4C71-430C-A289-59C8D59164B0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.UI", "src\UI\Microsoft.AspNetCore.Identity.UI.csproj", "{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Identity.FunctionalTests", "test\Identity.FunctionalTests\Microsoft.AspNetCore.Identity.FunctionalTests.csproj", "{BAC36757-9A47-43CB-A6F3-86E8C4650A28}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{C47C1165-9F19-4DF8-ABA9-707ACEB3BDC7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.DefaultUI.WebSite", "test\WebSites\Identity.DefaultUI.WebSite\Identity.DefaultUI.WebSite.csproj", "{EA424B4D-0BE1-49AC-A106-CC6CC808A104}"
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
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x64.ActiveCfg = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x64.Build.0 = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Debug|x86.ActiveCfg = Debug|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Any CPU.Build.0 = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x64.ActiveCfg = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x64.Build.0 = Release|Any CPU
{1729302E-A58E-4652-B639-5B6B68DA2748}.Release|x86.ActiveCfg = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x64.ActiveCfg = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x64.Build.0 = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Debug|x86.ActiveCfg = Debug|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Any CPU.Build.0 = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x64.ActiveCfg = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x64.Build.0 = Release|Any CPU
{2CF3927B-19E4-4866-9BAA-2C131580E7C3}.Release|x86.ActiveCfg = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x64.ActiveCfg = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x64.Build.0 = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Debug|x86.ActiveCfg = Debug|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Any CPU.Build.0 = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x64.ActiveCfg = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x64.Build.0 = Release|Any CPU
{65161409-C4C4-4D63-A73B-231FCFF4D503}.Release|x86.ActiveCfg = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x64.ActiveCfg = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x64.Build.0 = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Any CPU.Build.0 = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x64.ActiveCfg = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x64.Build.0 = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x86.ActiveCfg = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x64.ActiveCfg = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x64.Build.0 = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Debug|x86.ActiveCfg = Debug|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Any CPU.Build.0 = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x64.ActiveCfg = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x64.Build.0 = Release|Any CPU
{37236EA3-915D-46D5-997C-DF513C500E4B}.Release|x86.ActiveCfg = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x64.ActiveCfg = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x64.Build.0 = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Debug|x86.ActiveCfg = Debug|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Any CPU.Build.0 = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x64.ActiveCfg = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x64.Build.0 = Release|Any CPU
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD}.Release|x86.ActiveCfg = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x64.ActiveCfg = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x64.Build.0 = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Debug|x86.ActiveCfg = Debug|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Any CPU.Build.0 = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x64.ActiveCfg = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x64.Build.0 = Release|Any CPU
{4490894C-3572-4E63-86F1-EE5105CE8A06}.Release|x86.ActiveCfg = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x64.ActiveCfg = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x64.Build.0 = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x86.ActiveCfg = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Debug|x86.Build.0 = Debug|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Any CPU.Build.0 = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x64.ActiveCfg = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x64.Build.0 = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x86.ActiveCfg = Release|Any CPU
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475}.Release|x86.Build.0 = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x64.ActiveCfg = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x64.Build.0 = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x86.ActiveCfg = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Debug|x86.Build.0 = Debug|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Any CPU.Build.0 = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x64.ActiveCfg = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x64.Build.0 = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x86.ActiveCfg = Release|Any CPU
{5608E828-DD54-4E2A-B73C-FC22268BE797}.Release|x86.Build.0 = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x64.ActiveCfg = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x64.Build.0 = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x86.ActiveCfg = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Debug|x86.Build.0 = Debug|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Any CPU.Build.0 = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x64.ActiveCfg = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x64.Build.0 = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x86.ActiveCfg = Release|Any CPU
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8}.Release|x86.Build.0 = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x64.ActiveCfg = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x64.Build.0 = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x86.ActiveCfg = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Debug|x86.Build.0 = Debug|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Any CPU.Build.0 = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x64.ActiveCfg = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x64.Build.0 = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x86.ActiveCfg = Release|Any CPU
{FADA11FC-DC06-4832-A569-7B2374A6CD42}.Release|x86.Build.0 = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|x64.ActiveCfg = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|x64.Build.0 = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|x86.ActiveCfg = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Debug|x86.Build.0 = Debug|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|Any CPU.Build.0 = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|x64.ActiveCfg = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|x64.Build.0 = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|x86.ActiveCfg = Release|Any CPU
{D5FB2E24-4C71-430C-A289-59C8D59164B0}.Release|x86.Build.0 = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|x64.ActiveCfg = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|x64.Build.0 = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|x86.ActiveCfg = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Debug|x86.Build.0 = Debug|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|Any CPU.Build.0 = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|x64.ActiveCfg = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|x64.Build.0 = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|x86.ActiveCfg = Release|Any CPU
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB}.Release|x86.Build.0 = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|x64.ActiveCfg = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|x64.Build.0 = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|x86.ActiveCfg = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Debug|x86.Build.0 = Debug|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|Any CPU.Build.0 = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|x64.ActiveCfg = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|x64.Build.0 = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|x86.ActiveCfg = Release|Any CPU
{BAC36757-9A47-43CB-A6F3-86E8C4650A28}.Release|x86.Build.0 = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|x64.ActiveCfg = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|x64.Build.0 = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|x86.ActiveCfg = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Debug|x86.Build.0 = Debug|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|Any CPU.Build.0 = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|x64.ActiveCfg = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|x64.Build.0 = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|x86.ActiveCfg = Release|Any CPU
{EA424B4D-0BE1-49AC-A106-CC6CC808A104}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1729302E-A58E-4652-B639-5B6B68DA2748} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{2CF3927B-19E4-4866-9BAA-2C131580E7C3} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{65161409-C4C4-4D63-A73B-231FCFF4D503} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
{37236EA3-915D-46D5-997C-DF513C500E4B} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{EA7EB28F-53B8-4009-9C6B-74DB090CA8DD} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{4490894C-3572-4E63-86F1-EE5105CE8A06} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{6A74C6EA-B241-4D6B-BCE4-BF89EC1D2475} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{5608E828-DD54-4E2A-B73C-FC22268BE797} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{D5905D78-A32E-44B8-8F21-EDAEDC95D9B8} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{FADA11FC-DC06-4832-A569-7B2374A6CD42} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{D5FB2E24-4C71-430C-A289-59C8D59164B0} = {58D94A0E-C2B7-43A7-8826-99ECBB1E0A50}
{1FB3E9BB-E20A-4807-A4C3-F86A341304DB} = {0F647068-6602-4E24-B1DC-8ED91481A50A}
{BAC36757-9A47-43CB-A6F3-86E8C4650A28} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{C47C1165-9F19-4DF8-ABA9-707ACEB3BDC7} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E}
{EA424B4D-0BE1-49AC-A106-CC6CC808A104} = {C47C1165-9F19-4DF8-ABA9-707ACEB3BDC7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21D598B0-2383-4B22-826D-E7FB4921BD66}
EndGlobalSection
EndGlobal

View File

@ -7,8 +7,8 @@
"Microsoft.AspNetCore.Identity.UI": {
"Exclusions": {
"DOC_MISSING": {
"lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll": "This is a library with packaged UI",
"lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.dll": "This assembly is generated and contains precompiled razor pages"
"lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V3.dll": "This assembly is generated and contains precompiled razor pages",
"lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll": "This assembly is generated and contains precompiled razor pages"
}
}
}

View File

@ -2,80 +2,80 @@
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<!-- These package versions may be overridden or updated by automation. -->
<PropertyGroup Label="Package Versions: Auto">
<PropertyGroup Label="Package Versions">
<AngleSharpPackageVersion>0.9.9</AngleSharpPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15831</InternalAspNetCoreSdkPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview2-20181004.6</InternalAspNetCoreSdkPackageVersion>
<IdentityServer4AspNetIdentityPackageVersion>2.3.0</IdentityServer4AspNetIdentityPackageVersion>
<IdentityServer4EntityFrameworkPackageVersion>2.3.0</IdentityServer4EntityFrameworkPackageVersion>
<IdentityServer4PackageVersion>2.3.0</IdentityServer4PackageVersion>
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
<MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>
<MicrosoftAspNetCoreAuthenticationGooglePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationGooglePackageVersion>
<MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>
<MicrosoftAspNetCoreAuthenticationTwitterPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationTwitterPackageVersion>
<MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>
<MicrosoftAspNetCoreAuthorizationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAuthorizationPackageVersion>
<MicrosoftAspNetCoreCookiePolicyPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreCookiePolicyPackageVersion>
<MicrosoftAspNetCoreCryptographyKeyDerivationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreCryptographyKeyDerivationPackageVersion>
<MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>
<MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreDiagnosticsPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreHttpsPolicyPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreHttpsPolicyPackageVersion>
<MicrosoftAspNetCoreMvcPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreMvcPackageVersion>
<MicrosoftAspNetCoreMvcRazorViewCompilationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreMvcRazorViewCompilationPackageVersion>
<MicrosoftAspNetCoreMvcTestingPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreMvcTestingPackageVersion>
<MicrosoftAspNetCoreRazorDesignPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreRazorDesignPackageVersion>
<MicrosoftAspNetCoreRewritePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreRewritePackageVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
<MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreStaticFilesPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetIdentityEntityFrameworkPackageVersion>2.2.1</MicrosoftAspNetIdentityEntityFrameworkPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.5</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>2.2.0-preview3-35425</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>2.2.0-preview3-35425</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>2.2.0-preview3-35425</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.2.0-preview3-35425</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>2.2.0-preview3-35425</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview3-27001-02</MicrosoftNETCoreApp22PackageVersion>
<MicrosoftNETSdkRazorPackageVersion>2.2.0-preview3-35425</MicrosoftNETSdkRazorPackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
<MicrosoftOwinSecurityCookiesPackageVersion>3.0.1</MicrosoftOwinSecurityCookiesPackageVersion>
<MicrosoftOwinSecurityInteropPackageVersion>2.2.0-preview3-35425</MicrosoftOwinSecurityInteropPackageVersion>
<MoqPackageVersion>4.7.49</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<SystemComponentModelAnnotationsPackageVersion>4.5.0</SystemComponentModelAnnotationsPackageVersion>
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitAssertPackageVersion>2.3.1</XunitAssertPackageVersion>
<XunitExtensibilityCorePackageVersion>2.3.1</XunitExtensibilityCorePackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
</PropertyGroup>
<!-- This may import a generated file which may override the variables above. -->
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
<!-- These are package versions that should not be overridden or updated by automation. -->
<PropertyGroup Label="Package Versions: Pinned">
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
<MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>
<MicrosoftAspNetCoreAuthenticationGooglePackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationGooglePackageVersion>
<MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>
<MicrosoftAspNetCoreAuthenticationTwitterPackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationTwitterPackageVersion>
<MicrosoftAspNetCoreAuthorizationPackageVersion>2.1.1</MicrosoftAspNetCoreAuthorizationPackageVersion>
<MicrosoftAspNetCoreCookiePolicyPackageVersion>2.1.1</MicrosoftAspNetCoreCookiePolicyPackageVersion>
<MicrosoftAspNetCoreCryptographyKeyDerivationPackageVersion>2.1.1</MicrosoftAspNetCoreCryptographyKeyDerivationPackageVersion>
<MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>2.1.1</MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion>
<MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>2.1.1</MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion>
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.1.1</MicrosoftAspNetCoreDiagnosticsPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.1.1</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.1.1</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreHttpsPolicyPackageVersion>2.1.1</MicrosoftAspNetCoreHttpsPolicyPackageVersion>
<MicrosoftAspNetCoreMvcPackageVersion>2.1.1</MicrosoftAspNetCoreMvcPackageVersion>
<MicrosoftAspNetCoreMvcRazorViewCompilationPackageVersion>2.1.1</MicrosoftAspNetCoreMvcRazorViewCompilationPackageVersion>
<MicrosoftAspNetCoreMvcTestingPackageVersion>2.1.1</MicrosoftAspNetCoreMvcTestingPackageVersion>
<MicrosoftAspNetCoreRazorDesignPackageVersion>2.1.1</MicrosoftAspNetCoreRazorDesignPackageVersion>
<MicrosoftAspNetCoreRewritePackageVersion>2.1.1</MicrosoftAspNetCoreRewritePackageVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
<MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.1.1</MicrosoftAspNetCoreStaticFilesPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>2.1.1</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>2.1.1</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>2.1.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.1</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.1.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.1.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>2.1.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>2.1.1</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>2.1.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.1.1</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>2.1.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.1</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.1.1</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.1.1</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.1</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>2.1.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.1.1</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>2.1.1</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.1.1</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>2.1.1</MicrosoftNETSdkRazorPackageVersion>
<MicrosoftOwinSecurityInteropPackageVersion>2.1.1</MicrosoftOwinSecurityInteropPackageVersion>
</PropertyGroup>
<PropertyGroup Label="Package Versions: Pinned" />
</Project>

View File

@ -1,19 +1,16 @@
<Project>
<Import Project="dependencies.props" />
<ItemGroup>
<ExcludeSolutions Include="$(RepositoryRoot)IdentityCore.sln" />
<ExcludeSolutions Include="$(RepositoryRoot)Identity.Samples.sln" />
</ItemGroup>
<PropertyGroup>
<!-- These properties are use by the automation that updates dependencies.props -->
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
<LineupPackageVersion>2.1.0-rc1-*</LineupPackageVersion>
<LineupPackageVersion>2.2.0-*</LineupPackageVersion>
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
</PropertyGroup>
<ItemGroup>
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp22PackageVersion)" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>
<UserSecretsId>aspnet-ApiAuthSample-12ED8ECC-9EF1-4D31-87B4-1405B3198E5E</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="$(MicrosoftAspNetCoreCookiePolicyPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.HttpsPolicy" Version="$(MicrosoftAspNetCoreHttpsPolicyPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Extensions" Version="$(MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="$(MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="$(MicrosoftAspNetCoreRewritePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="$(MicrosoftAspNetCoreServerKestrelHttpsPackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(MicrosoftEntityFrameworkCoreSqlitePackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" PrivateAssets="All" Version="$(MicrosoftEntityFrameworkCoreToolsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="$(MicrosoftExtensionsLoggingConfigurationPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.NET.Sdk.Razor" Version="$(MicrosoftNETSdkRazorPackageVersion)" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ApiAuth.IS\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj" />
<ProjectReference Include="..\..\src\EF\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\UI\Microsoft.AspNetCore.Identity.UI.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,25 @@
@using Microsoft.AspNetCore.Identity
@using ApiAuthSample.Models;
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@if (SignInManager.IsSignedIn(User))
{
<form asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/Index", new { area = "" })" method="post" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
</li>
<li>
<button type="submit" class="btn btn-link navbar-btn navbar-link">Logout</button>
</li>
</ul>
</form>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li><a asp-area="Identity" asp-page="/Account/Register">Register</a></li>
<li><a asp-area="Identity" asp-page="/Account/Login">Login</a></li>
</ul>
}

View File

@ -0,0 +1,5 @@
@using Microsoft.AspNetCore.Identity
@using ApiAuthSample.Areas.Identity
@using ApiAuthSample.Models
@namespace ApiAuthSample.Areas.Identity.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace ApiAuthSample.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}

View File

@ -0,0 +1,27 @@
using IdentityServer4.EntityFramework.Options;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using ApiAuthSample.Models;
namespace ApiAuthSample.Data
{
public class ApplicationDbContext : ApiAuthorizationDbContext<ApplicationUser>
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> options,
IOptions<OperationalStoreOptions> operationalStoreOptions)
: base(options, operationalStoreOptions)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
}

View File

@ -0,0 +1,260 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ApiAuthSample.Data;
namespace ApiAuthSample.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20180919224505_InitialMigration")]
partial class InitialMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
.HasMaxLength(200);
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
b.Property<DateTime>("CreationTime");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
b.Property<DateTime?>("Expiration");
b.Property<string>("SubjectId")
.HasMaxLength(200);
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50);
b.HasKey("Key");
b.HasIndex("SubjectId", "ClientId", "Type");
b.ToTable("PersistedGrants");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("ApiAuthSample.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,242 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace ApiAuthSample.Data.Migrations
{
public partial class InitialMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "PersistedGrants",
columns: table => new
{
Key = table.Column<string>(maxLength: 200, nullable: false),
Type = table.Column<string>(maxLength: 50, nullable: false),
SubjectId = table.Column<string>(maxLength: 200, nullable: true),
ClientId = table.Column<string>(maxLength: 200, nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
Expiration = table.Column<DateTime>(nullable: true),
Data = table.Column<string>(maxLength: 50000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PersistedGrants", x => x.Key);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
ProviderKey = table.Column<string>(maxLength: 128, nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",
columns: new[] { "SubjectId", "ClientId", "Type" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "PersistedGrants");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

View File

@ -0,0 +1,258 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ApiAuthSample.Data;
namespace ApiAuthSample.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
.HasMaxLength(200);
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
b.Property<DateTime>("CreationTime");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
b.Property<DateTime?>("Expiration");
b.Property<string>("SubjectId")
.HasMaxLength(200);
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50);
b.HasKey("Key");
b.HasIndex("SubjectId", "ClientId", "Type");
b.ToTable("PersistedGrants");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("ApiAuthSample.Models.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("ApiAuthSample.Models.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,9 @@
using Microsoft.AspNetCore.Identity;
namespace ApiAuthSample.Models
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
}
}

View File

@ -0,0 +1,33 @@
@page
@addTagHelper *, Microsoft.AspNetCore.ApiAuthorization.IdentityServer
@model ApiAuthSample.Pages.IndexModel
@{
ViewData["Title"] = "Index";
}
<!DOCTYPE html>
<html>
<head>
<title>@ViewData["Title"]</title>
</head>
<body>
<h1>ApiAuthSample SPA client</h1>
<button id="login">Login</button>
<button id="logout" disabled>Logout</button>
<button id="call-api" disabled>Call API</button>
<div id="login-result"></div>
<div id="api-result"></div>
<script src="js/oidc-client.js"></script>
<script id="apiauth" type="text/javascript" asp-apiauth-parameters="ApiAuthSampleSPA">
let $data = document.querySelector("#apiauth");
let configuration = {};
for (let key in $data.dataset) {
configuration[key] = $data.dataset[key];
}
let mgr = new Oidc.UserManager(configuration);
</script>
<script src="js/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ApiAuthSample.Pages
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}

View File

@ -0,0 +1,75 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Reflection;
namespace ApiAuthSample
{
public class Program
{
public static void Main(string[] args)
{
if (args == null)
{
throw new ArgumentNullException(nameof(args));
}
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var builder = new WebHostBuilder()
.UseKestrel((builderContext, options) =>
{
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseIISIntegration()
.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
});
if (args != null)
{
builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
}
builder.UseStartup<Startup>();
return builder;
}
}
}

View File

@ -0,0 +1,33 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:14440",
"sslPort": 44316
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ApiAuthSample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}"
}
}
}

View File

@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ApiAuthSample.Data;
using ApiAuthSample.Models;
namespace ApiAuthSample
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseIdentityServer();
app.UseMvc();
}
}
}

Binary file not shown.

View File

@ -0,0 +1,14 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Debug",
"Microsoft": "Debug"
}
},
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
}

View File

@ -0,0 +1,13 @@
{
"ConnectionStrings": {
"DefaultConnection": "DataSource=app.db"
},
"IdentityServer": {
"Clients": {
"ApiAuthSampleSPA": {
"Profile": "IdentityServerSPA"
}
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,60 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"optional": true,
"requires": {
"babel-runtime": "6.26.0",
"core-js": "2.5.7",
"regenerator-runtime": "0.10.5"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"optional": true,
"requires": {
"core-js": "2.5.7",
"regenerator-runtime": "0.11.1"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
"optional": true
}
}
},
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
},
"jsrsasign": {
"version": "8.0.12",
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.12.tgz",
"integrity": "sha1-Iqu5ZW00owuVMENnIINeicLlwxY="
},
"oidc-client": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.5.2.tgz",
"integrity": "sha512-2w4TOraEf4PEbuo8mR8tSRhtgAHQaghBWgt2qpnwebsdW87BRMC7XKAytHcbZ1GYjFH9jJn30Cav64zbYdjiCQ==",
"requires": {
"babel-polyfill": "6.26.0",
"jsrsasign": "8.0.12"
}
},
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
"optional": true
}
}
}

View File

@ -0,0 +1,116 @@

function invokeLogin() {
// Redirects to the Authorization Server for sign in.
return mgr.signinRedirect();
}
function invokeLogout() {
// Redirects to the Authorization Server for sign out.
return mgr.signoutRedirect();
}
async function handleAuthorizationServerCallback() {
try {
let user = await mgr.signinRedirectCallback();
updateUserUI(user);
} catch (error) {
updateUserUI(undefined, error);
}
}
async function callApi() {
try {
let user = await mgr.getUser();
let response = await fetch(
window.location.origin + '/api/values',
{
method: 'GET',
headers: {
'Authorization': `Bearer ${user.access_token}`
}
});
if (response.ok) {
return await response.json();
} else {
let text = await response.text();
return text;
}
} catch (e) {
return e.message;
}
}
// Code to update the UI
if (window.location.hash) {
handleAuthorizationServerCallback();
window.location.hash = '';
}
let ids = {
login: 'login',
logout: 'logout',
callApi: 'call-api',
loginResult: 'login-result',
apiResults: 'api-result'
};
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
let login = document.getElementById(ids.login);
let logout = document.getElementById(ids.logout);
let callApi = document.getElementById(ids.callApi);
login.addEventListener('click', invokeLogin);
logout.addEventListener('click', invokeLogout);
callApi.addEventListener('click', invokeCallApi);
}
};
function updateUserUI(user, error) {
let loginResults = document.getElementById(ids.loginResult);
let heading = document.createElement('h2');
heading.innerText = 'Login result';
if (user) {
loginResults.appendChild(heading);
loginResults.insertAdjacentText('beforeend', `Hello ${user.profile.name}`);
updateButtons(true, false, false);
} else {
loginResults.innerText = error.message;
}
}
function updateButtons(login, callApi, logout) {
let loginB = document.getElementById(ids.login);
let logoutB = document.getElementById(ids.logout);
let callApiB = document.getElementById(ids.callApi);
loginB.disabled = login;
logoutB.disabled = logout;
callApiB.disabled = callApi;
}
async function invokeCallApi() {
let result = await callApi();
let results = document.getElementById(ids.apiResults);
if (Array.isArray(result)) {
let list = document.createElement('ul');
let listElements = result.map(e => createListElement(e));
for (let element of listElements) {
list.appendChild(element);
}
let heading = document.createElement('h2');
heading.innerText = 'API call results';
results.appendChild(heading);
results.appendChild(list);
} else {
results.innerText = result;
}
function createListElement(element) {
let node = document.createElement('li');
node.innerText = element;
return node;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
}
<h4>@ViewData["Title"]</h4>
@Html.Partial("_StatusMessage", Model.StatusMessage)
<partial name="_StatusMessage" for="StatusMessage" />
<div class="row">
<div class="col-md-6">
<form method="post">

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Description>Identity sample MVC application on ASP.NET Core using the default UI</Description>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>
<UserSecretsId>aspnetcore-2ff9bc27-5e8c-4484-90ca-e3aace89b72a</UserSecretsId>
</PropertyGroup>
@ -30,6 +30,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.NET.Sdk.Razor" Version="$(MicrosoftNETSdkRazorPackageVersion)" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:28248/",
"applicationUrl": "http://localhost:54840/",
"sslPort": 0
}
},

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Identity Sample</title>
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css"></link>
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
@ -37,7 +37,7 @@
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/bootstrap.min.js"></script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("scripts", required: false)
</body>

View File

@ -1,2 +1,2 @@
 <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

View File

@ -1 +0,0 @@
body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}#qrCode{margin:15px}@media screen and (max-width:767px){.carousel-caption{display:none}}

View File

@ -187,7 +187,7 @@ namespace IdentitySample.Controllers
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
ViewData["ProviderDisplayName"] = info.ProviderDisplayName;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
}

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Description>Identity sample MVC application on ASP.NET Core</Description>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>
<UserSecretsId>aspnetcore-b3d20cbe-418e-4bf2-a0f4-57f91d067e07</UserSecretsId>
</PropertyGroup>
@ -30,5 +30,6 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.NET.Sdk.Razor" Version="$(MicrosoftNETSdkRazorPackageVersion)" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -3,7 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51567/",
"applicationUrl": "http://localhost:54838/",
"sslPort": 0
}
},

View File

@ -2,7 +2,7 @@
ViewData["Title"] = "Confirm Email";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<div>
<p>
Thank you for confirming your email. Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>.

View File

@ -3,8 +3,8 @@
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"].</h2>
<h3>Associate your @ViewData["LoginProvider"] account.</h3>
<h1>@ViewData["Title"].</h1>
<h3>Associate your @ViewData["ProviderDisplayName"] account.</h3>
<form asp-controller="Account" asp-action="ExternalLoginConfirmation" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<h4>Association Form</h4>
@ -12,7 +12,7 @@
<div asp-validation-summary="All" class="text-danger"></div>
<p class="text-info">
You've successfully authenticated with <strong>@ViewData["LoginProvider"]</strong>.
You've successfully authenticated with <strong>@ViewData["ProviderDisplayName"]</strong>.
Please enter a user name for this site below and click the Register button to finish
logging in.
</p>

View File

@ -3,6 +3,6 @@
}
<header>
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p class="text-danger">Unsuccessful login with service.</p>
</header>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Forgot your password?";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p>
For more information on how to enable reset password please see this <a href="http://go.microsoft.com/fwlink/?LinkID=532713">article</a>.
</p>

View File

@ -2,7 +2,7 @@
ViewData["Title"] = "Forgot Password Confirmation";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p>
Please check your email to reset your password.
</p>

View File

@ -8,7 +8,7 @@
ViewData["Title"] = "Log in";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<div class="row">
<div class="col-md-8">
<section>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<h4>Create a new account.</h4>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Reset password";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="ResetPassword" method="post" class="form-horizontal" role="form">
<h4>Reset your password.</h4>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Send Verification Code";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="SendCode" asp-route-returnurl="@Model.ReturnUrl" method="post" class="form-horizontal" role="form">
<input asp-for="RememberMe" type="hidden" />

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Use recovery code";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="UseRecoveryCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<div asp-validation-summary="All" class="text-danger"></div>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Verify";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="VerifyAuthenticatorCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<div asp-validation-summary="All" class="text-danger"></div>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Verify";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Account" asp-action="VerifyCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<div asp-validation-summary="All" class="text-danger"></div>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Add Phone Number";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Manage" asp-action="AddPhoneNumber" method="post" class="form-horizontal" role="form">
<h4>Add a phone number.</h4>
<hr />

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Change Password";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Manage" asp-action="ChangePassword" method="post" class="form-horizontal" role="form">
<h4>Change Password Form</h4>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Your recovery codes:";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p class="text-success">@ViewData["StatusMessage"]</p>
<div>

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Manage your account";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p class="text-success">@ViewData["StatusMessage"]</p>
<div>

View File

@ -4,7 +4,7 @@
ViewData["Title"] = "Manage your external logins";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<p class="text-success">@ViewData["StatusMessage"]</p>
@if (Model.CurrentLogins.Count > 0)
@ -15,7 +15,7 @@
@for (var index = 0; index < Model.CurrentLogins.Count; index++)
{
<tr>
<td>@Model.CurrentLogins[index].LoginProvider</td>
<td>@Model.CurrentLogins[index].ProviderDisplayName</td>
<td>
@if ((bool)ViewData["ShowRemoveButton"])
{
@ -23,7 +23,7 @@
<div>
<input asp-for="@Model.CurrentLogins[index].LoginProvider" name="LoginProvider" type="hidden"/>
<input asp-for="@Model.CurrentLogins[index].ProviderKey" name="ProviderKey" type="hidden"/>
<input type="submit" class="btn btn-default" value="Remove" title="Remove this @Model.CurrentLogins[index].LoginProvider login from your account" />
<input type="submit" class="btn btn-default" value="Remove" title="Remove this @Model.CurrentLogins[index].ProviderDisplayName login from your account" />
</div>
</form>
}

View File

@ -3,7 +3,7 @@
ViewData["Title"] = "Verify Phone Number";
}
<h2>@ViewData["Title"].</h2>
<h1>@ViewData["Title"].</h1>
<form asp-controller="Manage" asp-action="VerifyPhoneNumber" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<input asp-for="PhoneNumber" type="hidden" />

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Identity Sample</title>
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css"></link>
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
@ -37,7 +37,7 @@
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/bootstrap.min.js"></script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("scripts", required: false)
</body>

View File

@ -1,2 +1,2 @@
 <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View File

@ -1,9 +0,0 @@
<Application x:Class="NativeWPFClient.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NativeWPFClient"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace NativeWPFClient
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -1,25 +0,0 @@
<Window x:Class="NativeWPFClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NativeWPFClient"
mc:Ignorable="d"
Title="MainWindow" Width="525" SizeToContent="Height">
<StackPanel Margin="0,0,0,0" VerticalAlignment="Stretch" Orientation="Vertical">
<Label Content="Base address" Margin="5,0" />
<TextBox Name="BaseAddress" Margin="5,0" TextWrapping="Wrap" Text="{Binding BaseAddress}" />
<Label Content="Redirect URI" Margin="5,0" />
<TextBox Name="RedirectUri" Margin="5,0" TextWrapping="Wrap" Text="{Binding RedirectUri}" />
<Label Content="Tenant" Margin="5,0" />
<TextBox Name="Tenant" Margin="5,0" TextWrapping="Wrap" Text="{Binding Tenant}" />
<Label Content="Policy" HorizontalAlignment="Left" Margin="5,0" />
<TextBox Name="Policy" Margin="5,0" TextWrapping="Wrap" Text="{Binding Policy}" />
<Label Content="Client ID" Margin="5,0" />
<TextBox Name="ClientID" Margin="5,0" TextWrapping="Wrap" Text="{Binding ClientId}" />
<Label Content="Scopes" Margin="5,0" />
<TextBox Name="Scopes" Margin="5,0" TextWrapping="Wrap" Text="{Binding Scopes}" />
<Button Name="Authorize" Margin="5,3" Click="Authorize_Click">Authorize</Button>
<Label Margin="5,0" Name="Result" Content="{Binding Result, Mode=TwoWay}"></Label>
</StackPanel>
</Window>

View File

@ -1,139 +0,0 @@
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace NativeWPFClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Task _currentAuthorization;
public MainWindow()
{
InitializeComponent();
// Local client
DataContext = new NativeWPFClientViewModel
{
BaseAddress = "https://localhost:44324/",
RedirectUri = "urn:ietf:wg:oauth:2.0:oob",
Tenant = "Identity",
Policy = "signinsignup",
ClientId = "06D7C2FB-A66A-41AD-9509-77BDDFAB111B",
Scopes = "https://localhost/DFC7191F-FF74-42B9-A292-08FEA80F5B20/v2.0/ProtectedApi/read"
};
// DataContext = new NativeWPFClientViewModel
// {
// BaseAddress = "https://login.microsoftonline.com/",
// RedirectUri = "urn:ietf:wg:oauth:2.0:oob",
// Tenant = "jacalvarb2c.onmicrosoft.com",
// Policy = "B2C_1_signinsignup",
// ClientId = "42291769-0dc8-4497-9cbc-d3879783d6e7",
// Scopes = "https://jacalvarb2c.onmicrosoft.com/ProtectedApi/read"
// };
ViewModel.Result = "Hit authorize to sign in";
}
NativeWPFClientViewModel ViewModel => (NativeWPFClientViewModel)DataContext;
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
}
private async void Authorize_Click(object sender, RoutedEventArgs e)
{
if (_currentAuthorization == null)
{
Authorize.IsEnabled = false;
await AuthorizeAsync();
}
}
private async Task AuthorizeAsync()
{
var authority = $"{ViewModel.BaseAddress}tfp/{ViewModel.Tenant}/{ViewModel.Policy}";
var client = new PublicClientApplication(ViewModel.ClientId, authority)
{
ValidateAuthority = false
};
try
{
var scope = new string[] { };
var appScopes = ViewModel.Scopes.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var currentAuthorization = await client.AcquireTokenAsync(
appScopes,
user: null,
behavior: UIBehavior.ForceLogin,
extraQueryParameters: string.Empty,
extraScopesToConsent: null,
authority: authority);
ViewModel.Result = currentAuthorization.User?.Name ?? "Authenticated but no name";
}
catch (MsalException ex)
{
if (ex.ErrorCode != "authentication_canceled")
{
// An unexpected error occurred.
string message = ex.Message;
if (ex.InnerException != null)
{
message += "Inner Exception : " + ex.InnerException.Message;
}
MessageBox.Show(message);
}
}
finally
{
_currentAuthorization = null;
Authorize.IsEnabled = true;
}
}
}
internal class NativeWPFClientViewModel : INotifyPropertyChanged
{
private string _result;
public string BaseAddress { get; set; }
public string RedirectUri { get; set; }
public string Tenant { get; set; }
public string Policy { get; set; }
public string ClientId { get; set; }
public string Scopes { get; set; }
public string Result
{
get => _result;
set
{
_result = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Result)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<ImportDirectoryBuildTargets>false</ImportDirectoryBuildTargets>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{39AA4E4D-5E62-4213-8641-BF8012D45DE4}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>NativeWPFClient</RootNamespace>
<AssemblyName>NativeWPFClient</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<!-- Workaround for Visual Studio complaining about inexisting project.json file -->
<RuntimeIdentifier Condition="'$(BaseNuGetRuntimeIdentifier)' != ''">$(BaseNuGetRuntimeIdentifier)</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Identity.Client">
<Version>1.1.0-preview</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,55 +0,0 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NativeWPFClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NativeWPFClient")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,71 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NativeWPFClient.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NativeWPFClient.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,30 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NativeWPFClient.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,65 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Authentication;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Extension methods to configure authentication for existing APIs coexisting with an Authorization Server.
/// </summary>
public static class AuthenticationBuilderExtensions
{
private const string IdentityServerJwtNameSuffix = "API";
private static readonly PathString DefaultIdentityUIPathPrefix =
new PathString("/Identity");
/// <summary>
/// Adds an authentication handler for an API that coexists with an Authorization Server.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
public static AuthenticationBuilder AddIdentityServerJwt(this AuthenticationBuilder builder)
{
var services = builder.Services;
services.TryAddSingleton<IIdentityServerJwtDescriptor, IdentityServerJwtDescriptor>();
services.TryAddEnumerable(ServiceDescriptor
.Transient<IConfigureOptions<JwtBearerOptions>, IdentityServerJwtBearerOptionsConfiguration>(JwtBearerOptionsFactory));
services.AddAuthentication(IdentityServerJwtConstants.IdentityServerJwtScheme)
.AddPolicyScheme(IdentityServerJwtConstants.IdentityServerJwtScheme, null, options =>
{
options.ForwardDefaultSelector = new IdentityServerJwtPolicySchemeForwardSelector(
DefaultIdentityUIPathPrefix,
IdentityServerJwtConstants.IdentityServerJwtBearerScheme).SelectScheme;
})
.AddJwtBearer(IdentityServerJwtConstants.IdentityServerJwtBearerScheme, null, o => { });
return builder;
IdentityServerJwtBearerOptionsConfiguration JwtBearerOptionsFactory(IServiceProvider sp)
{
var schemeName = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
var localApiDescriptor = sp.GetRequiredService<IIdentityServerJwtDescriptor>();
var hostingEnvironment = sp.GetRequiredService<IHostingEnvironment>();
var apiName = hostingEnvironment.ApplicationName + IdentityServerJwtNameSuffix;
return new IdentityServerJwtBearerOptionsConfiguration(schemeName, apiName, localApiDescriptor);
}
}
}
}

View File

@ -0,0 +1,77 @@
// 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 IdentityServer4.Extensions;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class IdentityServerJwtBearerOptionsConfiguration : IConfigureNamedOptions<JwtBearerOptions>
{
private readonly string _scheme;
private readonly string _apiName;
private readonly IIdentityServerJwtDescriptor _localApiDescriptor;
public IdentityServerJwtBearerOptionsConfiguration(
string scheme,
string apiName,
IIdentityServerJwtDescriptor localApiDescriptor)
{
_scheme = scheme;
_apiName = apiName;
_localApiDescriptor = localApiDescriptor;
}
public void Configure(string name, JwtBearerOptions options)
{
var definitions = _localApiDescriptor.GetResourceDefinitions();
if (!definitions.ContainsKey(_apiName))
{
return;
}
if (string.Equals(name, _scheme, StringComparison.Ordinal))
{
options.Events = options.Events ?? new JwtBearerEvents();
options.Events.OnMessageReceived = ResolveAuthorityAndKeysAsync;
options.Audience = _apiName;
var staticConfiguration = new OpenIdConnectConfiguration
{
Issuer = options.Authority
};
var manager = new StaticConfigurationManager(staticConfiguration);
options.ConfigurationManager = manager;
options.TokenValidationParameters.ValidIssuer = options.Authority;
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
}
}
internal static async Task ResolveAuthorityAndKeysAsync(MessageReceivedContext messageReceivedContext)
{
var options = messageReceivedContext.Options;
if (options.TokenValidationParameters.ValidIssuer == null || options.TokenValidationParameters.IssuerSigningKey == null)
{
var store = messageReceivedContext.HttpContext.RequestServices.GetRequiredService<ISigningCredentialStore>();
var credential = await store.GetSigningCredentialsAsync();
options.Authority = options.Authority ?? messageReceivedContext.HttpContext.GetIdentityServerIssuerUri();
options.TokenValidationParameters.IssuerSigningKey = credential.Key;
options.TokenValidationParameters.ValidIssuer = options.Authority;
}
}
public void Configure(JwtBearerOptions options)
{
}
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Constants for a default API authentication handler.
/// </summary>
public class IdentityServerJwtConstants
{
/// <summary>
/// Scheme used for the default API policy authentication scheme.
/// </summary>
public const string IdentityServerJwtScheme = "IdentityServerJwt";
/// <summary>
/// Scheme used for the underlying default API JwtBearer authentication scheme.
/// </summary>
public const string IdentityServerJwtBearerScheme = "IdentityServerJwtBearer";
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Authentication
{
internal class IdentityServerJwtPolicySchemeForwardSelector
{
private readonly PathString _identityPath;
private readonly string _IdentityServerJwtScheme;
public IdentityServerJwtPolicySchemeForwardSelector(
string identityPath,
string IdentityServerJwtScheme)
{
_identityPath = identityPath;
_IdentityServerJwtScheme = IdentityServerJwtScheme;
}
public string SelectScheme(HttpContext ctx)
{
if (ctx.Request.Path.StartsWithSegments(_identityPath, StringComparison.OrdinalIgnoreCase))
{
return IdentityConstants.ApplicationScheme;
}
return _IdentityServerJwtScheme;
}
}
}

View File

@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class StaticConfigurationManager : IConfigurationManager<OpenIdConnectConfiguration>
{
private readonly Task<OpenIdConnectConfiguration> _configuration;
public StaticConfigurationManager(OpenIdConnectConfiguration configuration) => _configuration = Task.FromResult(configuration);
public Task<OpenIdConnectConfiguration> GetConfigurationAsync(CancellationToken cancel) => _configuration;
public void RequestRefresh()
{
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Constants for the different application profiles for applications in an authorization server.
/// </summary>
public static class ApplicationProfiles
{
/// <summary>
/// The application is an external API registered with the authorization server.
/// </summary>
public const string API = "API";
/// <summary>
/// The application is an API that coexists with the authorization server.
/// </summary>
public const string IdentityServerJwt = "IdentityServerJwt";
/// <summary>
/// The application is an external single page application registered with the authorization server.
/// </summary>
public const string SPA = "SPA";
/// <summary>
/// The application is a single page application that coexists with the authorization server.
/// </summary>
public const string IdentityServerSPA = "IdentityServerSPA";
/// <summary>
/// The application is a native application like a mobile or desktop application.
/// </summary>
public const string NativeApp = "NativeApp";
/// <summary>
/// The application is a web application.
/// </summary>
internal const string WebApplication = "WebApplication";
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using IdentityServer4.Models;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Constants used for storing information about application profiles in the <see cref="Client.Properties"/> or <see cref="Resource.Properties"/>
/// of a <see cref="Client"/> or <see cref="ApiResource"/> respectively.
/// </summary>
public static class ApplicationProfilesPropertyNames
{
/// <summary>
/// Key to the Profile on <see cref="Client.Properties"/> or <see cref="Resource.Properties"/>.
/// The Profile value will be one of the constants in <see cref="ApplicationProfiles"/>.
/// </summary>
public const string Profile = nameof(Profile);
/// <summary>
/// Key to the Source on <see cref="Client.Properties"/> or <see cref="Resource.Properties"/>.
/// The Source value will be Configuration if present.
/// </summary>
public const string Source = nameof(Source);
/// <summary>
/// Key to the Clients on <see cref="Resource.Properties"/>.
/// The Clients value will be <c>*</c> to indicate that all clients are allowed to access this resource or a space separated list of
/// the client ids that are allowed to access this resource.
/// </summary>
public const string Clients = nameof(Clients);
}
}

View File

@ -0,0 +1,31 @@
// 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 IdentityServer4.Models;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Constants for special values defined for specific <see cref="ApplicationProfilesPropertyNames" /> keys.
/// </summary>
public static class ApplicationProfilesPropertyValues
{
/// <summary>
/// The value given to <see cref="ApplicationProfilesPropertyNames.Clients"/> in <see cref="Resource.Properties"/> to indicate that the
/// resource can be accessed by all configured clients.
/// </summary>
public const string AllowAllApplications = "*";
/// <summary>
/// The value given to <see cref="ApplicationProfilesPropertyNames.Source"/> in <see cref="Resource.Properties"/> or <see cref="Client.Properties"/>
/// to indicate that the application was defined in configuration.
/// </summary>
public const string Configuration = nameof(Configuration);
/// <summary>
/// The value given to <see cref="ApplicationProfilesPropertyNames.Source"/> in <see cref="Resource.Properties"/>
/// to indicate that the resource was defined as a default identity resource.
/// </summary>
public const string Default = nameof(Default);
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using IdentityServer4.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class AspNetConventionsConfigureOptions : IConfigureOptions<IdentityServerOptions>
{
public void Configure(IdentityServerOptions options)
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.Authentication.CookieAuthenticationScheme = IdentityConstants.ApplicationScheme;
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ClientDefinition : ServiceDefinition
{
public string RedirectUri { get; set; }
public string LogoutUri { get; set; }
public string ClientSecret { get; set; }
}
}

View File

@ -0,0 +1,110 @@
// 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 IdentityServer4.Models;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
internal class ConfigureApiResources : IConfigureOptions<ApiAuthorizationOptions>
{
private static readonly char[] ScopesSeparator = new char[] { ' ' };
private readonly IConfiguration _configuration;
private readonly ILogger<ConfigureApiResources> _logger;
private readonly IIdentityServerJwtDescriptor _localApiDescriptor;
public ConfigureApiResources(
IConfiguration configuration,
IIdentityServerJwtDescriptor localApiDescriptor,
ILogger<ConfigureApiResources> logger)
{
_configuration = configuration;
_localApiDescriptor = localApiDescriptor;
_logger = logger;
}
public void Configure(ApiAuthorizationOptions options)
{
var resources = GetApiResources();
foreach (var resource in resources)
{
options.ApiResources.Add(resource);
}
}
internal IEnumerable<ApiResource> GetApiResources()
{
var data = _configuration
.Get<Dictionary<string, ResourceDefinition>>();
if (data != null)
{
foreach (var kvp in data)
{
_logger.LogInformation($"Configuring API resource '{kvp.Key}'.");
yield return GetResource(kvp.Key, kvp.Value);
}
}
var localResources = _localApiDescriptor.GetResourceDefinitions();
if (localResources != null)
{
foreach (var kvp in localResources)
{
_logger.LogInformation($"Configuring local API resource '{kvp.Key}'.");
yield return GetResource(kvp.Key, kvp.Value);
}
}
}
public ApiResource GetResource(string name, ResourceDefinition definition)
{
switch (definition.Profile)
{
case ApplicationProfiles.API:
return GetAPI(name, definition);
case ApplicationProfiles.IdentityServerJwt:
return GetLocalAPI(name, definition);
default:
throw new InvalidOperationException($"Type '{definition.Profile}' is not supported.");
}
}
private string[] ParseScopes(string scopes)
{
if (scopes == null)
{
return null;
}
var parsed = scopes.Split(ScopesSeparator, StringSplitOptions.RemoveEmptyEntries);
if (parsed.Length == 0)
{
return null;
}
return parsed;
}
private ApiResource GetAPI(string name, ResourceDefinition definition) =>
ApiResourceBuilder.ApiResource(name)
.FromConfiguration()
.WithAllowedClients(ApplicationProfilesPropertyValues.AllowAllApplications)
.ReplaceScopes(ParseScopes(definition.Scopes) ?? new[] { name })
.Build();
private ApiResource GetLocalAPI(string name, ResourceDefinition definition) =>
ApiResourceBuilder.IdentityServerJwt(name)
.FromConfiguration()
.WithAllowedClients(ApplicationProfilesPropertyValues.AllowAllApplications)
.ReplaceScopes(ParseScopes(definition.Scopes) ?? new[] { name })
.Build();
}
}

View File

@ -0,0 +1,110 @@
// 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 IdentityServer4.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
{
internal class ConfigureClientScopes : IPostConfigureOptions<ApiAuthorizationOptions>
{
private static readonly char[] DefaultClientListSeparator = new char[] { ' ' };
private readonly ILogger<ConfigureClientScopes> _logger;
public ConfigureClientScopes(ILogger<ConfigureClientScopes> logger)
{
_logger = logger;
}
public void PostConfigure(string name, ApiAuthorizationOptions options)
{
AddApiResourceScopesToClients(options);
AddIdentityResourceScopesToClients(options);
}
private void AddIdentityResourceScopesToClients(ApiAuthorizationOptions options)
{
foreach (var identityResource in options.IdentityResources)
{
if (!identityResource.Properties.TryGetValue(ApplicationProfilesPropertyNames.Clients, out var clientList))
{
_logger.LogInformation($"Identity resource '{identityResource.Name}' doesn't define a list of allowed applications.");
continue;
}
var resourceClients = clientList.Split(DefaultClientListSeparator, StringSplitOptions.RemoveEmptyEntries);
if (resourceClients.Length == 0)
{
_logger.LogInformation($"Identity resource '{identityResource.Name}' doesn't define a list of allowed applications.");
continue;
}
if (resourceClients.Length == 1 && resourceClients[0] == ApplicationProfilesPropertyValues.AllowAllApplications)
{
_logger.LogInformation($"Identity resource '{identityResource.Name}' allows all applications.");
}
else
{
_logger.LogInformation($"Identity resource '{identityResource.Name}' allows applications '{string.Join(" ", resourceClients)}'.");
}
foreach (var client in options.Clients)
{
if ((resourceClients.Length == 1 && resourceClients[0] == ApplicationProfilesPropertyValues.AllowAllApplications) ||
resourceClients.Contains(client.ClientId))
{
client.AllowedScopes.Add(identityResource.Name);
}
}
}
}
private void AddApiResourceScopesToClients(ApiAuthorizationOptions options)
{
foreach (var resource in options.ApiResources)
{
if (!resource.Properties.TryGetValue(ApplicationProfilesPropertyNames.Clients, out var clientList))
{
_logger.LogInformation($"Resource '{resource.Name}' doesn't define a list of allowed applications.");
continue;
}
var resourceClients = clientList.Split(DefaultClientListSeparator, StringSplitOptions.RemoveEmptyEntries);
if (resourceClients.Length == 0)
{
_logger.LogInformation($"Resource '{resource.Name}' doesn't define a list of allowed applications.");
continue;
}
if (resourceClients.Length == 1 && resourceClients[0] == ApplicationProfilesPropertyValues.AllowAllApplications)
{
_logger.LogInformation($"Resource '{resource.Name}' allows all applications.");
}
else
{
_logger.LogInformation($"Resource '{resource.Name}' allows applications '{string.Join(" ", resourceClients)}'.");
}
foreach (var client in options.Clients)
{
if ((resourceClients.Length == 1 && resourceClients[0] == ApplicationProfilesPropertyValues.AllowAllApplications) ||
resourceClients.Contains(client.ClientId))
{
AddScopes(resource, client);
}
}
}
}
private static void AddScopes(ApiResource resource, Client client)
{
foreach (var scope in resource.Scopes)
{
client.AllowedScopes.Add(scope.Name);
}
}
}
}

View File

@ -0,0 +1,165 @@
// 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 IdentityServer4.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ConfigureClients : IConfigureOptions<ApiAuthorizationOptions>
{
private const string DefaultLocalSPARelativeRedirectUri = "";
private const string DefaultLocalSPARelativePostLogoutRedirectUri = "";
private readonly IConfiguration _configuration;
private readonly ILogger<ConfigureClients> _logger;
public ConfigureClients(
IConfiguration configuration,
ILogger<ConfigureClients> logger)
{
_configuration = configuration;
_logger = logger;
}
public void Configure(ApiAuthorizationOptions options)
{
foreach (var client in GetClients())
{
options.Clients.Add(client);
}
}
internal IEnumerable<Client> GetClients()
{
var data = _configuration.Get<Dictionary<string, ClientDefinition>>();
if (data != null)
{
foreach (var kvp in data)
{
_logger.LogInformation($"Configuring client '{kvp.Key}'.");
var name = kvp.Key;
var definition = kvp.Value;
switch (definition.Profile)
{
case ApplicationProfiles.SPA:
yield return GetSPA(name, definition);
break;
//case ApplicationProfiles.WebApplication:
// yield return GetWebApplication(name, definition);
// break;
case ApplicationProfiles.IdentityServerSPA:
yield return GetLocalSPA(name, definition);
break;
case ApplicationProfiles.NativeApp:
yield return GetNativeApp(name, definition);
break;
default:
throw new InvalidOperationException($"Type '{definition.Profile}' is not supported.");
}
}
}
}
private Client GetWebApplication(string name, ClientDefinition definition)
{
if (definition.RedirectUri == null ||
!Uri.TryCreate(definition.RedirectUri, UriKind.Absolute, out var redirectUri))
{
throw new InvalidOperationException($"The redirect uri " +
$"'{definition.RedirectUri}' for '{name}' is invalid. " +
$"The redirect URI must be an absolute url.");
}
if (definition.LogoutUri == null ||
!Uri.TryCreate(definition.LogoutUri, UriKind.Absolute, out var postLogouturi))
{
throw new InvalidOperationException($"The logout uri " +
$"'{definition.LogoutUri}' for '{name}' is invalid. " +
$"The logout URI must be an absolute url.");
}
if (!string.Equals(
redirectUri.GetLeftPart(UriPartial.Authority),
postLogouturi.GetLeftPart(UriPartial.Authority),
StringComparison.Ordinal))
{
throw new InvalidOperationException($"The redirect uri and the logout uri " +
$"for '{name}' have a different scheme, host or port.");
}
if (definition.ClientSecret == null)
{
throw new InvalidOperationException($"The configuration for '{name}' does not contain a client secret. " +
$"Client secrets are required for web applications.");
}
return ClientBuilder.WebApplication(name)
.WithRedirectUri(definition.RedirectUri)
.WithLogoutRedirectUri(definition.LogoutUri)
.FromConfiguration()
.WithClientSecret(definition.ClientSecret)
.Build();
}
private Client GetSPA(string name, ClientDefinition definition)
{
if (definition.RedirectUri == null ||
!Uri.TryCreate(definition.RedirectUri, UriKind.Absolute, out var redirectUri))
{
throw new InvalidOperationException($"The redirect uri " +
$"'{definition.RedirectUri}' for '{name}' is invalid. " +
$"The redirect URI must be an absolute url.");
}
if (definition.LogoutUri == null ||
!Uri.TryCreate(definition.LogoutUri, UriKind.Absolute, out var postLogouturi))
{
throw new InvalidOperationException($"The logout uri " +
$"'{definition.LogoutUri}' for '{name}' is invalid. " +
$"The logout URI must be an absolute url.");
}
if (!string.Equals(
redirectUri.GetLeftPart(UriPartial.Authority),
postLogouturi.GetLeftPart(UriPartial.Authority),
StringComparison.Ordinal))
{
throw new InvalidOperationException($"The redirect uri and the logout uri " +
$"for '{name}' have a different scheme, host or port.");
}
var client = ClientBuilder.SPA(name)
.WithRedirectUri(definition.RedirectUri)
.WithLogoutRedirectUri(definition.LogoutUri)
.WithAllowedOrigins(redirectUri.GetLeftPart(UriPartial.Authority))
.FromConfiguration();
return client.Build();
}
private Client GetNativeApp(string name, ClientDefinition definition)
{
var client = ClientBuilder.NativeApp(name)
.FromConfiguration();
return client.Build();
}
private Client GetLocalSPA(string name, ClientDefinition definition)
{
var client = ClientBuilder
.IdentityServerSPA(name)
.WithRedirectUri(definition.RedirectUri ?? DefaultLocalSPARelativeRedirectUri)
.WithLogoutRedirectUri(definition.LogoutUri ?? DefaultLocalSPARelativePostLogoutRedirectUri)
.WithAllowedOrigins()
.FromConfiguration();
return client.Build();
}
}
}

View File

@ -0,0 +1,108 @@
// 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.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ConfigureIdentityResources : IConfigureOptions<ApiAuthorizationOptions>
{
private readonly IConfiguration _configuration;
private readonly ILogger<ConfigureIdentityResources> _logger;
private static readonly char[] ScopesSeparator = new char[] { ' ' };
public ConfigureIdentityResources(IConfiguration configuration, ILogger<ConfigureIdentityResources> logger)
{
_configuration = configuration;
_logger = logger;
}
public void Configure(ApiAuthorizationOptions options)
{
var data = _configuration.Get<IdentityResourceDefinition>();
if (data != null && data.Scopes != null)
{
var scopes = ParseScopes(data.Scopes);
if (scopes != null && scopes.Length > 0)
{
ClearDefaultIdentityResources(options);
}
foreach (var scope in scopes)
{
switch (scope)
{
case IdentityServer4.IdentityServerConstants.StandardScopes.OpenId:
options.IdentityResources.Add(IdentityResourceBuilder.OpenId()
.AllowAllClients()
.FromConfiguration()
.Build());
break;
case IdentityServer4.IdentityServerConstants.StandardScopes.Profile:
options.IdentityResources.Add(IdentityResourceBuilder.Profile()
.AllowAllClients()
.FromConfiguration()
.Build());
break;
case IdentityServer4.IdentityServerConstants.StandardScopes.Address:
options.IdentityResources.Add(IdentityResourceBuilder.Address()
.AllowAllClients()
.FromConfiguration()
.Build());
break;
case IdentityServer4.IdentityServerConstants.StandardScopes.Email:
options.IdentityResources.Add(IdentityResourceBuilder.Email()
.AllowAllClients()
.FromConfiguration()
.Build());
break;
case IdentityServer4.IdentityServerConstants.StandardScopes.Phone:
options.IdentityResources.Add(IdentityResourceBuilder.Phone()
.AllowAllClients()
.FromConfiguration()
.Build());
break;
default:
throw new InvalidOperationException($"Invalid identity resource name '{scope}'");
}
}
}
}
private static void ClearDefaultIdentityResources(ApiAuthorizationOptions options)
{
var allDefault = true;
foreach (var resource in options.IdentityResources)
{
if (!resource.Properties.TryGetValue(ApplicationProfilesPropertyNames.Source, out var source) ||
!string.Equals(ApplicationProfilesPropertyValues.Default, source, StringComparison.OrdinalIgnoreCase))
{
allDefault = false;
break;
}
}
if (allDefault)
{
options.IdentityResources.Clear();
}
}
private string[] ParseScopes(string scopes)
{
if (scopes == null)
{
return null;
}
var parsed = scopes.Split(ScopesSeparator, StringSplitOptions.RemoveEmptyEntries);
if (parsed.Length == 0)
{
return null;
}
return parsed;
}
}
}

View File

@ -0,0 +1,117 @@
// 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.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ConfigureSigningCredentials : IConfigureOptions<ApiAuthorizationOptions>
{
// We need to cast the underlying int value of the EphemeralKeySet to X509KeyStorageFlags
// due to the fact that is not part of .NET Standard. This value is only used with non-windows
// platforms (all .NET Core) for which the value is defined on the underlying platform.
private const X509KeyStorageFlags UnsafeEphemeralKeySet = (X509KeyStorageFlags)32;
private const string DefaultTempKeyRelativePath = "obj/tempkey.json";
private readonly IConfiguration _configuration;
private readonly ILogger<ConfigureSigningCredentials> _logger;
public ConfigureSigningCredentials(
IConfiguration configuration,
ILogger<ConfigureSigningCredentials> logger)
{
_configuration = configuration;
_logger = logger;
}
public void Configure(ApiAuthorizationOptions options)
{
var key = LoadKey();
options.SigningCredential = key;
}
public SigningCredentials LoadKey()
{
var key = new KeyDefinition();
_configuration.Bind(key);
switch (key.Type)
{
case KeySources.Development:
var developmentKeyPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath ?? DefaultTempKeyRelativePath);
var createIfMissing = key.Persisted ?? true;
_logger.LogInformation($"Loading development key at '{developmentKeyPath}'.");
var developmentKey = new RsaSecurityKey(SigningKeysLoader.LoadDevelopment(developmentKeyPath, createIfMissing))
{
KeyId = "Development"
};
return new SigningCredentials(developmentKey, "RS256");
case KeySources.File:
var pfxPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath);
var pfxPassword = key.Password;
var storageFlags = GetStorageFlags(key);
_logger.LogInformation($"Loading certificate file at '{pfxPath}' with storage flags '{key.StorageFlags}'.");
return new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromFile(pfxPath, key.Password, storageFlags)), "RS256");
case KeySources.Store:
if (!Enum.TryParse<StoreLocation>(key.StoreLocation, out var storeLocation))
{
throw new InvalidOperationException($"Invalid certificate store location '{key.StoreLocation}'.");
}
_logger.LogInformation($"Loading certificate with subject '{key.Name}' in '{key.StoreLocation}\\{key.StoreName}'.");
return new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromStoreCert(key.Name, key.StoreName, storeLocation, GetCurrentTime())), "RS256");
case null:
throw new InvalidOperationException($"Key type not specified.");
default:
throw new InvalidOperationException($"Invalid key type '{key.Type ?? "(null)"}'.");
}
}
// for testing purposes only
internal virtual DateTimeOffset GetCurrentTime() => DateTimeOffset.UtcNow;
private X509KeyStorageFlags GetStorageFlags(KeyDefinition key)
{
var defaultFlags = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ?
UnsafeEphemeralKeySet : (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? X509KeyStorageFlags.PersistKeySet :
X509KeyStorageFlags.DefaultKeySet);
if (key.StorageFlags == null)
{
return defaultFlags;
}
var flagsList = key.StorageFlags.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (flagsList.Length == 0)
{
return defaultFlags;
}
var result = ParseCurrentFlag(flagsList[0]);
foreach (var flag in flagsList.Skip(1))
{
result |= ParseCurrentFlag(flag);
}
return result;
X509KeyStorageFlags ParseCurrentFlag(string candidate)
{
if (Enum.TryParse<X509KeyStorageFlags>(candidate, out var flag))
{
return flag;
}
else
{
throw new InvalidOperationException($"Invalid storage flag '{candidate}'");
}
}
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
{
internal interface IIdentityServerJwtDescriptor
{
IDictionary<string, ResourceDefinition> GetResourceDefinitions();
}
}

View File

@ -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.ApiAuthorization.IdentityServer
{
internal class IdentityResourceDefinition : ResourceDefinition
{
public IdentityResourceDefinition()
{
Profile = "API";
}
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Hosting;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
{
internal class IdentityServerJwtDescriptor : IIdentityServerJwtDescriptor
{
public IdentityServerJwtDescriptor(IHostingEnvironment environment)
{
Environment = environment;
}
public IHostingEnvironment Environment { get; }
public IDictionary<string, ResourceDefinition> GetResourceDefinitions()
{
return new Dictionary<string, ResourceDefinition>
{
[Environment.ApplicationName + "API"] = new ResourceDefinition() { Profile = ApplicationProfiles.IdentityServerJwt }
};
}
}
}

View File

@ -0,0 +1,17 @@
// 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.ApiAuthorization.IdentityServer.Configuration
{
internal class KeyDefinition
{
public string Type { get; set; }
public bool? Persisted { get; set; }
public string FilePath { get; set; }
public string Password { get; set; }
public string Name { get; set; }
public string StoreLocation { get; set; }
public string StoreName { get; set; }
public string StorageFlags { get; set; }
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
{
internal class KeySources
{
public const string File = nameof(File);
public const string Development = nameof(Development);
public const string Store = nameof(Store);
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ResourceDefinition : ServiceDefinition
{
public string Scopes { get; set; }
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class ServiceDefinition
{
public string Profile { get; set; }
}
}

View File

@ -0,0 +1,243 @@
// 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 Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal static class SigningKeysLoader
{
public static X509Certificate2 LoadFromFile(string path, string password, X509KeyStorageFlags keyStorageFlags)
{
try
{
if (!File.Exists(path))
{
throw new InvalidOperationException($"There was an error loading the certificate. The file '{path}' was not found.");
}
else if (password == null)
{
throw new InvalidOperationException("There was an error loading the certificate. No password was provided.");
}
return new X509Certificate2(path, password, keyStorageFlags);
}
catch (CryptographicException e)
{
var message = "There was an error loading the certificate. Either the password is incorrect or the process does not have permisions to " +
$"store the key in the Keyset '{keyStorageFlags}'";
throw new InvalidOperationException(message, e);
}
}
public static X509Certificate2 LoadFromStoreCert(
string subject,
string storeName,
StoreLocation storeLocation,
DateTimeOffset currentTime)
{
using (var store = new X509Store(storeName, storeLocation))
{
X509Certificate2Collection storeCertificates = null;
X509Certificate2 foundCertificate = null;
try
{
store.Open(OpenFlags.ReadOnly);
storeCertificates = store.Certificates;
var foundCertificates = storeCertificates
.Find(X509FindType.FindBySubjectDistinguishedName, subject, validOnly: false);
foundCertificate = foundCertificates
.OfType<X509Certificate2>()
.Where(certificate => certificate.NotBefore <= currentTime && certificate.NotAfter > currentTime)
.OrderBy(certificate => certificate.NotAfter)
.FirstOrDefault();
if (foundCertificate == null)
{
throw new InvalidOperationException("Couldn't find a valid certificate with " +
$"subject '{subject}' on the '{storeLocation}\\{storeName}'");
}
return foundCertificate;
}
finally
{
DisposeCertificates(storeCertificates, except: foundCertificate);
}
}
}
public static RSA LoadDevelopment(string path, bool createIfMissing)
{
var fileExists = File.Exists(path);
if (!fileExists && !createIfMissing)
{
throw new InvalidOperationException($"Couldn't find the file '{path}' and creation of a development key was not requested.");
}
if (fileExists)
{
var rsa = JsonConvert.DeserializeObject<RSAKeyParameters>(File.ReadAllText(path));
return rsa.GetRSA();
}
else
{
var parameters = RSAKeyParameters.Create();
var directory = Path.GetDirectoryName(path);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
File.WriteAllText(path, JsonConvert.SerializeObject(parameters));
return parameters.GetRSA();
}
}
private class RSAKeyParameters
{
public string D { get; set; }
public string DP { get; set; }
public string DQ { get; set; }
public string E { get; set; }
public string IQ { get; set; }
public string M { get; set; }
public string P { get; set; }
public string Q { get; set; }
public static RSAKeyParameters Create()
{
using (var rsa = RSA.Create())
{
if (rsa is RSACryptoServiceProvider rSACryptoServiceProvider && rsa.KeySize < 2048)
{
rsa.KeySize = 2048;
if (rsa.KeySize < 2048)
{
throw new InvalidOperationException("We can't generate an RSA key with at least 2048 bits. Key generation is not supported in this system.");
}
}
return GetParameters(rsa);
}
}
public static RSAKeyParameters GetParameters(RSA key)
{
var result = new RSAKeyParameters();
var rawParameters = key.ExportParameters(includePrivateParameters: true);
if (rawParameters.D != null)
{
result.D = Convert.ToBase64String(rawParameters.D);
}
if (rawParameters.DP != null)
{
result.DP = Convert.ToBase64String(rawParameters.DP);
}
if (rawParameters.DQ != null)
{
result.DQ = Convert.ToBase64String(rawParameters.DQ);
}
if (rawParameters.Exponent != null)
{
result.E = Convert.ToBase64String(rawParameters.Exponent);
}
if (rawParameters.InverseQ != null)
{
result.IQ = Convert.ToBase64String(rawParameters.InverseQ);
}
if (rawParameters.Modulus != null)
{
result.M = Convert.ToBase64String(rawParameters.Modulus);
}
if (rawParameters.P != null)
{
result.P = Convert.ToBase64String(rawParameters.P);
}
if (rawParameters.Q != null)
{
result.Q = Convert.ToBase64String(rawParameters.Q);
}
return result;
}
public RSA GetRSA()
{
var parameters = new RSAParameters();
if (D != null)
{
parameters.D = Convert.FromBase64String(D);
}
if (DP != null)
{
parameters.DP = Convert.FromBase64String(DP);
}
if (DQ != null)
{
parameters.DQ = Convert.FromBase64String(DQ);
}
if (E != null)
{
parameters.Exponent = Convert.FromBase64String(E);
}
if (IQ != null)
{
parameters.InverseQ = Convert.FromBase64String(IQ);
}
if (M != null)
{
parameters.Modulus = Convert.FromBase64String(M);
}
if (P != null)
{
parameters.P = Convert.FromBase64String(P);
}
if (Q != null)
{
parameters.Q = Convert.FromBase64String(Q);
}
var rsa = RSA.Create();
rsa.ImportParameters(parameters);
return rsa;
}
}
private static void DisposeCertificates(X509Certificate2Collection certificates, X509Certificate2 except)
{
if (certificates != null)
{
foreach (var certificate in certificates)
{
if (!certificate.Equals(except))
{
certificate.Dispose();
}
}
}
}
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using IdentityServer4.EntityFramework.Entities;
using IdentityServer4.EntityFramework.Extensions;
using IdentityServer4.EntityFramework.Interfaces;
using IdentityServer4.EntityFramework.Options;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Database abstraction for a combined <see cref="DbContext"/> using ASP.NET Identity and Identity Server.
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class ApiAuthorizationDbContext<TUser> : IdentityDbContext<TUser>, IPersistedGrantDbContext where TUser : IdentityUser
{
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
/// <summary>
/// Initializes a new instance of <see cref="ApiAuthorizationDbContext{TUser}"/>.
/// </summary>
/// <param name="options">The <see cref="DbContextOptions"/>.</param>
/// <param name="operationalStoreOptions">The <see cref="IOptions{OperationalStoreOptions}"/>.</param>
public ApiAuthorizationDbContext(
DbContextOptions options,
IOptions<OperationalStoreOptions> operationalStoreOptions)
: base(options)
{
_operationalStoreOptions = operationalStoreOptions;
}
/// <summary>
/// Gets or sets the <see cref="DbSet{PersistedGrant}"/>.
/// </summary>
public DbSet<PersistedGrant> PersistedGrants { get; set; }
/// <summary>
/// Gets or sets the <see cref="DbSet{DeviceFlowCodes}"/>.
/// </summary>
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
Task<int> IPersistedGrantDbContext.SaveChangesAsync() => base.SaveChangesAsync();
/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
}
}
}

View File

@ -0,0 +1,63 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
using System;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class AbsoluteUrlFactory : IAbsoluteUrlFactory
{
public AbsoluteUrlFactory(IHttpContextAccessor httpContextAccessor)
{
// We need the context accessor here in order to produce an absolute url from a potentially relative url.
ContextAccessor = httpContextAccessor;
}
public IHttpContextAccessor ContextAccessor { get; }
// Call this method when you are overriding a service that doesn't have an HttpContext instance available.
public string GetAbsoluteUrl(string path)
{
var (process, result) = ShouldProcessPath(path);
if (!process)
{
return result;
}
if (ContextAccessor.HttpContext?.Request == null)
{
throw new InvalidOperationException("The request is not currently available. This service can only be used within the context of an existing HTTP request.");
}
return GetAbsoluteUrl(ContextAccessor.HttpContext, path);
}
// Call this method when you are implementing a service that has an HttpContext instance available.
public string GetAbsoluteUrl(HttpContext context, string path)
{
var (process, result) = ShouldProcessPath(path);
if (!process)
{
return result;
}
var request = context.Request;
return $"{request.Scheme}://{request.Host.ToUriComponent()}{request.PathBase.ToUriComponent()}{path}";
}
private (bool, string) ShouldProcessPath(string path)
{
if (path == null || !Uri.IsWellFormedUriString(path, UriKind.RelativeOrAbsolute))
{
return (false, null);
}
if (Uri.IsWellFormedUriString(path, UriKind.Absolute))
{
return (false, path);
}
return (true, path);
}
}
}

View File

@ -0,0 +1,124 @@
// 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.Specialized;
using System.Net;
using System.Threading.Tasks;
using IdentityServer4.Configuration;
using IdentityServer4.Endpoints.Results;
using IdentityServer4.Hosting;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class AutoRedirectEndSessionEndpoint : IEndpointHandler
{
private readonly ILogger _logger;
private readonly IUserSession _session;
private readonly IOptions<IdentityServerOptions> _identityServerOptions;
private readonly IEndSessionRequestValidator _requestvalidator;
public AutoRedirectEndSessionEndpoint(
ILogger<AutoRedirectEndSessionEndpoint> logger,
IEndSessionRequestValidator requestValidator,
IOptions<IdentityServerOptions> identityServerOptions,
IUserSession session)
{
_logger = logger;
_session = session;
_identityServerOptions = identityServerOptions;
_requestvalidator = requestValidator;
}
public async Task<IEndpointResult> ProcessAsync(HttpContext ctx)
{
var validtionResult = ValidateRequest(ctx.Request);
if (validtionResult != null)
{
return validtionResult;
}
var parameters = await GetParametersAsync(ctx.Request);
var user = await _session.GetUserAsync();
var result = await _requestvalidator.ValidateAsync(parameters, user);
if (result.IsError)
{
_logger.LogError($"Error ending session {result.Error}");
return new RedirectResult(_identityServerOptions.Value.UserInteraction.ErrorUrl);
}
var client = result.ValidatedRequest?.Client;
if (client != null &&
client.Properties.TryGetValue(ApplicationProfilesPropertyNames.Profile, out var type))
{
var signInScheme = _identityServerOptions.Value.Authentication.CookieAuthenticationScheme;
if (signInScheme != null)
{
await ctx.SignOutAsync(signInScheme);
}
else
{
await ctx.SignOutAsync();
}
return new RedirectResult(result.ValidatedRequest.PostLogOutUri);
}
else
{
return new RedirectResult(_identityServerOptions.Value.UserInteraction.LogoutUrl);
}
}
private async Task<NameValueCollection> GetParametersAsync(HttpRequest request)
{
if (HttpMethods.IsGet(request.Method))
{
return request.Query.AsNameValueCollection();
}
else
{
var form = await request.ReadFormAsync();
return form.AsNameValueCollection();
}
}
private IEndpointResult ValidateRequest(HttpRequest request)
{
if (!HttpMethods.IsPost(request.Method) && !HttpMethods.IsGet(request.Method))
{
return new StatusCodeResult(HttpStatusCode.BadRequest);
}
if (HttpMethods.IsPost(request.Method) &&
!string.Equals(request.ContentType, "application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase))
{
return new StatusCodeResult(HttpStatusCode.BadRequest);
}
return null;
}
internal class RedirectResult : IEndpointResult
{
public RedirectResult(string url)
{
Url = url;
}
public string Url { get; }
public Task ExecuteAsync(HttpContext context)
{
context.Response.Redirect(Url);
return Task.CompletedTask;
}
}
}
}

View File

@ -0,0 +1,65 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using IdentityServer4.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class DefaultClientRequestParametersProvider : IClientRequestParametersProvider
{
public DefaultClientRequestParametersProvider(
IAbsoluteUrlFactory urlFactory,
IOptions<ApiAuthorizationOptions> options)
{
UrlFactory = urlFactory;
Options = options;
}
public IAbsoluteUrlFactory UrlFactory { get; }
public IOptions<ApiAuthorizationOptions> Options { get; }
public IDictionary<string, string> GetClientParameters(HttpContext context, string clientId)
{
var client = Options.Value.Clients[clientId];
var authority = context.GetIdentityServerIssuerUri();
var responseType = "";
if (!client.Properties.TryGetValue(ApplicationProfilesPropertyNames.Profile, out var type))
{
throw new InvalidOperationException($"Can't determine the type for the client '{clientId}'");
}
switch (type)
{
case ApplicationProfiles.IdentityServerSPA:
case ApplicationProfiles.SPA:
responseType = "id_token token";
break;
case ApplicationProfiles.NativeApp:
responseType = "code";
break;
//case ApplicationProfiles.WebApplication:
// responseType = "id_token code";
// break;
default:
throw new InvalidOperationException($"Invalid application type '{type}' for '{clientId}'.");
}
return new Dictionary<string, string>
{
["authority"] = authority,
["client_id"] = client.ClientId,
["redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.RedirectUris.First()),
["post_logout_redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.RedirectUris.First()),
["response_type"] = responseType,
["scope"] = string.Join(" ", client.AllowedScopes)
};
}
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal interface IAbsoluteUrlFactory
{
string GetAbsoluteUrl(string path);
string GetAbsoluteUrl(HttpContext context, string path);
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// Generates oauth/openID parameter values for configured clients.
/// </summary>
public interface IClientRequestParametersProvider
{
/// <summary>
/// Gets parameter values for the client with client id<paramref name="clientId"/>.
/// </summary>
/// <param name="context">The current <see cref="HttpContext"/>.</param>
/// <param name="clientId">The client id for the client.</param>
/// <returns>A <see cref="IDictionary{TKey, TValue}"/> containing the client parameters and their values.</returns>
IDictionary<string, string> GetClientParameters(HttpContext context, string clientId);
}
}

View File

@ -0,0 +1,71 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Validation;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
internal class RelativeRedirectUriValidator : StrictRedirectUriValidator
{
public RelativeRedirectUriValidator(IAbsoluteUrlFactory absoluteUrlFactory)
{
if (absoluteUrlFactory == null)
{
throw new ArgumentNullException(nameof(absoluteUrlFactory));
}
AbsoluteUrlFactory = absoluteUrlFactory;
}
public IAbsoluteUrlFactory AbsoluteUrlFactory { get; }
public override Task<bool> IsRedirectUriValidAsync(string requestedUri, Client client)
{
if (IsLocalSPA(client))
{
return ValidateRelativeUris(requestedUri, client.RedirectUris);
}
else
{
return base.IsRedirectUriValidAsync(requestedUri, client);
}
}
public override Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client)
{
if (IsLocalSPA(client))
{
return ValidateRelativeUris(requestedUri, client.PostLogoutRedirectUris);
}
else
{
return base.IsPostLogoutRedirectUriValidAsync(requestedUri, client);
}
}
private static bool IsLocalSPA(Client client) =>
client.Properties.TryGetValue(ApplicationProfilesPropertyNames.Profile, out var clientType) &&
ApplicationProfiles.IdentityServerSPA == clientType;
private Task<bool> ValidateRelativeUris(string requestedUri, IEnumerable<string> clientUris)
{
foreach (var url in clientUris)
{
if (Uri.IsWellFormedUriString(url, UriKind.Relative))
{
var newUri = AbsoluteUrlFactory.GetAbsoluteUrl(url);
if (string.Equals(newUri, requestedUri, StringComparison.Ordinal))
{
return Task.FromResult(true);
}
}
}
return Task.FromResult(false);
}
}
}

View File

@ -0,0 +1,270 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using IdentityServer4.Configuration;
using IdentityServer4.EntityFramework.Interfaces;
using IdentityServer4.Hosting;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for configuring Identity Server.
/// </summary>
public static class IdentityServerBuilderConfigurationExtensions
{
/// <summary>
/// Configures defaults for Identity Server for ASP.NET Core scenarios.
/// </summary>
/// <typeparam name="TUser">The <typeparamref name="TUser"/> type.</typeparam>
/// <typeparam name="TContext">The <typeparamref name="TContext"/> type.</typeparam>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddApiAuthorization<TUser, TContext>(
this IIdentityServerBuilder builder) where TUser : class
where TContext : DbContext, IPersistedGrantDbContext
{
builder.AddApiAuthorization<TUser, TContext>(o => { });
return builder;
}
/// <summary>
/// Configures defaults on Identity Server for ASP.NET Core scenarios.
/// </summary>
/// <typeparam name="TUser">The <typeparamref name="TUser"/> type.</typeparam>
/// <typeparam name="TContext">The <typeparamref name="TContext"/> type.</typeparam>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <param name="configure">The <see cref="Action{ApplicationsOptions}"/>
/// to configure the <see cref="ApiAuthorizationOptions"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddApiAuthorization<TUser, TContext>(
this IIdentityServerBuilder builder,
Action<ApiAuthorizationOptions> configure)
where TUser : class
where TContext : DbContext, IPersistedGrantDbContext
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
builder.AddAspNetIdentity<TUser>()
.AddOperationalStore<TContext>()
.ConfigureReplacedServices()
.AddIdentityResources()
.AddApiResources()
.AddClients()
.AddSigningCredentials();
builder.Services.Configure(configure);
return builder;
}
/// <summary>
/// Adds API resources from the default configuration to the server using the key
/// IdentityServer:Resources
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddApiResources(
this IIdentityServerBuilder builder) => builder.AddApiResources(configuration: null);
/// <summary>
/// Adds API resources from the given <paramref name="configuration"/> instance.
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> instance containing the API definitions.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddApiResources(
this IIdentityServerBuilder builder,
IConfiguration configuration)
{
builder.ConfigureReplacedServices();
builder.AddInMemoryApiResources(Enumerable.Empty<ApiResource>());
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<ApiAuthorizationOptions>, ConfigureApiResources>(sp =>
{
var logger = sp.GetRequiredService<ILogger<ConfigureApiResources>>();
var effectiveConfig = configuration ?? sp.GetRequiredService<IConfiguration>().GetSection("IdentityServer:Resources");
var localApiDescriptor = sp.GetService<IIdentityServerJwtDescriptor>();
return new ConfigureApiResources(effectiveConfig, localApiDescriptor, logger);
}));
// We take over the setup for the API resources as Identity Server registers the enumerable as a singleton
// and that prevents normal composition.
builder.Services.AddSingleton<IEnumerable<ApiResource>>(sp =>
{
var options = sp.GetRequiredService<IOptions<ApiAuthorizationOptions>>();
return options.Value.ApiResources;
});
return builder;
}
/// <summary>
/// Adds identity resources from the default configuration to the server using the key
/// IdentityServer:Resources
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddIdentityResources(
this IIdentityServerBuilder builder) => builder.AddIdentityResources(configuration: null);
/// <summary>
/// Adds identity resources from the given <paramref name="configuration"/> instance.
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> instance containing the API definitions.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddIdentityResources(
this IIdentityServerBuilder builder,
IConfiguration configuration)
{
builder.ConfigureReplacedServices();
builder.AddInMemoryIdentityResources(Enumerable.Empty<IdentityResource>());
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<ApiAuthorizationOptions>, ConfigureIdentityResources>(sp =>
{
var logger = sp.GetRequiredService<ILogger<ConfigureIdentityResources>>();
var effectiveConfig = configuration ?? sp.GetRequiredService<IConfiguration>().GetSection("IdentityServer:Identity");
return new ConfigureIdentityResources(effectiveConfig, logger);
}));
// We take over the setup for the identity resources as Identity Server registers the enumerable as a singleton
// and that prevents normal composition.
builder.Services.AddSingleton<IEnumerable<IdentityResource>>(sp =>
{
var options = sp.GetRequiredService<IOptions<ApiAuthorizationOptions>>();
return options.Value.IdentityResources;
});
return builder;
}
/// <summary>
/// Adds clients from the default configuration to the server using the key
/// IdentityServer:Clients
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddClients(
this IIdentityServerBuilder builder) => builder.AddClients(configuration: null);
/// <summary>
/// Adds clients from the given <paramref name="configuration"/> instance.
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> instance containing the client definitions.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddClients(
this IIdentityServerBuilder builder,
IConfiguration configuration)
{
builder.ConfigureReplacedServices();
builder.AddInMemoryClients(Enumerable.Empty<Client>());
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<ApiAuthorizationOptions>, ConfigureClientScopes>());
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<ApiAuthorizationOptions>, ConfigureClients>(sp =>
{
var logger = sp.GetRequiredService<ILogger<ConfigureClients>>();
var effectiveConfig = configuration ?? sp.GetRequiredService<IConfiguration>().GetSection("IdentityServer:Clients");
return new ConfigureClients(effectiveConfig, logger);
}));
// We take over the setup for the clients as Identity Server registers the enumerable as a singleton and that prevents normal composition.
builder.Services.AddSingleton<IEnumerable<Client>>(sp =>
{
var options = sp.GetRequiredService<IOptions<ApiAuthorizationOptions>>();
return options.Value.Clients;
});
return builder;
}
/// <summary>
/// Adds a signing key from the default configuration to the server using the configuration key
/// IdentityServer:Key
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddSigningCredentials(
this IIdentityServerBuilder builder) => builder.AddSigningCredentials(configuration: null);
/// <summary>
/// Adds a signing key from the given <paramref name="configuration"/> instance.
/// </summary>
/// <param name="builder">The <see cref="IIdentityServerBuilder"/>.</param>
/// <param name="configuration">The <see cref="IConfiguration"/>.</param>
/// <returns>The <see cref="IIdentityServerBuilder"/>.</returns>
public static IIdentityServerBuilder AddSigningCredentials(
this IIdentityServerBuilder builder,
IConfiguration configuration)
{
builder.ConfigureReplacedServices();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<ApiAuthorizationOptions>, ConfigureSigningCredentials>(sp =>
{
var logger = sp.GetRequiredService<ILogger<ConfigureSigningCredentials>>();
var effectiveConfig = configuration ?? sp.GetRequiredService<IConfiguration>().GetSection("IdentityServer:Key");
return new ConfigureSigningCredentials(effectiveConfig, logger);
}));
// We take over the setup for the credentials store as Identity Server registers a singleton
builder.Services.AddSingleton<ISigningCredentialStore>(sp =>
{
var options = sp.GetRequiredService<IOptions<ApiAuthorizationOptions>>();
return new DefaultSigningCredentialsStore(options.Value.SigningCredential);
});
// We take over the setup for the validation keys store as Identity Server registers a singleton
builder.Services.AddSingleton<IValidationKeysStore>(sp =>
{
var options = sp.GetRequiredService<IOptions<ApiAuthorizationOptions>>();
return new DefaultValidationKeysStore(new[] { options.Value.SigningCredential.Key });
});
return builder;
}
internal static IIdentityServerBuilder ConfigureReplacedServices(this IIdentityServerBuilder builder)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<IdentityServerOptions>, AspNetConventionsConfigureOptions>());
builder.Services.TryAddSingleton<IAbsoluteUrlFactory, AbsoluteUrlFactory>();
builder.Services.AddSingleton<IRedirectUriValidator, RelativeRedirectUriValidator>();
builder.Services.AddSingleton<IClientRequestParametersProvider, DefaultClientRequestParametersProvider>();
ReplaceEndSessionEndpoint(builder);
return builder;
}
private static void ReplaceEndSessionEndpoint(IIdentityServerBuilder builder)
{
// We don't have a better way to replace the end session endpoint as far as we know other than looking the descriptor up
// on the container and replacing the instance. This is due to the fact that we chain on AddIdentityServer which configures the
// list of endpoints by default.
var endSessionEndpointDescriptor = builder.Services
.Single(s => s.ImplementationInstance is Endpoint e &&
string.Equals(e.Name, "Endsession", StringComparison.OrdinalIgnoreCase) &&
string.Equals("/connect/endsession", e.Path, StringComparison.OrdinalIgnoreCase));
builder.Services.Remove(endSessionEndpointDescriptor);
builder.AddEndpoint<AutoRedirectEndSessionEndpoint>("EndSession", "/connect/endsession");
}
}
}

Some files were not shown because too many files have changed in this diff Show More