├── .appveyor.yml ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .vsts-pipelines └── builds │ ├── ci-internal.yml │ └── ci-public.yml ├── AADIntegration.sln ├── CONTRIBUTING.md ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE.txt ├── NuGet.config ├── NuGetPackageVerifier.json ├── README.md ├── Settings.StyleCop ├── build.cmd ├── build.sh ├── build ├── Key.snk ├── dependencies.props ├── repo.props └── sources.props ├── korebuild-lock.txt ├── korebuild.json ├── run.cmd ├── run.ps1 ├── run.sh ├── samples └── AzureADB2CSample │ ├── AzureADB2CSample.csproj │ ├── Pages │ ├── Index.cshtml │ ├── Index.cshtml.cs │ ├── Shared │ │ ├── _Layout.cshtml │ │ └── _LoginPartial.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ ├── banner3.svg │ └── banner4.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ └── jquery.validate.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ └── jquery.min.map ├── src ├── Directory.Build.props ├── Microsoft.AspNetCore.Authentication.AzureAD.UI │ ├── Areas │ │ └── AzureAD │ │ │ ├── Controllers │ │ │ └── AccountController.cs │ │ │ └── Pages │ │ │ ├── Account │ │ │ ├── AccessDenied.cshtml │ │ │ ├── AccessDenied.cshtml.cs │ │ │ ├── Error.cshtml │ │ │ ├── Error.cshtml.cs │ │ │ ├── SignedOut.cshtml │ │ │ ├── SignedOut.cshtml.cs │ │ │ └── _viewImports.cshtml │ │ │ └── _ViewStart.cshtml │ ├── AzureADAccountControllerFeatureProvider.cs │ ├── AzureADAuthenticationBuilderExtensions.cs │ ├── AzureADDefaults.cs │ ├── AzureADOptions.cs │ ├── AzureADOptionsConfiguration.cs │ ├── AzureADSchemeOptions.cs │ ├── CookieOptionsConfiguration.cs │ ├── JwtBearerOptionsConfiguration.cs │ ├── Microsoft.AspNetCore.Authentication.AzureAD.UI.csproj │ ├── OpenIdConnectOptionsConfiguration.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── baseline.netcore.json └── Microsoft.AspNetCore.Authentication.AzureADB2C.UI │ ├── Areas │ └── AzureADB2C │ │ ├── Controllers │ │ └── AccountController.cs │ │ └── Pages │ │ ├── Account │ │ ├── AccessDenied.cshtml │ │ ├── AccessDenied.cshtml.cs │ │ ├── Error.cshtml │ │ ├── Error.cshtml.cs │ │ ├── SignedOut.cshtml │ │ ├── SignedOut.cshtml.cs │ │ └── _viewImports.cshtml │ │ └── _ViewStart.cshtml │ ├── AzureADB2CAccountControllerFeatureProvider.cs │ ├── AzureAdB2CAuthenticationBuilderExtensions.cs │ ├── AzureAdB2CDefaults.cs │ ├── AzureAdB2COpenIDConnectEventHandlers.cs │ ├── AzureAdB2COptions.cs │ ├── AzureAdB2COptionsConfiguration.cs │ ├── AzureAdB2CSchemeOptions.cs │ ├── CookieOptionsConfiguration.cs │ ├── JwtBearerOptionsConfiguration.cs │ ├── Microsoft.AspNetCore.Authentication.AzureADB2C.UI.csproj │ ├── OpenIdConnectOptionsConfiguration.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── baseline.netcore.json ├── test ├── AADIntegration.ruleset ├── Directory.Build.props ├── Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests │ ├── ApiAuthenticationTests.cs │ ├── Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests.csproj │ ├── WebAuthenticationTests.cs │ └── xunit.runner.json ├── Microsoft.AspNetCore.Authentication.AzureAD.UI.Test │ ├── AzureADAuthenticationBuilderExtensionsTests.cs │ ├── Controllers │ │ └── AccountControllerTests.cs │ ├── Microsoft.AspNetCore.Authentication.AzureAD.UI.Test.csproj │ └── xunit.runner.json ├── Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test │ ├── AzureAdB2CAuthenticationBuilderExtensionsTests.cs │ ├── AzureAdB2COpenIDConnectEventHandlersTests.cs │ ├── Controllers │ │ └── AccountControllerTests.cs │ ├── Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test.csproj │ └── xunit.runner.json └── WebSites │ ├── AzureAD.WebSite │ ├── AzureAD.WebSite.csproj │ ├── Controllers │ │ └── TestController.cs │ ├── Program.cs │ └── Startup.cs │ └── Directory.Build.props └── version.props /.appveyor.yml: -------------------------------------------------------------------------------- 1 | init: 2 | - git config --global core.autocrlf true 3 | branches: 4 | only: 5 | - master 6 | - /^release\/.*$/ 7 | - /^(.*\/)?ci-.*$/ 8 | build_script: 9 | - ps: .\run.ps1 default-build 10 | clone_depth: 1 11 | environment: 12 | global: 13 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 14 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 15 | test: 'off' 16 | deploy: 'off' 17 | image: Visual Studio 2017 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome:http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | 11 | # Code files 12 | [*.{cs,csx,vb,vbx}] 13 | indent_size = 4 14 | 15 | # Xml project files 16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 17 | indent_size = 2 18 | 19 | # Xml config files 20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 21 | indent_size = 2 22 | 23 | # JSON files 24 | [*.json] 25 | indent_size = 2 26 | 27 | # Dotnet code style settings: 28 | [*.cs] 29 | # Sort using and Import directives with System.* appearing first 30 | dotnet_sort_system_directives_first = true 31 | 32 | # Don't use this. qualifier 33 | dotnet_style_qualification_for_field = false:suggestion 34 | dotnet_style_qualification_for_property = false:suggestion 35 | 36 | # use int x = .. over Int32 37 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 38 | 39 | # use int.MaxValue over Int32.MaxValue 40 | dotnet_style_predefined_type_for_member_access = true:suggestion 41 | 42 | # Require var all the time. 43 | csharp_style_var_for_built_in_types = true:suggestion 44 | csharp_style_var_when_type_is_apparent = true:suggestion 45 | csharp_style_var_elsewhere = true:suggestion 46 | 47 | # Disallow throw expressions. 48 | csharp_style_throw_expression = false:suggestion 49 | 50 | # Newline settings 51 | csharp_new_line_before_open_brace = all 52 | csharp_new_line_before_else = true 53 | csharp_new_line_before_catch = true 54 | csharp_new_line_before_finally = true 55 | csharp_new_line_before_members_in_object_initializers = true 56 | csharp_new_line_before_members_in_anonymous_types = true 57 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text=auto diff=csharp 17 | *.vb text=auto 18 | *.resx text=auto 19 | *.c text=auto 20 | *.cpp text=auto 21 | *.cxx text=auto 22 | *.h text=auto 23 | *.hxx text=auto 24 | *.py text=auto 25 | *.rb text=auto 26 | *.java text=auto 27 | *.html text=auto 28 | *.htm text=auto 29 | *.css text=auto 30 | *.scss text=auto 31 | *.sass text=auto 32 | *.less text=auto 33 | *.js text=auto 34 | *.lisp text=auto 35 | *.clj text=auto 36 | *.sql text=auto 37 | *.php text=auto 38 | *.lua text=auto 39 | *.m text=auto 40 | *.asm text=auto 41 | *.erl text=auto 42 | *.fs text=auto 43 | *.fsx text=auto 44 | *.hs text=auto 45 | 46 | *.csproj text=auto 47 | *.vbproj text=auto 48 | *.fsproj text=auto 49 | *.dbproj text=auto 50 | *.sln text=auto eol=crlf 51 | 52 | *.sh eol=lf 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj/ 2 | [Bb]in/ 3 | TestResults/ 4 | .nuget/ 5 | .build/ 6 | .testPublish/ 7 | *.sln.ide/ 8 | _ReSharper.*/ 9 | packages/ 10 | artifacts/ 11 | PublishProfiles/ 12 | .vs/ 13 | bower_components/ 14 | node_modules/ 15 | debugSettings.json 16 | project.lock.json 17 | *.user 18 | *.suo 19 | *.cache 20 | *.docstates 21 | _ReSharper.* 22 | nuget.exe 23 | *net45.csproj 24 | *net451.csproj 25 | *k10.csproj 26 | *.psess 27 | *.vsp 28 | *.pidb 29 | *.userprefs 30 | *DS_Store 31 | *.ncrunchsolution 32 | *.*sdf 33 | *.ipch 34 | .settings 35 | *.sln.ide 36 | node_modules 37 | *launchSettings.json 38 | *.orig 39 | .vscode/ 40 | global.json 41 | BenchmarkDotNet.Artifacts/ 42 | .idea/ 43 | msbuild.binlog 44 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | sudo: required 3 | dist: trusty 4 | env: 5 | global: 6 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 7 | - DOTNET_CLI_TELEMETRY_OPTOUT: 1 8 | addons: 9 | apt: 10 | packages: 11 | - libunwind8 12 | mono: none 13 | os: 14 | - linux 15 | - osx 16 | osx_image: xcode8.2 17 | branches: 18 | only: 19 | - master 20 | - /^release\/.*$/ 21 | - /^(.*\/)?ci-.*$/ 22 | before_install: 23 | - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s 24 | /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib 25 | /usr/local/lib/; fi 26 | script: 27 | - ./build.sh 28 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-internal.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | resources: 6 | repositories: 7 | - repository: buildtools 8 | type: git 9 | name: aspnet-BuildTools 10 | ref: refs/heads/master 11 | 12 | phases: 13 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 14 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-public.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | # See https://github.com/aspnet/BuildTools 6 | resources: 7 | repositories: 8 | - repository: buildtools 9 | type: github 10 | endpoint: DotNet-Bot GitHub Connection 11 | name: aspnet/BuildTools 12 | ref: refs/heads/master 13 | 14 | phases: 15 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 16 | -------------------------------------------------------------------------------- /AADIntegration.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{75A812B0-D98C-45F3-B2A9-357BBDF7331A}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{8CF63E1D-F9F7-4CB4-AD90-88C4077F7BFF}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{57F46508-E53D-4F6B-B77C-2EFE95925AEF}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureADB2CSample", "samples\AzureADB2CSample\AzureADB2CSample.csproj", "{5D2378D4-9DDA-468F-82C6-AE4DAA54E96C}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.AzureADB2C.UI", "src\Microsoft.AspNetCore.Authentication.AzureADB2C.UI\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.csproj", "{16912327-C9B3-49FC-87E0-49FEDED0A065}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test", "test\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test.csproj", "{454089F9-ED16-4A11-9C52-2BA74DCF5D35}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.AzureAD.UI", "src\Microsoft.AspNetCore.Authentication.AzureAD.UI\Microsoft.AspNetCore.Authentication.AzureAD.UI.csproj", "{1762840C-A14A-4498-9883-CC671956F0F2}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.AzureAD.UI.Test", "test\Microsoft.AspNetCore.Authentication.AzureAD.UI.Test\Microsoft.AspNetCore.Authentication.AzureAD.UI.Test.csproj", "{3D0CF896-3A9D-4A8F-A343-A2E1A131C861}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests", "test\Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests\Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests.csproj", "{1967296B-614B-43E5-B1BA-A601579961D5}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{2AEF59C3-7ADA-404D-B965-26B700FBD03F}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureAD.WebSite", "test\WebSites\AzureAD.WebSite\AzureAD.WebSite.csproj", "{4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {5D2378D4-9DDA-468F-82C6-AE4DAA54E96C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {5D2378D4-9DDA-468F-82C6-AE4DAA54E96C}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {5D2378D4-9DDA-468F-82C6-AE4DAA54E96C}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {5D2378D4-9DDA-468F-82C6-AE4DAA54E96C}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {16912327-C9B3-49FC-87E0-49FEDED0A065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {16912327-C9B3-49FC-87E0-49FEDED0A065}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {16912327-C9B3-49FC-87E0-49FEDED0A065}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {16912327-C9B3-49FC-87E0-49FEDED0A065}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {454089F9-ED16-4A11-9C52-2BA74DCF5D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {454089F9-ED16-4A11-9C52-2BA74DCF5D35}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {454089F9-ED16-4A11-9C52-2BA74DCF5D35}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {454089F9-ED16-4A11-9C52-2BA74DCF5D35}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {1762840C-A14A-4498-9883-CC671956F0F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {1762840C-A14A-4498-9883-CC671956F0F2}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {1762840C-A14A-4498-9883-CC671956F0F2}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {1762840C-A14A-4498-9883-CC671956F0F2}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {3D0CF896-3A9D-4A8F-A343-A2E1A131C861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {3D0CF896-3A9D-4A8F-A343-A2E1A131C861}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {3D0CF896-3A9D-4A8F-A343-A2E1A131C861}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {3D0CF896-3A9D-4A8F-A343-A2E1A131C861}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {1967296B-614B-43E5-B1BA-A601579961D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {1967296B-614B-43E5-B1BA-A601579961D5}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {1967296B-614B-43E5-B1BA-A601579961D5}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {1967296B-614B-43E5-B1BA-A601579961D5}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316}.Release|Any CPU.Build.0 = Release|Any CPU 62 | EndGlobalSection 63 | GlobalSection(SolutionProperties) = preSolution 64 | HideSolutionNode = FALSE 65 | EndGlobalSection 66 | GlobalSection(NestedProjects) = preSolution 67 | {5D2378D4-9DDA-468F-82C6-AE4DAA54E96C} = {8CF63E1D-F9F7-4CB4-AD90-88C4077F7BFF} 68 | {16912327-C9B3-49FC-87E0-49FEDED0A065} = {75A812B0-D98C-45F3-B2A9-357BBDF7331A} 69 | {454089F9-ED16-4A11-9C52-2BA74DCF5D35} = {57F46508-E53D-4F6B-B77C-2EFE95925AEF} 70 | {1762840C-A14A-4498-9883-CC671956F0F2} = {75A812B0-D98C-45F3-B2A9-357BBDF7331A} 71 | {3D0CF896-3A9D-4A8F-A343-A2E1A131C861} = {57F46508-E53D-4F6B-B77C-2EFE95925AEF} 72 | {1967296B-614B-43E5-B1BA-A601579961D5} = {57F46508-E53D-4F6B-B77C-2EFE95925AEF} 73 | {2AEF59C3-7ADA-404D-B965-26B700FBD03F} = {57F46508-E53D-4F6B-B77C-2EFE95925AEF} 74 | {4DB3C5B2-9FBF-42BC-80B2-2190EB1AE316} = {2AEF59C3-7ADA-404D-B965-26B700FBD03F} 75 | EndGlobalSection 76 | GlobalSection(ExtensibilityGlobals) = postSolution 77 | SolutionGuid = {C6DBF56C-E862-46EA-A4E0-993D2950D78D} 78 | EndGlobalSection 79 | EndGlobal 80 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ====== 3 | 4 | Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. 5 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Microsoft ASP.NET Core AAD Integration 12 | https://github.com/aspnet/AADIntegration 13 | git 14 | $(MSBuildThisFileDirectory) 15 | $(MSBuildThisFileDirectory)build\Key.snk 16 | true 17 | true 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MicrosoftNETCoreAppPackageVersion) 4 | $(NETStandardLibrary20PackageVersion) 5 | 6 | 7 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NuGetPackageVerifier.json: -------------------------------------------------------------------------------- 1 | { 2 | "Default": { 3 | "rules": [ 4 | "DefaultCompositeRule" 5 | ], 6 | "packages": { 7 | "Microsoft.AspNetCore.Authentication.AzureADB2C.UI": { 8 | "Exclusions": { 9 | "DOC_MISSING": { 10 | "lib/netcoreapp3.0/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Views.dll": "This library contains precompiled views." 11 | } 12 | } 13 | }, 14 | "Microsoft.AspNetCore.Authentication.AzureAD.UI": { 15 | "Exclusions": { 16 | "DOC_MISSING": { 17 | "lib/netcoreapp3.0/Microsoft.AspNetCore.Authentication.AzureAD.UI.Views.dll": "This library contains precompiled views." 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ASP.NET Core Azure Active Directory Integration [Archived] 2 | ========================================================== 3 | 4 | **This GitHub project has been archived.** Ongoing development on this project can be found in . 5 | 6 | ASP.NET Core Azure Active Directory Integration provides seamless authentication integration with different Azure Active Directory services like Azure Active Directory and Azure Active Directory B2C for ASP.NET Core applications. 7 | 8 | This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [AspNetCore](https://github.com/aspnet/AspNetCore) repo. 9 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) 7 | chmod +x "$DIR/run.sh"; sync 8 | "$DIR/run.sh" default-build "$@" 9 | -------------------------------------------------------------------------------- /build/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/build/Key.snk -------------------------------------------------------------------------------- /build/dependencies.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 4 | 5 | 6 | 3.0.0-build-20181114.5 7 | 3.0.0-alpha1-10742 8 | 3.0.0-alpha1-10742 9 | 3.0.0-alpha1-10742 10 | 3.0.0-alpha1-10742 11 | 3.0.0-alpha1-10742 12 | 3.0.0-alpha1-10742 13 | 3.0.0-alpha1-10742 14 | 3.0.0-alpha1-10742 15 | 3.0.0-alpha1-10742 16 | 3.0.0-alpha1-10742 17 | 3.0.0-alpha1-10742 18 | 3.0.0-alpha1-10742 19 | 3.0.0-alpha1-10742 20 | 3.0.0-preview-181113-11 21 | 3.0.0-preview-181113-11 22 | 3.0.0-preview-181113-11 23 | 3.0.0-preview-181113-11 24 | 3.0.0-preview-181113-11 25 | 3.0.0-preview-181113-11 26 | 3.0.0-preview-181113-11 27 | 3.0.0-preview-181113-11 28 | 3.0.0-preview1-26907-05 29 | 3.0.0-alpha1-10742 30 | 15.6.1 31 | 4.10.0 32 | 2.0.3 33 | 0.10.0 34 | 2.3.1 35 | 2.4.0 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /build/repo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Internal.AspNetCore.Universe.Lineup 7 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /build/sources.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | $(DotNetRestoreSources) 6 | 7 | $(RestoreSources); 8 | https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; 9 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; 10 | https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; 11 | 12 | 13 | $(RestoreSources); 14 | https://api.nuget.org/v3/index.json; 15 | 16 | 17 | -------------------------------------------------------------------------------- /korebuild-lock.txt: -------------------------------------------------------------------------------- 1 | version:3.0.0-build-20181114.5 2 | commithash:880e9a204d4ee4a18dfd83c9fb05a192a28bca60 3 | -------------------------------------------------------------------------------- /korebuild.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", 3 | "channel": "master" 4 | } 5 | -------------------------------------------------------------------------------- /run.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /run.ps1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env powershell 2 | #requires -version 4 3 | 4 | <# 5 | .SYNOPSIS 6 | Executes KoreBuild commands. 7 | 8 | .DESCRIPTION 9 | Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. 10 | 11 | .PARAMETER Command 12 | The KoreBuild command to run. 13 | 14 | .PARAMETER Path 15 | The folder to build. Defaults to the folder containing this script. 16 | 17 | .PARAMETER Channel 18 | The channel of KoreBuild to download. Overrides the value from the config file. 19 | 20 | .PARAMETER DotNetHome 21 | The directory where .NET Core tools will be stored. 22 | 23 | .PARAMETER ToolsSource 24 | The base url where build tools can be downloaded. Overrides the value from the config file. 25 | 26 | .PARAMETER Update 27 | Updates KoreBuild to the latest version even if a lock file is present. 28 | 29 | .PARAMETER Reinstall 30 | Re-installs KoreBuild 31 | 32 | .PARAMETER ConfigFile 33 | The path to the configuration file that stores values. Defaults to korebuild.json. 34 | 35 | .PARAMETER ToolsSourceSuffix 36 | The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. 37 | 38 | .PARAMETER CI 39 | Sets up CI specific settings and variables. 40 | 41 | .PARAMETER Arguments 42 | Arguments to be passed to the command 43 | 44 | .NOTES 45 | This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. 46 | When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. 47 | 48 | The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set 49 | in the file are overridden by command line parameters. 50 | 51 | .EXAMPLE 52 | Example config file: 53 | ```json 54 | { 55 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", 56 | "channel": "master", 57 | "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" 58 | } 59 | ``` 60 | #> 61 | [CmdletBinding(PositionalBinding = $false)] 62 | param( 63 | [Parameter(Mandatory = $true, Position = 0)] 64 | [string]$Command, 65 | [string]$Path = $PSScriptRoot, 66 | [Alias('c')] 67 | [string]$Channel, 68 | [Alias('d')] 69 | [string]$DotNetHome, 70 | [Alias('s')] 71 | [string]$ToolsSource, 72 | [Alias('u')] 73 | [switch]$Update, 74 | [switch]$Reinstall, 75 | [string]$ToolsSourceSuffix, 76 | [string]$ConfigFile = $null, 77 | [switch]$CI, 78 | [Parameter(ValueFromRemainingArguments = $true)] 79 | [string[]]$Arguments 80 | ) 81 | 82 | Set-StrictMode -Version 2 83 | $ErrorActionPreference = 'Stop' 84 | 85 | # 86 | # Functions 87 | # 88 | 89 | function Get-KoreBuild { 90 | 91 | $lockFile = Join-Path $Path 'korebuild-lock.txt' 92 | 93 | if (!(Test-Path $lockFile) -or $Update) { 94 | Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix 95 | } 96 | 97 | $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 98 | if (!$version) { 99 | Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" 100 | } 101 | $version = $version.TrimStart('version:').Trim() 102 | $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) 103 | 104 | if ($Reinstall -and (Test-Path $korebuildPath)) { 105 | Remove-Item -Force -Recurse $korebuildPath 106 | } 107 | 108 | if (!(Test-Path $korebuildPath)) { 109 | Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" 110 | New-Item -ItemType Directory -Path $korebuildPath | Out-Null 111 | $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" 112 | 113 | try { 114 | $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" 115 | Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix 116 | if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { 117 | # Use built-in commands where possible as they are cross-plat compatible 118 | Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath 119 | } 120 | else { 121 | # Fallback to old approach for old installations of PowerShell 122 | Add-Type -AssemblyName System.IO.Compression.FileSystem 123 | [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) 124 | } 125 | } 126 | catch { 127 | Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore 128 | throw 129 | } 130 | finally { 131 | Remove-Item $tmpfile -ErrorAction Ignore 132 | } 133 | } 134 | 135 | return $korebuildPath 136 | } 137 | 138 | function Join-Paths([string]$path, [string[]]$childPaths) { 139 | $childPaths | ForEach-Object { $path = Join-Path $path $_ } 140 | return $path 141 | } 142 | 143 | function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { 144 | if ($RemotePath -notlike 'http*') { 145 | Copy-Item $RemotePath $LocalPath 146 | return 147 | } 148 | 149 | $retries = 10 150 | while ($retries -gt 0) { 151 | $retries -= 1 152 | try { 153 | Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath 154 | return 155 | } 156 | catch { 157 | Write-Verbose "Request failed. $retries retries remaining" 158 | } 159 | } 160 | 161 | Write-Error "Download failed: '$RemotePath'." 162 | } 163 | 164 | # 165 | # Main 166 | # 167 | 168 | # Load configuration or set defaults 169 | 170 | $Path = Resolve-Path $Path 171 | if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } 172 | 173 | if (Test-Path $ConfigFile) { 174 | try { 175 | $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json 176 | if ($config) { 177 | if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } 178 | if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} 179 | } 180 | } 181 | catch { 182 | Write-Host -ForegroundColor Red $Error[0] 183 | Write-Error "$ConfigFile contains invalid JSON." 184 | exit 1 185 | } 186 | } 187 | 188 | if (!$DotNetHome) { 189 | $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` 190 | elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` 191 | elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` 192 | else { Join-Path $PSScriptRoot '.dotnet'} 193 | } 194 | 195 | if (!$Channel) { $Channel = 'master' } 196 | if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } 197 | 198 | # Execute 199 | 200 | $korebuildPath = Get-KoreBuild 201 | Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') 202 | 203 | try { 204 | Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI 205 | Invoke-KoreBuildCommand $Command @Arguments 206 | } 207 | finally { 208 | Remove-Module 'KoreBuild' -ErrorAction Ignore 209 | } 210 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | # 6 | # variables 7 | # 8 | 9 | RESET="\033[0m" 10 | RED="\033[0;31m" 11 | YELLOW="\033[0;33m" 12 | MAGENTA="\033[0;95m" 13 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 14 | [ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" 15 | verbose=false 16 | update=false 17 | reinstall=false 18 | repo_path="$DIR" 19 | channel='' 20 | tools_source='' 21 | tools_source_suffix='' 22 | ci=false 23 | 24 | # 25 | # Functions 26 | # 27 | __usage() { 28 | echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" 29 | echo "" 30 | echo "Arguments:" 31 | echo " command The command to be run." 32 | echo " ... Arguments passed to the command. Variable number of arguments allowed." 33 | echo "" 34 | echo "Options:" 35 | echo " --verbose Show verbose output." 36 | echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." 37 | echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." 38 | echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." 39 | echo " --path The directory to build. Defaults to the directory containing the script." 40 | echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." 41 | echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." 42 | echo " -u|--update Update to the latest KoreBuild even if the lock file is present." 43 | echo " --reinstall Reinstall KoreBuild." 44 | echo " --ci Apply CI specific settings and environment variables." 45 | echo "" 46 | echo "Description:" 47 | echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." 48 | echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." 49 | 50 | if [[ "${1:-}" != '--no-exit' ]]; then 51 | exit 2 52 | fi 53 | } 54 | 55 | get_korebuild() { 56 | local version 57 | local lock_file="$repo_path/korebuild-lock.txt" 58 | if [ ! -f "$lock_file" ] || [ "$update" = true ]; then 59 | __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" 60 | fi 61 | version="$(grep 'version:*' -m 1 "$lock_file")" 62 | if [[ "$version" == '' ]]; then 63 | __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" 64 | return 1 65 | fi 66 | version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 67 | local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" 68 | 69 | if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then 70 | rm -rf "$korebuild_path" 71 | fi 72 | 73 | { 74 | if [ ! -d "$korebuild_path" ]; then 75 | mkdir -p "$korebuild_path" 76 | local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" 77 | tmpfile="$(mktemp)" 78 | echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" 79 | if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then 80 | unzip -q -d "$korebuild_path" "$tmpfile" 81 | fi 82 | rm "$tmpfile" || true 83 | fi 84 | 85 | source "$korebuild_path/KoreBuild.sh" 86 | } || { 87 | if [ -d "$korebuild_path" ]; then 88 | echo "Cleaning up after failed installation" 89 | rm -rf "$korebuild_path" || true 90 | fi 91 | return 1 92 | } 93 | } 94 | 95 | __error() { 96 | echo -e "${RED}error: $*${RESET}" 1>&2 97 | } 98 | 99 | __warn() { 100 | echo -e "${YELLOW}warning: $*${RESET}" 101 | } 102 | 103 | __machine_has() { 104 | hash "$1" > /dev/null 2>&1 105 | return $? 106 | } 107 | 108 | __get_remote_file() { 109 | local remote_path=$1 110 | local local_path=$2 111 | local remote_path_suffix=$3 112 | 113 | if [[ "$remote_path" != 'http'* ]]; then 114 | cp "$remote_path" "$local_path" 115 | return 0 116 | fi 117 | 118 | local failed=false 119 | if __machine_has wget; then 120 | wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true 121 | else 122 | failed=true 123 | fi 124 | 125 | if [ "$failed" = true ] && __machine_has curl; then 126 | failed=false 127 | curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true 128 | fi 129 | 130 | if [ "$failed" = true ]; then 131 | __error "Download failed: $remote_path" 1>&2 132 | return 1 133 | fi 134 | } 135 | 136 | # 137 | # main 138 | # 139 | 140 | command="${1:-}" 141 | shift 142 | 143 | while [[ $# -gt 0 ]]; do 144 | case $1 in 145 | -\?|-h|--help) 146 | __usage --no-exit 147 | exit 0 148 | ;; 149 | -c|--channel|-Channel) 150 | shift 151 | channel="${1:-}" 152 | [ -z "$channel" ] && __usage 153 | ;; 154 | --config-file|-ConfigFile) 155 | shift 156 | config_file="${1:-}" 157 | [ -z "$config_file" ] && __usage 158 | if [ ! -f "$config_file" ]; then 159 | __error "Invalid value for --config-file. $config_file does not exist." 160 | exit 1 161 | fi 162 | ;; 163 | -d|--dotnet-home|-DotNetHome) 164 | shift 165 | DOTNET_HOME="${1:-}" 166 | [ -z "$DOTNET_HOME" ] && __usage 167 | ;; 168 | --path|-Path) 169 | shift 170 | repo_path="${1:-}" 171 | [ -z "$repo_path" ] && __usage 172 | ;; 173 | -s|--tools-source|-ToolsSource) 174 | shift 175 | tools_source="${1:-}" 176 | [ -z "$tools_source" ] && __usage 177 | ;; 178 | --tools-source-suffix|-ToolsSourceSuffix) 179 | shift 180 | tools_source_suffix="${1:-}" 181 | [ -z "$tools_source_suffix" ] && __usage 182 | ;; 183 | -u|--update|-Update) 184 | update=true 185 | ;; 186 | --reinstall|-[Rr]einstall) 187 | reinstall=true 188 | ;; 189 | --ci|-[Cc][Ii]) 190 | ci=true 191 | ;; 192 | --verbose|-Verbose) 193 | verbose=true 194 | ;; 195 | --) 196 | shift 197 | break 198 | ;; 199 | *) 200 | break 201 | ;; 202 | esac 203 | shift 204 | done 205 | 206 | if ! __machine_has unzip; then 207 | __error 'Missing required command: unzip' 208 | exit 1 209 | fi 210 | 211 | if ! __machine_has curl && ! __machine_has wget; then 212 | __error 'Missing required command. Either wget or curl is required.' 213 | exit 1 214 | fi 215 | 216 | [ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" 217 | if [ -f "$config_file" ]; then 218 | if __machine_has jq ; then 219 | if jq '.' "$config_file" >/dev/null ; then 220 | config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" 221 | config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" 222 | else 223 | __error "$config_file contains invalid JSON." 224 | exit 1 225 | fi 226 | elif __machine_has python ; then 227 | if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then 228 | config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" 229 | config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" 230 | else 231 | __error "$config_file contains invalid JSON." 232 | exit 1 233 | fi 234 | elif __machine_has python3 ; then 235 | if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then 236 | config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" 237 | config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" 238 | else 239 | __error "$config_file contains invalid JSON." 240 | exit 1 241 | fi 242 | else 243 | __error 'Missing required command: jq or python. Could not parse the JSON file.' 244 | exit 1 245 | fi 246 | 247 | [ ! -z "${config_channel:-}" ] && channel="$config_channel" 248 | [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" 249 | fi 250 | 251 | [ -z "$channel" ] && channel='master' 252 | [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' 253 | 254 | get_korebuild 255 | set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" 256 | invoke_korebuild_command "$command" "$@" 257 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/AzureADB2CSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |
8 |

@User.Identity.Name

9 |
-------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.RazorPages; 2 | 3 | namespace AzureADB2CSample.Pages 4 | { 5 | public class IndexModel : PageModel 6 | { 7 | public void OnGet() 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - AzureADB2CSample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 39 | 40 |
41 | @RenderBody() 42 |
43 |
44 |

© 2018 - AzureADB2CSample

45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 66 | 67 | 68 | 69 | @RenderSection("Scripts", required: false) 70 | 71 | 72 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Authentication.AzureADB2C.UI 2 | @using Microsoft.Extensions.Options 3 | @inject IOptionsMonitor AzureADB2COptions 4 | @{ 5 | var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme); 6 | } 7 | @if (User.Identity.IsAuthenticated) 8 | { 9 | 20 | } 21 | else 22 | { 23 | 26 | } 27 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @namespace AzureADB2CSample.Pages 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.IO; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace AzureADB2CSample 10 | { 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | CreateWebHostBuilder(args).Build().Run(); 16 | } 17 | 18 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 19 | new WebHostBuilder() 20 | .UseContentRoot(Directory.GetCurrentDirectory()) 21 | .ConfigureAppConfiguration((hostingContext, config) =>{ 22 | var env = hostingContext.HostingEnvironment; 23 | 24 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 25 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); 26 | 27 | config.AddEnvironmentVariables(); 28 | }) 29 | .ConfigureLogging(factory => 30 | { 31 | factory 32 | .AddConsole() 33 | .AddDebug(); 34 | }) 35 | .UseIISIntegration() 36 | .UseKestrel() 37 | .UseStartup(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:59364/", 7 | "sslPort": 44315 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "AzureADB2CSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:44315/;http://localhost:59364/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Authentication; 5 | using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | 10 | namespace AzureADB2CSample 11 | { 12 | public class Startup 13 | { 14 | public Startup(IConfiguration configuration) 15 | { 16 | Configuration = configuration; 17 | } 18 | 19 | public IConfiguration Configuration { get; } 20 | 21 | // This method gets called by the runtime. Use this method to add services to the container. 22 | public void ConfigureServices(IServiceCollection services) 23 | { 24 | services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) 25 | .AddAzureADB2C(options => Configuration.GetSection("AzureADB2C").Bind(options)); 26 | 27 | services.AddMvc(); 28 | } 29 | 30 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 31 | public void Configure(IApplicationBuilder app) 32 | { 33 | app.UseHttpsRedirection(); 34 | app.UseAuthentication(); 35 | app.UseStaticFiles(); 36 | app.UseMvcWithDefaultRoute(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureADB2C": { 3 | "Instance": "https://login.microsoftonline.com/tfp/", 4 | "ClientId": "64f31f76-2750-49e4-aab9-f5de105b5172", 5 | "CallbackPath": "/signin-oidc", 6 | "Domain": "jacalvarb2c.onmicrosoft.com", 7 | "SignUpSignInPolicyId": "B2C_1_SiUpIn", 8 | "ResetPasswordPolicyId": "B2C_1_SSPR", 9 | "EditProfilePolicyId": "B2C_1_SiPe" 10 | }, 11 | "Logging": { 12 | "LogLevel": { 13 | "Default": "Warning" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Carousel */ 14 | .carousel-caption p { 15 | font-size: 20px; 16 | line-height: 1.4; 17 | } 18 | 19 | /* Make .svg files in the carousel display properly in older browsers */ 20 | .carousel-inner .item img[src$=".svg"] { 21 | width: 100%; 22 | } 23 | 24 | /* QR code generator */ 25 | #qrCode { 26 | margin: 15px; 27 | } 28 | 29 | /* Hide/rearrange for smaller screens */ 30 | @media screen and (max-width: 767px) { 31 | /* Hide captions */ 32 | .carousel-caption { 33 | display: none; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | 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}} -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/favicon.ico -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/images/banner1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/images/banner2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/images/banner3.svg: -------------------------------------------------------------------------------- 1 | banner3b -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.3.7", 35 | "_release": "3.3.7", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.7", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.3.7", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/AADIntegration/26c7e2cdf2fb7977c0d06becd8332aebc82177ee/samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /samples/AzureADB2CSample/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.AzureAD.Controllers.Internal 9 | { 10 | [NonController] 11 | [AllowAnonymous] 12 | [Area("AzureAD")] 13 | [Route("[area]/[controller]/[action]")] 14 | internal class AccountController : Controller 15 | { 16 | public AccountController(IOptionsMonitor options) 17 | { 18 | Options = options; 19 | } 20 | 21 | public IOptionsMonitor Options { get; } 22 | 23 | [HttpGet("{scheme?}")] 24 | public IActionResult SignIn([FromRoute] string scheme) 25 | { 26 | scheme = scheme ?? AzureADDefaults.AuthenticationScheme; 27 | var redirectUrl = Url.Content("~/"); 28 | return Challenge( 29 | new AuthenticationProperties { RedirectUri = redirectUrl }, 30 | scheme); 31 | } 32 | 33 | [HttpGet("{scheme?}")] 34 | public IActionResult SignOut([FromRoute] string scheme) 35 | { 36 | scheme = scheme ?? AzureADDefaults.AuthenticationScheme; 37 | var options = Options.Get(scheme); 38 | var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme); 39 | return SignOut( 40 | new AuthenticationProperties { RedirectUri = callbackUrl }, 41 | options.CookieSchemeName, 42 | options.OpenIdConnectSchemeName); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/AccessDenied.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AccessDeniedModel 3 | @{ 4 | ViewData["Title"] = "Access denied"; 5 | } 6 | 7 |
    8 |

    @ViewData["Title"]

    9 |

    You do not have access to this resource.

    10 |
    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/AccessDenied.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.Internal 8 | { 9 | /// 10 | /// This API supports infrastructure and is not intended to be used 11 | /// directly from your code.This API may change or be removed in future releases 12 | /// 13 | [AllowAnonymous] 14 | public class AccessDeniedModel : PageModel 15 | { 16 | /// 17 | /// This API supports infrastructure and is not intended to be used 18 | /// directly from your code.This API may change or be removed in future releases 19 | /// 20 | public void OnGet() 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

    Error.

    8 |

    An error occurred while processing your request.

    9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

    13 | Request ID: @Model.RequestId 14 |

    15 | } 16 | 17 |

    Development Mode

    18 |

    19 | Swapping to Development environment will display more detailed information about the error that occurred. 20 |

    21 |

    22 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 23 |

    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Diagnostics; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.Internal 10 | { 11 | /// 12 | /// This API supports infrastructure and is not intended to be used 13 | /// directly from your code.This API may change or be removed in future releases 14 | /// 15 | [AllowAnonymous] 16 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 17 | public class ErrorModel : PageModel 18 | { 19 | /// 20 | /// This API supports infrastructure and is not intended to be used 21 | /// directly from your code.This API may change or be removed in future releases 22 | /// 23 | public string RequestId { get; set; } 24 | 25 | /// 26 | /// This API supports infrastructure and is not intended to be used 27 | /// directly from your code.This API may change or be removed in future releases 28 | /// 29 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 30 | 31 | /// 32 | /// This API supports infrastructure and is not intended to be used 33 | /// directly from your code.This API may change or be removed in future releases 34 | /// 35 | public void OnGet() 36 | { 37 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/SignedOut.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model SignedOutModel 3 | @{ 4 | ViewData["Title"] = "Signed out"; 5 | } 6 | 7 |

    @ViewData["Title"]

    8 |

    9 | You have successfully signed out. 10 |

    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/SignedOut.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.Internal 9 | { 10 | /// 11 | /// This API supports infrastructure and is not intended to be used 12 | /// directly from your code.This API may change or be removed in future releases 13 | /// 14 | [AllowAnonymous] 15 | public class SignedOutModel : PageModel 16 | { 17 | /// 18 | /// This API supports infrastructure and is not intended to be used 19 | /// directly from your code.This API may change or be removed in future releases 20 | /// 21 | public IActionResult OnGet() 22 | { 23 | if (User.Identity.IsAuthenticated) 24 | { 25 | return LocalRedirect("~/"); 26 | } 27 | 28 | return Page(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/Account/_viewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Authentication.AzureAD.UI.Internal 2 | @namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.Pages.Internal -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Areas/AzureAD/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Hosting 2 | @using Microsoft.AspNetCore.Mvc.ViewEngines 3 | 4 | @inject IHostingEnvironment Environment 5 | @inject ICompositeViewEngine Engine 6 | 7 | @{ 8 | var result = Engine.FindView(ViewContext, "_Layout", isMainPage: false); 9 | if (result.Success) 10 | { 11 | Layout = "_Layout"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADAccountControllerFeatureProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using Microsoft.AspNetCore.Authentication.AzureAD.UI.AzureAD.Controllers.Internal; 7 | using Microsoft.AspNetCore.Mvc.ApplicationParts; 8 | using Microsoft.AspNetCore.Mvc.Controllers; 9 | 10 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 11 | { 12 | internal class AzureADAccountControllerFeatureProvider : IApplicationFeatureProvider, IApplicationFeatureProvider 13 | { 14 | public void PopulateFeature(IEnumerable parts, ControllerFeature feature) 15 | { 16 | if (!feature.Controllers.Contains(typeof(AccountController).GetTypeInfo())) 17 | { 18 | feature.Controllers.Add(typeof(AccountController).GetTypeInfo()); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADAuthenticationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Microsoft.AspNetCore.Authentication.AzureAD.UI; 8 | using Microsoft.AspNetCore.Authentication.Cookies; 9 | using Microsoft.AspNetCore.Authentication.JwtBearer; 10 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 11 | using Microsoft.AspNetCore.Mvc.ApplicationParts; 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.DependencyInjection.Extensions; 14 | using Microsoft.Extensions.Options; 15 | 16 | namespace Microsoft.AspNetCore.Authentication 17 | { 18 | /// 19 | /// Extension methods to add Azure Active Directory Authentication to your application. 20 | /// 21 | public static class AzureADAuthenticationBuilderExtensions 22 | { 23 | /// 24 | /// Adds JWT Bearer authentication to your app for Azure Active Directory Applications. 25 | /// 26 | /// The . 27 | /// The to configure the 28 | /// . 29 | /// 30 | /// The . 31 | public static AuthenticationBuilder AddAzureADBearer(this AuthenticationBuilder builder, Action configureOptions) => 32 | builder.AddAzureADBearer( 33 | AzureADDefaults.BearerAuthenticationScheme, 34 | AzureADDefaults.JwtBearerAuthenticationScheme, 35 | configureOptions); 36 | 37 | /// 38 | /// Adds JWT Bearer authentication to your app for Azure Active Directory Applications. 39 | /// 40 | /// The . 41 | /// The identifier for the virtual scheme. 42 | /// The identifier for the underlying JWT Bearer scheme. 43 | /// The to configure the 44 | /// . 45 | /// 46 | /// The . 47 | public static AuthenticationBuilder AddAzureADBearer( 48 | this AuthenticationBuilder builder, 49 | string scheme, 50 | string jwtBearerScheme, 51 | Action configureOptions) 52 | { 53 | 54 | builder.AddPolicyScheme(scheme, displayName: null, configureOptions: o => 55 | { 56 | o.ForwardDefault = jwtBearerScheme; 57 | }); 58 | 59 | builder.Services.Configure(TryAddJwtBearerSchemeMapping(scheme, jwtBearerScheme)); 60 | 61 | builder.Services.TryAddSingleton, AzureADOptionsConfiguration>(); 62 | 63 | builder.Services.TryAddSingleton, JwtBearerOptionsConfiguration>(); 64 | 65 | builder.Services.Configure(scheme, configureOptions); 66 | builder.AddJwtBearer(jwtBearerScheme, o => { }); 67 | 68 | return builder; 69 | } 70 | 71 | /// 72 | /// Adds Azure Active Directory Authentication to your application. 73 | /// 74 | /// The . 75 | /// The to configure the 76 | /// 77 | /// 78 | /// The . 79 | public static AuthenticationBuilder AddAzureAD(this AuthenticationBuilder builder, Action configureOptions) => 80 | builder.AddAzureAD( 81 | AzureADDefaults.AuthenticationScheme, 82 | AzureADDefaults.OpenIdScheme, 83 | AzureADDefaults.CookieScheme, 84 | AzureADDefaults.DisplayName, 85 | configureOptions); 86 | 87 | /// 88 | /// Adds Azure Active Directory Authentication to your application. 89 | /// 90 | /// The . 91 | /// The identifier for the virtual scheme. 92 | /// The identifier for the underlying Open ID Connect scheme. 93 | /// The identifier for the underlying cookie scheme. 94 | /// The display name for the scheme. 95 | /// The to configure the 96 | /// 97 | /// 98 | /// The . 99 | public static AuthenticationBuilder AddAzureAD( 100 | this AuthenticationBuilder builder, 101 | string scheme, 102 | string openIdConnectScheme, 103 | string cookieScheme, 104 | string displayName, 105 | Action configureOptions) 106 | { 107 | AddAdditionalMvcApplicationParts(builder.Services); 108 | builder.AddPolicyScheme(scheme, displayName, o => 109 | { 110 | o.ForwardDefault = cookieScheme; 111 | o.ForwardChallenge = openIdConnectScheme; 112 | }); 113 | 114 | builder.Services.Configure(TryAddOpenIDCookieSchemeMappings(scheme, openIdConnectScheme, cookieScheme)); 115 | 116 | builder.Services.TryAddSingleton, AzureADOptionsConfiguration>(); 117 | 118 | builder.Services.TryAddSingleton, OpenIdConnectOptionsConfiguration>(); 119 | 120 | builder.Services.TryAddSingleton, CookieOptionsConfiguration>(); 121 | 122 | builder.Services.Configure(scheme, configureOptions); 123 | 124 | builder.AddOpenIdConnect(openIdConnectScheme, null, o => { }); 125 | builder.AddCookie(cookieScheme, null, o => { }); 126 | 127 | return builder; 128 | } 129 | 130 | private static Action TryAddJwtBearerSchemeMapping(string scheme, string jwtBearerScheme) 131 | { 132 | return TryAddMapping; 133 | 134 | void TryAddMapping(AzureADSchemeOptions o) 135 | { 136 | if (o.JwtBearerMappings.ContainsKey(scheme)) 137 | { 138 | throw new InvalidOperationException($"A scheme with the name '{scheme}' was already added."); 139 | } 140 | foreach (var mapping in o.JwtBearerMappings) 141 | { 142 | if (mapping.Value.JwtBearerScheme == jwtBearerScheme) 143 | { 144 | throw new InvalidOperationException( 145 | $"The JSON Web Token Bearer scheme '{jwtBearerScheme}' can't be associated with the Azure Active Directory scheme '{scheme}'. " + 146 | $"The JSON Web Token Bearer scheme '{jwtBearerScheme}' is already mapped to the Azure Active Directory scheme '{mapping.Key}'"); 147 | } 148 | } 149 | o.JwtBearerMappings.Add(scheme, new AzureADSchemeOptions.JwtBearerSchemeMapping 150 | { 151 | JwtBearerScheme = jwtBearerScheme 152 | }); 153 | }; 154 | } 155 | 156 | private static Action TryAddOpenIDCookieSchemeMappings(string scheme, string openIdConnectScheme, string cookieScheme) 157 | { 158 | return TryAddMapping; 159 | 160 | void TryAddMapping(AzureADSchemeOptions o) 161 | { 162 | if (o.OpenIDMappings.ContainsKey(scheme)) 163 | { 164 | throw new InvalidOperationException($"A scheme with the name '{scheme}' was already added."); 165 | } 166 | foreach (var mapping in o.OpenIDMappings) 167 | { 168 | if (mapping.Value.CookieScheme == cookieScheme) 169 | { 170 | throw new InvalidOperationException( 171 | $"The cookie scheme '{cookieScheme}' can't be associated with the Azure Active Directory scheme '{scheme}'. " + 172 | $"The cookie scheme '{cookieScheme}' is already mapped to the Azure Active Directory scheme '{mapping.Key}'"); 173 | } 174 | 175 | if (mapping.Value.OpenIdConnectScheme == openIdConnectScheme) 176 | { 177 | throw new InvalidOperationException( 178 | $"The Open ID Connect scheme '{openIdConnectScheme}' can't be associated with the Azure Active Directory scheme '{scheme}'. " + 179 | $"The Open ID Connect scheme '{openIdConnectScheme}' is already mapped to the Azure Active Directory scheme '{mapping.Key}'"); 180 | } 181 | } 182 | o.OpenIDMappings.Add(scheme, new AzureADSchemeOptions.AzureADOpenIDSchemeMapping 183 | { 184 | OpenIdConnectScheme = openIdConnectScheme, 185 | CookieScheme = cookieScheme 186 | }); 187 | }; 188 | } 189 | 190 | private static void AddAdditionalMvcApplicationParts(IServiceCollection services) 191 | { 192 | var additionalParts = GetAdditionalParts(); 193 | var mvcBuilder = services 194 | .AddMvc() 195 | .AddRazorPagesOptions(o => o.AllowAreas = true) 196 | .ConfigureApplicationPartManager(apm => 197 | { 198 | foreach (var part in additionalParts) 199 | { 200 | if (!apm.ApplicationParts.Any(ap => HasSameName(ap.Name, part.Name))) 201 | { 202 | apm.ApplicationParts.Add(part); 203 | } 204 | } 205 | 206 | apm.FeatureProviders.Add(new AzureADAccountControllerFeatureProvider()); 207 | }); 208 | 209 | bool HasSameName(string left, string right) => string.Equals(left, right, StringComparison.Ordinal); 210 | } 211 | 212 | private static IEnumerable GetAdditionalParts() 213 | { 214 | var thisAssembly = typeof(AzureADAuthenticationBuilderExtensions).Assembly; 215 | var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(thisAssembly, throwOnError: true); 216 | 217 | foreach (var reference in relatedAssemblies) 218 | { 219 | yield return new CompiledRazorAssemblyPart(reference); 220 | } 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADDefaults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | 5 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 6 | { 7 | /// 8 | /// Constants for different Azure Active Directory authentication components. 9 | /// 10 | public static class AzureADDefaults 11 | { 12 | /// 13 | /// The scheme name for Open ID Connect when using 14 | /// . 15 | /// 16 | public static readonly string OpenIdScheme = "AzureADOpenID"; 17 | 18 | /// 19 | /// The scheme name for cookies when using 20 | /// . 21 | /// 22 | public static readonly string CookieScheme = "AzureADCookie"; 23 | 24 | /// 25 | /// The default scheme for Azure Active Directory Bearer. 26 | /// 27 | public static readonly string BearerAuthenticationScheme = "AzureADBearer"; 28 | 29 | /// 30 | /// The scheme name for JWT Bearer when using 31 | /// . 32 | /// 33 | public static readonly string JwtBearerAuthenticationScheme = "AzureADJwtBearer"; 34 | 35 | /// 36 | /// The default scheme for Azure Active Directory. 37 | /// 38 | public static readonly string AuthenticationScheme = "AzureAD"; 39 | 40 | /// 41 | /// The display name for Azure Active Directory. 42 | /// 43 | public static readonly string DisplayName = "Azure Active Directory"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authentication.Cookies; 5 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 8 | { 9 | /// 10 | /// Options for configuring authentication using Azure Active Directory. 11 | /// 12 | public class AzureADOptions 13 | { 14 | /// 15 | /// Gets or sets the OpenID Connect authentication scheme to use for authentication with this instance 16 | /// of Azure Active Directory authentication. 17 | /// 18 | public string OpenIdConnectSchemeName { get; set; } = OpenIdConnectDefaults.AuthenticationScheme; 19 | 20 | /// 21 | /// Gets or sets the Cookie authentication scheme to use for sign in with this instance of 22 | /// Azure Active Directory authentication. 23 | /// 24 | public string CookieSchemeName { get; set; } = CookieAuthenticationDefaults.AuthenticationScheme; 25 | 26 | /// 27 | /// Gets or sets the Jwt bearer authentication scheme to use for validating access tokens for this 28 | /// instance of Azure Active Directory Bearer authentication. 29 | /// 30 | public string JwtBearerSchemeName { get; internal set; } 31 | 32 | /// 33 | /// Gets or sets the client Id. 34 | /// 35 | public string ClientId { get; set; } 36 | 37 | /// 38 | /// Gets or sets the client secret. 39 | /// 40 | public string ClientSecret { get; set; } 41 | 42 | /// 43 | /// Gets or sets the tenant Id. 44 | /// 45 | public string TenantId { get; set; } 46 | 47 | /// 48 | /// Gets or sets the Azure Active Directory instance. 49 | /// 50 | public string Instance { get; set; } 51 | 52 | /// 53 | /// Gets or sets the domain of the Azure Active Directory tennant. 54 | /// 55 | public string Domain { get; set; } 56 | 57 | /// 58 | /// Gets or sets the sign in callback path. 59 | /// 60 | public string CallbackPath { get; set; } 61 | 62 | /// 63 | /// Gets or sets the sign out callback path. 64 | /// 65 | public string SignedOutCallbackPath { get; set; } 66 | 67 | /// 68 | /// Gets all the underlying authentication schemes. 69 | /// 70 | public string[] AllSchemes => new[] { CookieSchemeName, OpenIdConnectSchemeName }; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.Extensions.Options; 5 | 6 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 7 | { 8 | internal class AzureADOptionsConfiguration : IConfigureNamedOptions 9 | { 10 | private readonly IOptions _schemeOptions; 11 | 12 | public AzureADOptionsConfiguration(IOptions schemeOptions) 13 | { 14 | _schemeOptions = schemeOptions; 15 | } 16 | 17 | public void Configure(string name, AzureADOptions options) 18 | { 19 | // This can be called because of someone configuring JWT or someone configuring 20 | // Open ID + Cookie. 21 | if (_schemeOptions.Value.OpenIDMappings.TryGetValue(name, out var webMapping)) 22 | { 23 | options.OpenIdConnectSchemeName = webMapping.OpenIdConnectScheme; 24 | options.CookieSchemeName = webMapping.CookieScheme; 25 | return; 26 | } 27 | if (_schemeOptions.Value.JwtBearerMappings.TryGetValue(name, out var mapping)) 28 | { 29 | options.JwtBearerSchemeName = mapping.JwtBearerScheme; 30 | return; 31 | } 32 | } 33 | 34 | public void Configure(AzureADOptions options) 35 | { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/AzureADSchemeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 7 | { 8 | internal class AzureADSchemeOptions 9 | { 10 | public IDictionary OpenIDMappings { get; set; } = new Dictionary(); 11 | 12 | public IDictionary JwtBearerMappings { get; set; } = new Dictionary(); 13 | 14 | public class AzureADOpenIDSchemeMapping 15 | { 16 | public string OpenIdConnectScheme { get; set; } 17 | public string CookieScheme { get; set; } 18 | } 19 | 20 | public class JwtBearerSchemeMapping 21 | { 22 | public string JwtBearerScheme { get; set; } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/CookieOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authentication.Cookies; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 8 | { 9 | internal class CookieOptionsConfiguration : IConfigureNamedOptions 10 | { 11 | private readonly IOptions _schemeOptions; 12 | private readonly IOptionsMonitor _AzureADOptions; 13 | 14 | public CookieOptionsConfiguration(IOptions schemeOptions, IOptionsMonitor AzureADOptions) 15 | { 16 | _schemeOptions = schemeOptions; 17 | _AzureADOptions = AzureADOptions; 18 | } 19 | 20 | public void Configure(string name, CookieAuthenticationOptions options) 21 | { 22 | var AzureADScheme = GetAzureADScheme(name); 23 | var AzureADOptions = _AzureADOptions.Get(AzureADScheme); 24 | if (name != AzureADOptions.CookieSchemeName) 25 | { 26 | return; 27 | } 28 | 29 | options.LoginPath = $"/AzureAD/Account/SignIn/{AzureADScheme}"; 30 | options.LogoutPath = $"/AzureAD/Account/SignOut/{AzureADScheme}"; 31 | options.AccessDeniedPath = "/AzureAD/Account/AccessDenied"; 32 | } 33 | 34 | public void Configure(CookieAuthenticationOptions options) 35 | { 36 | } 37 | 38 | private string GetAzureADScheme(string name) 39 | { 40 | foreach (var mapping in _schemeOptions.Value.OpenIDMappings) 41 | { 42 | if (mapping.Value.OpenIdConnectScheme == name) 43 | { 44 | return mapping.Key; 45 | } 46 | } 47 | 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/JwtBearerOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Authentication.AzureAD.UI; 6 | using Microsoft.AspNetCore.Authentication.JwtBearer; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.AspNetCore.Authentication 10 | { 11 | internal class JwtBearerOptionsConfiguration : IConfigureNamedOptions 12 | { 13 | private readonly IOptions _schemeOptions; 14 | private readonly IOptionsMonitor _azureADOptions; 15 | 16 | public JwtBearerOptionsConfiguration( 17 | IOptions schemeOptions, 18 | IOptionsMonitor azureADOptions) 19 | { 20 | _schemeOptions = schemeOptions; 21 | _azureADOptions = azureADOptions; 22 | } 23 | 24 | public void Configure(string name, JwtBearerOptions options) 25 | { 26 | var azureADScheme = GetAzureADScheme(name); 27 | var azureADOptions = _azureADOptions.Get(azureADScheme); 28 | if (name != azureADOptions.JwtBearerSchemeName) 29 | { 30 | return; 31 | } 32 | 33 | options.Audience = azureADOptions.ClientId; 34 | options.Authority = new Uri(new Uri(azureADOptions.Instance), azureADOptions.TenantId).ToString(); 35 | } 36 | 37 | public void Configure(JwtBearerOptions options) 38 | { 39 | } 40 | 41 | private string GetAzureADScheme(string name) 42 | { 43 | foreach (var mapping in _schemeOptions.Value.JwtBearerMappings) 44 | { 45 | if (mapping.Value.JwtBearerScheme == name) 46 | { 47 | return mapping.Key; 48 | } 49 | } 50 | 51 | return null; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Microsoft.AspNetCore.Authentication.AzureAD.UI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ASP.NET Core Azure Active Directory Integration provides components for easily integrating Azure Active Directory authentication within your ASP.NET Core application. 5 | Precompiled views assembly for the ASP.NET Core Azure Active Directory Integration package. 6 | netcoreapp3.0 7 | aspnetcore;authentication;AzureAD 8 | true 9 | Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory, Microsoft.AspNetCore.Mvc.Core 10 | 11 | <_EnableAllInclusiveRazorSdk>true 12 | 3.0 13 | MVC-3.0 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <_Parameter1>BuildNumber 27 | <_Parameter2>$(BuildNumber) 28 | 29 | 30 | 31 | <_Parameter1>BuildNumber 32 | <_Parameter2>$(BuildNumber) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/OpenIdConnectOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI 9 | { 10 | internal class OpenIdConnectOptionsConfiguration : IConfigureNamedOptions 11 | { 12 | private readonly IOptions _schemeOptions; 13 | private readonly IOptionsMonitor _azureADOptions; 14 | 15 | public OpenIdConnectOptionsConfiguration(IOptions schemeOptions, IOptionsMonitor azureADOptions) 16 | { 17 | _schemeOptions = schemeOptions; 18 | _azureADOptions = azureADOptions; 19 | } 20 | 21 | public void Configure(string name, OpenIdConnectOptions options) 22 | { 23 | var azureADScheme = GetAzureADScheme(name); 24 | var azureADOptions = _azureADOptions.Get(azureADScheme); 25 | if (name != azureADOptions.OpenIdConnectSchemeName) 26 | { 27 | return; 28 | } 29 | 30 | options.ClientId = azureADOptions.ClientId; 31 | options.ClientSecret = azureADOptions.ClientSecret; 32 | options.Authority = new Uri(new Uri(azureADOptions.Instance), azureADOptions.TenantId).ToString(); 33 | options.CallbackPath = azureADOptions.CallbackPath ?? options.CallbackPath; 34 | options.SignedOutCallbackPath = azureADOptions.SignedOutCallbackPath ?? options.SignedOutCallbackPath; 35 | options.SignInScheme = azureADOptions.CookieSchemeName; 36 | options.UseTokenLifetime = true; 37 | } 38 | 39 | private string GetAzureADScheme(string name) 40 | { 41 | foreach (var mapping in _schemeOptions.Value.OpenIDMappings) 42 | { 43 | if (mapping.Value.OpenIdConnectScheme == name) 44 | { 45 | return mapping.Key; 46 | } 47 | } 48 | 49 | return null; 50 | } 51 | 52 | public void Configure(OpenIdConnectOptions options) 53 | { 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureAD.UI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Authentication.AzureAD.UI.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Options; 9 | 10 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI.AzureADB2C.Controllers.Internal 11 | { 12 | [NonController] 13 | [AllowAnonymous] 14 | [Area("AzureADB2C")] 15 | [Route("[area]/[controller]/[action]")] 16 | internal class AccountController : Controller 17 | { 18 | private readonly IOptionsMonitor _options; 19 | 20 | public AccountController(IOptionsMonitor AzureADB2COptions) 21 | { 22 | _options = AzureADB2COptions; 23 | } 24 | 25 | [HttpGet("{scheme?}")] 26 | public IActionResult SignIn([FromRoute] string scheme) 27 | { 28 | scheme = scheme ?? AzureADB2CDefaults.AuthenticationScheme; 29 | var redirectUrl = Url.Content("~/"); 30 | return Challenge( 31 | new AuthenticationProperties { RedirectUri = redirectUrl }, 32 | scheme); 33 | } 34 | 35 | [HttpGet("{scheme?}")] 36 | public IActionResult ResetPassword([FromRoute] string scheme) 37 | { 38 | scheme = scheme ?? AzureADB2CDefaults.AuthenticationScheme; 39 | var options = _options.Get(scheme); 40 | 41 | var redirectUrl = Url.Content("~/"); 42 | var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; 43 | properties.Items[AzureADB2CDefaults.PolicyKey] = options.ResetPasswordPolicyId; 44 | return Challenge(properties, scheme); 45 | } 46 | 47 | [HttpGet("{scheme?}")] 48 | public async Task EditProfile([FromRoute] string scheme) 49 | { 50 | scheme = scheme ?? AzureADB2CDefaults.AuthenticationScheme; 51 | var authenticated = await HttpContext.AuthenticateAsync(scheme); 52 | if (!authenticated.Succeeded) 53 | { 54 | return Challenge(scheme); 55 | } 56 | 57 | var options = _options.Get(scheme); 58 | 59 | var redirectUrl = Url.Content("~/"); 60 | var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; 61 | properties.Items[AzureADB2CDefaults.PolicyKey] = options.EditProfilePolicyId; 62 | return Challenge(properties, scheme); 63 | } 64 | 65 | [HttpGet("{scheme?}")] 66 | public async Task SignOut([FromRoute] string scheme) 67 | { 68 | scheme = scheme ?? AzureADB2CDefaults.AuthenticationScheme; 69 | var authenticated = await HttpContext.AuthenticateAsync(scheme); 70 | if (!authenticated.Succeeded) 71 | { 72 | return Challenge(scheme); 73 | } 74 | 75 | var options = _options.Get(scheme); 76 | 77 | var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme); 78 | return SignOut( 79 | new AuthenticationProperties { RedirectUri = callbackUrl }, 80 | options.AllSchemes); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/AccessDenied.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AccessDeniedModel 3 | @{ 4 | ViewData["Title"] = "Access denied"; 5 | } 6 | 7 |
    8 |

    @ViewData["Title"]

    9 |

    You do not have access to this resource.

    10 |
    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/AccessDenied.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Internal 8 | { 9 | /// 10 | /// This API supports infrastructure and is not intended to be used 11 | /// directly from your code.This API may change or be removed in future releases 12 | /// 13 | [AllowAnonymous] 14 | public class AccessDeniedModel : PageModel 15 | { 16 | /// 17 | /// This API supports infrastructure and is not intended to be used 18 | /// directly from your code.This API may change or be removed in future releases 19 | /// 20 | public void OnGet() 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

    Error.

    8 |

    An error occurred while processing your request.

    9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

    13 | Request ID: @Model.RequestId 14 |

    15 | } 16 | 17 |

    Development Mode

    18 |

    19 | Swapping to Development environment will display more detailed information about the error that occurred. 20 |

    21 |

    22 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 23 |

    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Diagnostics; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Internal 10 | { 11 | /// 12 | /// This API supports infrastructure and is not intended to be used 13 | /// directly from your code.This API may change or be removed in future releases 14 | /// 15 | [AllowAnonymous] 16 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 17 | public class ErrorModel : PageModel 18 | { 19 | /// 20 | /// This API supports infrastructure and is not intended to be used 21 | /// directly from your code.This API may change or be removed in future releases 22 | /// 23 | public string RequestId { get; set; } 24 | 25 | /// 26 | /// This API supports infrastructure and is not intended to be used 27 | /// directly from your code.This API may change or be removed in future releases 28 | /// 29 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 30 | 31 | /// 32 | /// This API supports infrastructure and is not intended to be used 33 | /// directly from your code.This API may change or be removed in future releases 34 | /// 35 | public void OnGet() 36 | { 37 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/SignedOut.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model SignedOutModel 3 | @{ 4 | ViewData["Title"] = "Signed out"; 5 | } 6 | 7 |

    @ViewData["Title"]

    8 |

    9 | You have successfully signed out. 10 |

    -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/SignedOut.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Internal 9 | { 10 | /// 11 | /// This API supports infrastructure and is not intended to be used 12 | /// directly from your code.This API may change or be removed in future releases 13 | /// 14 | [AllowAnonymous] 15 | public class SignedOutModel : PageModel 16 | { 17 | /// 18 | /// This API supports infrastructure and is not intended to be used 19 | /// directly from your code.This API may change or be removed in future releases 20 | /// 21 | public IActionResult OnGet() 22 | { 23 | if (User.Identity.IsAuthenticated) 24 | { 25 | return LocalRedirect("~/"); 26 | } 27 | 28 | return Page(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/Account/_viewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Internal 2 | @namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Pages.Internal -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Areas/AzureADB2C/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Hosting 2 | @using Microsoft.AspNetCore.Mvc.ViewEngines 3 | 4 | @inject IHostingEnvironment Environment 5 | @inject ICompositeViewEngine Engine 6 | 7 | @{ 8 | var result = Engine.FindView(ViewContext, "_Layout", isMainPage: false); 9 | if (result.Success) 10 | { 11 | Layout = "_Layout"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureADB2CAccountControllerFeatureProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using Microsoft.AspNetCore.Authentication.AzureADB2C.UI.AzureADB2C.Controllers.Internal; 7 | using Microsoft.AspNetCore.Mvc.ApplicationParts; 8 | using Microsoft.AspNetCore.Mvc.Controllers; 9 | 10 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 11 | { 12 | internal class AzureADB2CAccountControllerFeatureProvider : IApplicationFeatureProvider, IApplicationFeatureProvider 13 | { 14 | public void PopulateFeature(IEnumerable parts, ControllerFeature feature) 15 | { 16 | if (!feature.Controllers.Contains(typeof(AccountController).GetTypeInfo())) 17 | { 18 | feature.Controllers.Add(typeof(AccountController).GetTypeInfo()); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureAdB2CDefaults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | 5 | using Microsoft.AspNetCore.Authentication; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 8 | { 9 | /// 10 | /// Constants for different Azure Active Directory B2C authentication components. 11 | /// 12 | public static class AzureADB2CDefaults 13 | { 14 | /// 15 | /// The key for the policy used in . 16 | /// 17 | public static readonly string PolicyKey = "Policy"; 18 | 19 | /// 20 | /// The scheme name for Open ID Connect when using 21 | /// . 22 | /// 23 | public static readonly string OpenIdScheme = "AzureADB2COpenID"; 24 | 25 | /// 26 | /// The scheme name for cookies when using 27 | /// . 28 | /// 29 | public static readonly string CookieScheme = "AzureADB2CCookie"; 30 | 31 | /// 32 | /// The default scheme for Azure Active Directory B2C Bearer. 33 | /// 34 | public static readonly string BearerAuthenticationScheme = "AzureADB2CBearer"; 35 | 36 | /// 37 | /// The scheme name for JWT Bearer when using 38 | /// . 39 | /// 40 | public static readonly string JwtBearerAuthenticationScheme = "AzureADB2CJwtBearer"; 41 | 42 | /// 43 | /// The default scheme for Azure Active Directory B2C. 44 | /// 45 | public static readonly string AuthenticationScheme = "AzureADB2C"; 46 | 47 | /// 48 | /// The display name for Azure Active Directory B2C. 49 | /// 50 | public static readonly string DisplayName = "Azure Active Directory B2C"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureAdB2COpenIDConnectEventHandlers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Authentication; 8 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 9 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 10 | 11 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 12 | { 13 | internal class AzureADB2COpenIDConnectEventHandlers 14 | { 15 | private IDictionary _policyToIssuerAddress = 16 | new Dictionary(StringComparer.OrdinalIgnoreCase); 17 | 18 | public AzureADB2COpenIDConnectEventHandlers(string schemeName, AzureADB2COptions options) 19 | { 20 | SchemeName = schemeName; 21 | Options = options; 22 | } 23 | 24 | public string SchemeName { get; } 25 | 26 | public AzureADB2COptions Options { get; } 27 | 28 | public Task OnRedirectToIdentityProvider(RedirectContext context) 29 | { 30 | var defaultPolicy = Options.DefaultPolicy; 31 | if (context.Properties.Items.TryGetValue(AzureADB2CDefaults.PolicyKey, out var policy) && 32 | !string.IsNullOrEmpty(policy) && 33 | !string.Equals(policy, defaultPolicy, StringComparison.OrdinalIgnoreCase)) 34 | { 35 | context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile; 36 | context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken; 37 | context.ProtocolMessage.IssuerAddress = BuildIssuerAddress(context, defaultPolicy, policy); 38 | context.Properties.Items.Remove(AzureADB2CDefaults.PolicyKey); 39 | } 40 | 41 | return Task.CompletedTask; 42 | } 43 | 44 | private string BuildIssuerAddress(RedirectContext context, string defaultPolicy, string policy) 45 | { 46 | if (!_policyToIssuerAddress.TryGetValue(policy, out var issuerAddress)) 47 | { 48 | _policyToIssuerAddress[policy] = context.ProtocolMessage.IssuerAddress.ToLowerInvariant() 49 | .Replace($"/{defaultPolicy.ToLowerInvariant()}/", $"/{policy.ToLowerInvariant()}/"); 50 | } 51 | 52 | return _policyToIssuerAddress[policy]; 53 | } 54 | 55 | public Task OnRemoteFailure(RemoteFailureContext context) 56 | { 57 | context.HandleResponse(); 58 | // Handle the error code that Azure Active Directory B2C throws when trying to reset a password from the login page 59 | // because password reset is not supported by a "sign-up or sign-in policy". 60 | // Below is a sample error message: 61 | // 'access_denied', error_description: 'AADB2C90118: The user has forgotten their password. 62 | // Correlation ID: f99deff4-f43b-43cc-b4e7-36141dbaf0a0 63 | // Timestamp: 2018-03-05 02:49:35Z 64 | //', error_uri: 'error_uri is null'. 65 | if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118")) 66 | { 67 | // If the user clicked the reset password link, redirect to the reset password route 68 | context.Response.Redirect($"/AzureADB2C/Account/ResetPassword/{SchemeName}"); 69 | } 70 | // Access denied errors happen when a user cancels an action on the Azure Active Directory B2C UI. We just redirect back to 71 | // the main page in that case. 72 | // Message contains error: 'access_denied', error_description: 'AADB2C90091: The user has cancelled entering self-asserted information. 73 | // Correlation ID: d01c8878-0732-4eb2-beb8-da82a57432e0 74 | // Timestamp: 2018-03-05 02:56:49Z 75 | // ', error_uri: 'error_uri is null'. 76 | else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied")) 77 | { 78 | context.Response.Redirect("/"); 79 | } 80 | else 81 | { 82 | context.Response.Redirect("/AzureADB2C/Account/Error"); 83 | } 84 | 85 | return Task.CompletedTask; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureAdB2COptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authentication.Cookies; 5 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 8 | { 9 | /// 10 | /// Options for configuring authentication using Azure Active Directory B2C. 11 | /// 12 | public class AzureADB2COptions 13 | { 14 | /// 15 | /// Gets or sets the OpenID Connect authentication scheme to use for authentication with this instance 16 | /// of Azure Active Directory B2C authentication. 17 | /// 18 | public string OpenIdConnectSchemeName { get; set; } = OpenIdConnectDefaults.AuthenticationScheme; 19 | 20 | /// 21 | /// Gets or sets the Cookie authentication scheme to use for sign in with this instance of 22 | /// Azure Active Directory B2C authentication. 23 | /// 24 | public string CookieSchemeName { get; set; } = CookieAuthenticationDefaults.AuthenticationScheme; 25 | 26 | /// 27 | /// Gets or sets the Jwt bearer authentication scheme to use for validating access tokens for this 28 | /// instance of Azure Active Directory B2C Bearer authentication. 29 | /// 30 | public string JwtBearerSchemeName { get; internal set; } 31 | 32 | 33 | /// 34 | /// Gets or sets the client Id. 35 | /// 36 | public string ClientId { get; set; } 37 | 38 | /// 39 | /// Gets or sets the client secret. 40 | /// 41 | public string ClientSecret { get; set; } 42 | 43 | /// 44 | /// Gets or sets the Azure Active Directory B2C instance. 45 | /// 46 | public string Instance { get; set; } 47 | 48 | /// 49 | /// Gets or sets the domain of the Azure Active Directory B2C tennant. 50 | /// 51 | public string Domain { get; set; } 52 | 53 | /// 54 | /// Gets or sets the edit profile policy name. 55 | /// 56 | public string EditProfilePolicyId { get; set; } 57 | 58 | /// 59 | /// Gets or sets the sign up or sign in policy name. 60 | /// 61 | public string SignUpSignInPolicyId { get; set; } 62 | 63 | /// 64 | /// Gets or sets the reset password policy id. 65 | /// 66 | public string ResetPasswordPolicyId { get; set; } 67 | 68 | /// 69 | /// Gets or sets the sign in callback path. 70 | /// 71 | public string CallbackPath { get; set; } 72 | 73 | /// 74 | /// Gets or sets the sign out callback path. 75 | /// 76 | public string SignedOutCallbackPath { get; set; } 77 | 78 | /// 79 | /// Gets or sets the default policy. 80 | /// 81 | public string DefaultPolicy => SignUpSignInPolicyId; 82 | 83 | /// 84 | /// Gets all the underlying authentication schemes. 85 | /// 86 | public string[] AllSchemes => new[] { CookieSchemeName, OpenIdConnectSchemeName }; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureAdB2COptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.Extensions.Options; 5 | 6 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 7 | { 8 | internal class AzureADB2COptionsConfiguration : IConfigureNamedOptions 9 | { 10 | private readonly IOptions _schemeOptions; 11 | 12 | public AzureADB2COptionsConfiguration(IOptions schemeOptions) 13 | { 14 | _schemeOptions = schemeOptions; 15 | } 16 | 17 | public void Configure(string name, AzureADB2COptions options) 18 | { 19 | // This can be called because of someone configuring JWT or someone configuring 20 | // Open ID + Cookie. 21 | if (_schemeOptions.Value.OpenIDMappings.TryGetValue(name, out var webMapping)) 22 | { 23 | options.OpenIdConnectSchemeName = webMapping.OpenIdConnectScheme; 24 | options.CookieSchemeName = webMapping.CookieScheme; 25 | return; 26 | } 27 | if (_schemeOptions.Value.JwtBearerMappings.TryGetValue(name, out var mapping)) 28 | { 29 | options.JwtBearerSchemeName = mapping.JwtBearerScheme; 30 | return; 31 | } 32 | } 33 | 34 | public void Configure(AzureADB2COptions options) 35 | { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/AzureAdB2CSchemeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 7 | { 8 | internal class AzureADB2CSchemeOptions 9 | { 10 | public IDictionary OpenIDMappings { get; set; } = new Dictionary(); 11 | 12 | public IDictionary JwtBearerMappings { get; set; } = new Dictionary(); 13 | 14 | public class AzureADB2COpenIDSchemeMapping 15 | { 16 | public string OpenIdConnectScheme { get; set; } 17 | public string CookieScheme { get; set; } 18 | } 19 | 20 | public class JwtBearerSchemeMapping 21 | { 22 | public string JwtBearerScheme { get; set; } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/CookieOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authentication.Cookies; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 8 | { 9 | internal class CookieOptionsConfiguration : IConfigureNamedOptions 10 | { 11 | private readonly IOptions _schemeOptions; 12 | private readonly IOptionsMonitor _azureADB2COptions; 13 | 14 | public CookieOptionsConfiguration(IOptions schemeOptions, IOptionsMonitor azureADB2COptions) 15 | { 16 | _schemeOptions = schemeOptions; 17 | _azureADB2COptions = azureADB2COptions; 18 | } 19 | 20 | public void Configure(string name, CookieAuthenticationOptions options) 21 | { 22 | var azureADB2CScheme = GetAzureADB2CScheme(name); 23 | var azureADB2COptions = _azureADB2COptions.Get(azureADB2CScheme); 24 | if (name != azureADB2COptions.CookieSchemeName) 25 | { 26 | return; 27 | } 28 | 29 | options.LoginPath = $"/AzureADB2C/Account/SignIn/{azureADB2CScheme}"; 30 | options.LogoutPath = $"/AzureADB2C/Account/SignOut/{azureADB2CScheme}"; 31 | options.AccessDeniedPath = "/AzureADB2C/Account/AccessDenied"; 32 | } 33 | 34 | public void Configure(CookieAuthenticationOptions options) 35 | { 36 | } 37 | 38 | private string GetAzureADB2CScheme(string name) 39 | { 40 | foreach (var mapping in _schemeOptions.Value.OpenIDMappings) 41 | { 42 | if (mapping.Value.OpenIdConnectScheme == name) 43 | { 44 | return mapping.Key; 45 | } 46 | } 47 | 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/JwtBearerOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authentication.JwtBearer; 5 | using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Authentication 9 | { 10 | internal class JwtBearerOptionsConfiguration : IConfigureNamedOptions 11 | { 12 | private readonly IOptions _schemeOptions; 13 | private readonly IOptionsMonitor _azureADB2COptions; 14 | 15 | public JwtBearerOptionsConfiguration( 16 | IOptions schemeOptions, 17 | IOptionsMonitor azureADB2COptions) 18 | { 19 | _schemeOptions = schemeOptions; 20 | _azureADB2COptions = azureADB2COptions; 21 | } 22 | 23 | public void Configure(string name, JwtBearerOptions options) 24 | { 25 | var azureADB2CScheme = GetAzureADB2CScheme(name); 26 | var azureADB2COptions = _azureADB2COptions.Get(azureADB2CScheme); 27 | if (name != azureADB2COptions.JwtBearerSchemeName) 28 | { 29 | return; 30 | } 31 | 32 | options.Audience = azureADB2COptions.ClientId; 33 | options.Authority = OpenIdConnectOptionsConfiguration.BuildAuthority(azureADB2COptions); 34 | } 35 | 36 | public void Configure(JwtBearerOptions options) 37 | { 38 | } 39 | 40 | private string GetAzureADB2CScheme(string name) 41 | { 42 | foreach (var mapping in _schemeOptions.Value.JwtBearerMappings) 43 | { 44 | if (mapping.Value.JwtBearerScheme == name) 45 | { 46 | return mapping.Key; 47 | } 48 | } 49 | 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ASP.NET Core Azure Active Directory B2C Integration provides components for easily integrating Azure Active Directory B2C authentication within your ASP.NET Core application. 5 | Precompiled views assembly for the ASP.NET Core Azure Active Directory B2C Integration package. 6 | netcoreapp3.0 7 | aspnetcore;authentication;AzureADB2C 8 | true 9 | Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory, Microsoft.AspNetCore.Mvc.Core 10 | 11 | <_EnableAllInclusiveRazorSdk>true 12 | 3.0 13 | MVC-3.0 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <_Parameter1>BuildNumber 27 | <_Parameter2>$(BuildNumber) 28 | 29 | 30 | 31 | <_Parameter1>BuildNumber 32 | <_Parameter2>$(BuildNumber) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/OpenIdConnectOptionsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.Extensions.Options; 8 | using Microsoft.IdentityModel.Tokens; 9 | 10 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 11 | { 12 | internal class OpenIdConnectOptionsConfiguration : IConfigureNamedOptions 13 | { 14 | private readonly IOptions _schemeOptions; 15 | private readonly IOptionsMonitor _azureADB2COptions; 16 | 17 | public OpenIdConnectOptionsConfiguration(IOptions schemeOptions, IOptionsMonitor azureADB2COptions) 18 | { 19 | _schemeOptions = schemeOptions; 20 | _azureADB2COptions = azureADB2COptions; 21 | } 22 | 23 | public void Configure(string name, OpenIdConnectOptions options) 24 | { 25 | var azureADB2CScheme = GetAzureADB2CScheme(name); 26 | var azureADB2COptions = _azureADB2COptions.Get(azureADB2CScheme); 27 | if (name != azureADB2COptions.OpenIdConnectSchemeName) 28 | { 29 | return; 30 | } 31 | 32 | options.ClientId = azureADB2COptions.ClientId; 33 | options.ClientSecret = azureADB2COptions.ClientSecret; 34 | options.Authority = BuildAuthority(azureADB2COptions); 35 | options.CallbackPath = azureADB2COptions.CallbackPath ?? options.CallbackPath; 36 | options.SignedOutCallbackPath = azureADB2COptions.SignedOutCallbackPath ?? options.SignedOutCallbackPath; 37 | options.SignInScheme = azureADB2COptions.CookieSchemeName; 38 | options.UseTokenLifetime = true; 39 | options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }; 40 | 41 | var handlers = new AzureADB2COpenIDConnectEventHandlers(azureADB2CScheme, azureADB2COptions); 42 | options.Events = new OpenIdConnectEvents 43 | { 44 | OnRedirectToIdentityProvider = handlers.OnRedirectToIdentityProvider, 45 | OnRemoteFailure = handlers.OnRemoteFailure 46 | }; 47 | } 48 | 49 | internal static string BuildAuthority(AzureADB2COptions AzureADB2COptions) 50 | { 51 | var baseUri = new Uri(AzureADB2COptions.Instance); 52 | var pathBase = baseUri.PathAndQuery.TrimEnd('/'); 53 | var domain = AzureADB2COptions.Domain; 54 | var policy = AzureADB2COptions.DefaultPolicy; 55 | 56 | return new Uri(baseUri, new PathString($"{pathBase}/{domain}/{policy}/v2.0")).ToString(); 57 | } 58 | 59 | private string GetAzureADB2CScheme(string name) 60 | { 61 | foreach (var mapping in _schemeOptions.Value.OpenIDMappings) 62 | { 63 | if (mapping.Value.OpenIdConnectScheme == name) 64 | { 65 | return mapping.Key; 66 | } 67 | } 68 | 69 | return null; 70 | } 71 | 72 | public void Configure(OpenIdConnectOptions options) 73 | { 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Authentication.AzureADB2C.UI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -------------------------------------------------------------------------------- /test/AADIntegration.ruleset: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | xUnit1026:$(WarningsNotAsErrors) 7 | $(MSBuildThisFileDirectory)AADIntegration.ruleset 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests/ApiAuthenticationTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Net; 5 | using System.Threading.Tasks; 6 | using AzureAD.WebSite; 7 | using Microsoft.AspNetCore.Authentication.AzureAD.UI; 8 | using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; 9 | using Microsoft.AspNetCore.Authentication.JwtBearer; 10 | using Microsoft.AspNetCore.Mvc.Testing; 11 | using Microsoft.AspNetCore.TestHost; 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 14 | using Xunit; 15 | 16 | namespace Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests 17 | { 18 | public class ApiAuthenticationTests : IClassFixture> 19 | { 20 | public ApiAuthenticationTests(WebApplicationFactory fixture) 21 | { 22 | Factory = fixture; 23 | } 24 | 25 | public WebApplicationFactory Factory { get; } 26 | 27 | [Fact] 28 | public async Task BearerAzureAD_Challenges_UnauthorizedRequests() 29 | { 30 | // Arrange 31 | var client = Factory.WithWebHostBuilder(builder => builder.ConfigureTestServices( 32 | services => 33 | { 34 | services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme) 35 | .AddAzureADBearer(o => 36 | { 37 | o.Instance = "https://login.microsoftonline.com/"; 38 | o.Domain = "test.onmicrosoft.com"; 39 | o.ClientId = "ClientId"; 40 | o.TenantId = "TenantId"; 41 | }); 42 | 43 | services.Configure(AzureADDefaults.JwtBearerAuthenticationScheme, o => 44 | { 45 | o.Configuration = new OpenIdConnectConfiguration() 46 | { 47 | Issuer = "https://www.example.com", 48 | }; 49 | }); 50 | })).CreateDefaultClient(); 51 | 52 | // Act 53 | var response = await client.GetAsync("/api/get"); 54 | 55 | // Assert 56 | Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); 57 | } 58 | 59 | [Fact] 60 | public async Task BearerAzureADB2C_Challenges_UnauthorizedRequests() 61 | { 62 | // Arrange 63 | var client = Factory.WithWebHostBuilder(builder => builder.ConfigureTestServices( 64 | services => 65 | { 66 | services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme) 67 | .AddAzureADB2CBearer(o => 68 | { 69 | o.Instance = "https://login.microsoftonline.com/"; 70 | o.Domain = "test.onmicrosoft.com"; 71 | o.ClientId = "ClientId"; 72 | o.SignUpSignInPolicyId = "B2c_1_SiSu"; 73 | }); 74 | 75 | services.Configure(AzureADB2CDefaults.JwtBearerAuthenticationScheme, o => 76 | { 77 | o.Configuration = new OpenIdConnectConfiguration() 78 | { 79 | Issuer = "https://www.example.com", 80 | }; 81 | }); 82 | })).CreateDefaultClient(); 83 | 84 | // Act 85 | var response = await client.GetAsync("/api/get"); 86 | 87 | // Assert 88 | Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests/Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests/WebAuthenticationTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Net; 5 | using System.Threading.Tasks; 6 | using AzureAD.WebSite; 7 | using Microsoft.AspNetCore.Authentication.AzureAD.UI; 8 | using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; 9 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 10 | using Microsoft.AspNetCore.Authorization; 11 | using Microsoft.AspNetCore.Mvc.Authorization; 12 | using Microsoft.AspNetCore.Mvc.Testing; 13 | using Microsoft.AspNetCore.TestHost; 14 | using Microsoft.Extensions.DependencyInjection; 15 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 16 | using Xunit; 17 | 18 | namespace Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests 19 | { 20 | public class WebAuthenticationTests : IClassFixture> 21 | { 22 | public WebAuthenticationTests(WebApplicationFactory fixture) 23 | { 24 | Factory = fixture; 25 | } 26 | 27 | public WebApplicationFactory Factory { get; } 28 | 29 | public static TheoryData NotAddedEndpoints => 30 | new TheoryData() 31 | { 32 | "/AzureAD/Account/AccessDenied", 33 | "/AzureAD/Account/Error", 34 | "/AzureAD/Account/SignedOut", 35 | "/AzureAD/Account/SignIn", 36 | "/AzureAD/Account/SignOut", 37 | "/AzureADB2C/Account/AccessDenied", 38 | "/AzureADB2C/Account/Error", 39 | "/AzureADB2C/Account/SignedOut", 40 | "/AzureADB2C/Account/SignIn", 41 | "/AzureADB2C/Account/ResetPassword", 42 | "/AzureADB2C/Account/EditProfile", 43 | "/AzureADB2C/Account/SignOut", 44 | }; 45 | 46 | [Theory] 47 | [MemberData(nameof(NotAddedEndpoints))] 48 | public async Task Endpoints_NotAvailable_When_Authentication_NotAdded(string endpoint) 49 | { 50 | // Act & Assert 51 | var response = await Factory.CreateDefaultClient().GetAsync(endpoint); 52 | 53 | // Assert 54 | Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); 55 | } 56 | 57 | public static TheoryData AddedEndpointsStatusCodesAD => 58 | new TheoryData() 59 | { 60 | { "/AzureAD/Account/AccessDenied", HttpStatusCode.OK }, 61 | { "/AzureAD/Account/Error", HttpStatusCode.OK }, 62 | { "/AzureAD/Account/SignedOut", HttpStatusCode.OK }, 63 | { "/AzureAD/Account/SignIn", HttpStatusCode.Redirect }, 64 | { "/AzureAD/Account/SignOut", HttpStatusCode.Redirect }, 65 | }; 66 | 67 | [Theory] 68 | [MemberData(nameof(AddedEndpointsStatusCodesAD))] 69 | public async Task ADEndpoints_AreAvailable_When_Authentication_IsAdded(string endpoint, HttpStatusCode expectedStatusCode) 70 | { 71 | // Act & Assert 72 | var client = Factory.WithWebHostBuilder(builder => builder.ConfigureTestServices( 73 | services => 74 | { 75 | services 76 | .AddAuthentication(AzureADDefaults.AuthenticationScheme) 77 | .AddAzureAD(o => 78 | { 79 | o.Instance = "https://login.microsoftonline.com/"; 80 | o.Domain = "test.onmicrosoft.com"; 81 | o.ClientId = "ClientId"; 82 | o.TenantId = "TenantId"; 83 | }); 84 | 85 | services.Configure(AzureADDefaults.OpenIdScheme, o => 86 | { 87 | o.Configuration = new OpenIdConnectConfiguration() 88 | { 89 | Issuer = "https://www.example.com", 90 | TokenEndpoint = "https://www.example.com/token", 91 | AuthorizationEndpoint = "https://www.example.com/authorize", 92 | EndSessionEndpoint = "https://www.example.com/logout" 93 | }; 94 | }); 95 | 96 | services.AddMvc(o => o.Filters.Add( 97 | new AuthorizeFilter(new AuthorizationPolicyBuilder(new[] { AzureADDefaults.AuthenticationScheme }) 98 | .RequireAuthenticatedUser().Build()))); 99 | })).CreateDefaultClient(); 100 | 101 | var response = await client.GetAsync(endpoint); 102 | 103 | // Assert 104 | Assert.Equal(expectedStatusCode, response.StatusCode); 105 | } 106 | 107 | public static TheoryData AddedEndpointsStatusCodesADB2C => 108 | new TheoryData() 109 | { 110 | { "/AzureADB2C/Account/AccessDenied", HttpStatusCode.OK }, 111 | { "/AzureADB2C/Account/Error", HttpStatusCode.OK }, 112 | { "/AzureADB2C/Account/SignedOut", HttpStatusCode.OK }, 113 | { "/AzureADB2C/Account/SignIn", HttpStatusCode.Redirect }, 114 | { "/AzureADB2C/Account/ResetPassword", HttpStatusCode.Redirect }, 115 | { "/AzureADB2C/Account/EditProfile", HttpStatusCode.Redirect }, 116 | { "/AzureADB2C/Account/SignOut", HttpStatusCode.Redirect } 117 | }; 118 | 119 | [Theory] 120 | [MemberData(nameof(AddedEndpointsStatusCodesADB2C))] 121 | public async Task ADB2CEndpoints_AreAvailable_When_Authentication_IsAdded(string endpoint, HttpStatusCode expectedStatusCode) 122 | { 123 | // Act & Assert 124 | var client = Factory.WithWebHostBuilder(builder => builder.ConfigureTestServices( 125 | services => 126 | { 127 | services 128 | .AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) 129 | .AddAzureADB2C(o => 130 | { 131 | o.Instance = "https://login.microsoftonline.com/tfp/"; 132 | o.ClientId = "ClientId"; 133 | o.CallbackPath = "/signin-oidc"; 134 | o.Domain = "test.onmicrosoft.com"; 135 | o.SignUpSignInPolicyId = "B2C_1_SiUpIn"; 136 | o.ResetPasswordPolicyId = "B2C_1_SSPR"; 137 | o.EditProfilePolicyId = "B2C_1_SiPe"; 138 | }); 139 | 140 | services.Configure(AzureADB2CDefaults.OpenIdScheme, o => 141 | { 142 | o.Configuration = new OpenIdConnectConfiguration() 143 | { 144 | Issuer = "https://www.example.com", 145 | TokenEndpoint = "https://www.example.com/token", 146 | AuthorizationEndpoint = "https://www.example.com/authorize", 147 | EndSessionEndpoint = "https://www.example.com/logout" 148 | }; 149 | }); 150 | 151 | services.AddMvc(o => o.Filters.Add( 152 | new AuthorizeFilter(new AuthorizationPolicyBuilder(new[] { AzureADB2CDefaults.AuthenticationScheme }) 153 | .RequireAuthenticatedUser().Build()))); 154 | })).CreateDefaultClient(); 155 | 156 | var response = await client.GetAsync(endpoint); 157 | 158 | // Assert 159 | Assert.Equal(expectedStatusCode, response.StatusCode); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.FunctionalTests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "shadowCopy": false 3 | } 4 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.UI.Test/Controllers/AccountControllerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Authentication; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.AspNetCore.Mvc.Abstractions; 11 | using Microsoft.AspNetCore.Mvc.RazorPages; 12 | using Microsoft.AspNetCore.Mvc.Routing; 13 | using Microsoft.AspNetCore.Routing; 14 | using Microsoft.Extensions.DependencyInjection; 15 | using Microsoft.Extensions.Options; 16 | using Moq; 17 | using Xunit; 18 | 19 | namespace Microsoft.AspNetCore.Authentication.AzureAD.UI.AzureAD.Controllers.Internal 20 | { 21 | public class AccountControllerTests 22 | { 23 | [Fact] 24 | public void SignInNoScheme_ChallengesAADAzureADDefaultScheme() 25 | { 26 | // Arrange 27 | var controller = new AccountController( 28 | new OptionsMonitor(AzureADDefaults.AuthenticationScheme, new AzureADOptions() 29 | { 30 | OpenIdConnectSchemeName = AzureADDefaults.OpenIdScheme, 31 | CookieSchemeName = AzureADDefaults.CookieScheme 32 | })) 33 | { 34 | Url = new TestUrlHelper("~/", "https://localhost/") 35 | }; 36 | 37 | // Act 38 | var result = controller.SignIn(null); 39 | 40 | // Assert 41 | var challenge = Assert.IsAssignableFrom(result); 42 | var challengedScheme = Assert.Single(challenge.AuthenticationSchemes); 43 | Assert.Equal(AzureADDefaults.AuthenticationScheme, challengedScheme); 44 | Assert.NotNull(challenge.Properties.RedirectUri); 45 | Assert.Equal("https://localhost/", challenge.Properties.RedirectUri); 46 | } 47 | 48 | [Fact] 49 | public void SignInProvidedScheme_ChallengesCustomScheme() 50 | { 51 | // Arrange 52 | var controller = new AccountController(new OptionsMonitor("Custom", new AzureADOptions())); 53 | controller.Url = new TestUrlHelper("~/", "https://localhost/"); 54 | 55 | // Act 56 | var result = controller.SignIn("Custom"); 57 | 58 | // Assert 59 | var challenge = Assert.IsAssignableFrom(result); 60 | var challengedScheme = Assert.Single(challenge.AuthenticationSchemes); 61 | Assert.Equal("Custom", challengedScheme); 62 | } 63 | 64 | private ClaimsPrincipal CreateAuthenticatedPrincipal(string scheme) => 65 | new ClaimsPrincipal(new ClaimsIdentity(scheme)); 66 | 67 | private static ControllerContext CreateControllerContext(ClaimsPrincipal principal = null) 68 | { 69 | principal = principal ?? new ClaimsPrincipal(new ClaimsIdentity()); 70 | var mock = new Mock(); 71 | mock.Setup(authS => authS.AuthenticateAsync(It.IsAny(), It.IsAny())) 72 | .ReturnsAsync( 73 | (ctx, scheme) => 74 | { 75 | if (principal.Identity.IsAuthenticated) 76 | { 77 | return AuthenticateResult.Success(new AuthenticationTicket(principal, scheme)); 78 | } 79 | else 80 | { 81 | return AuthenticateResult.NoResult(); 82 | } 83 | }); 84 | return new ControllerContext() 85 | { 86 | HttpContext = new DefaultHttpContext() 87 | { 88 | RequestServices = new ServiceCollection() 89 | .AddSingleton(mock.Object) 90 | .BuildServiceProvider() 91 | } 92 | }; 93 | } 94 | 95 | [Fact] 96 | public void SignOutNoScheme_SignsOutDefaultCookiesAndDefaultOpenIDConnectAADAzureADSchemesAsync() 97 | { 98 | // Arrange 99 | var options = new AzureADOptions() 100 | { 101 | CookieSchemeName = AzureADDefaults.CookieScheme, 102 | OpenIdConnectSchemeName = AzureADDefaults.OpenIdScheme 103 | }; 104 | 105 | var controllerContext = CreateControllerContext( 106 | CreateAuthenticatedPrincipal(AzureADDefaults.AuthenticationScheme)); 107 | 108 | var descriptor = new PageActionDescriptor() 109 | { 110 | AttributeRouteInfo = new AttributeRouteInfo() 111 | { 112 | Template = "/Account/SignedOut" 113 | } 114 | }; 115 | var controller = new AccountController(new OptionsMonitor(AzureADDefaults.AuthenticationScheme, options)) 116 | { 117 | Url = new TestUrlHelper( 118 | controllerContext.HttpContext, 119 | new RouteData(), 120 | descriptor, 121 | "/Account/SignedOut", 122 | "https://localhost/Account/SignedOut"), 123 | ControllerContext = new ControllerContext() 124 | { 125 | HttpContext = controllerContext.HttpContext 126 | } 127 | }; 128 | controller.Request.Scheme = "https"; 129 | 130 | // Act 131 | var result = controller.SignOut(null); 132 | 133 | // Assert 134 | var signOut = Assert.IsAssignableFrom(result); 135 | Assert.Equal(new[] { AzureADDefaults.CookieScheme, AzureADDefaults.OpenIdScheme }, signOut.AuthenticationSchemes); 136 | Assert.NotNull(signOut.Properties.RedirectUri); 137 | Assert.Equal("https://localhost/Account/SignedOut", signOut.Properties.RedirectUri); 138 | } 139 | 140 | [Fact] 141 | public void SignOutProvidedScheme_SignsOutCustomCookiesAndCustomOpenIDConnectAADAzureADSchemesAsync() 142 | { 143 | // Arrange 144 | var options = new AzureADOptions() 145 | { 146 | CookieSchemeName = "Cookie", 147 | OpenIdConnectSchemeName = "OpenID" 148 | }; 149 | 150 | var controllerContext = CreateControllerContext( 151 | CreateAuthenticatedPrincipal(AzureADDefaults.AuthenticationScheme)); 152 | var descriptor = new PageActionDescriptor() 153 | { 154 | AttributeRouteInfo = new AttributeRouteInfo() 155 | { 156 | Template = "/Account/SignedOut" 157 | } 158 | }; 159 | 160 | var controller = new AccountController(new OptionsMonitor("Custom", options)) 161 | { 162 | Url = new TestUrlHelper( 163 | controllerContext.HttpContext, 164 | new RouteData(), 165 | descriptor, 166 | "/Account/SignedOut", 167 | "https://localhost/Account/SignedOut"), 168 | ControllerContext = new ControllerContext() 169 | { 170 | HttpContext = controllerContext.HttpContext 171 | } 172 | }; 173 | controller.Request.Scheme = "https"; 174 | 175 | // Act 176 | var result = controller.SignOut("Custom"); 177 | 178 | // Assert 179 | var signOut = Assert.IsAssignableFrom(result); 180 | Assert.Equal(new[] { "Cookie", "OpenID" }, signOut.AuthenticationSchemes); 181 | } 182 | 183 | private class OptionsMonitor : IOptionsMonitor 184 | { 185 | public OptionsMonitor(string scheme, AzureADOptions options) 186 | { 187 | Scheme = scheme; 188 | Options = options; 189 | } 190 | 191 | public AzureADOptions CurrentValue => throw new NotImplementedException(); 192 | 193 | public string Scheme { get; } 194 | public AzureADOptions Options { get; } 195 | 196 | public AzureADOptions Get(string name) 197 | { 198 | if (name == Scheme) 199 | { 200 | return Options; 201 | } 202 | 203 | return null; 204 | } 205 | 206 | public IDisposable OnChange(Action listener) 207 | { 208 | throw new NotImplementedException(); 209 | } 210 | } 211 | 212 | private class TestUrlHelper : IUrlHelper 213 | { 214 | public TestUrlHelper(string contentPath, string url) 215 | { 216 | ContentPath = contentPath; 217 | Url = url; 218 | } 219 | 220 | public TestUrlHelper( 221 | HttpContext context, 222 | RouteData routeData, 223 | ActionDescriptor descriptor, 224 | string contentPath, 225 | string url) 226 | { 227 | HttpContext = context; 228 | RouteData = routeData; 229 | ActionDescriptor = descriptor; 230 | ContentPath = contentPath; 231 | Url = url; 232 | } 233 | 234 | public ActionContext ActionContext => 235 | new ActionContext(HttpContext, RouteData, ActionDescriptor); 236 | 237 | public string ContentPath { get; } 238 | public string Url { get; } 239 | public HttpContext HttpContext { get; } 240 | public RouteData RouteData { get; } 241 | public ActionDescriptor ActionDescriptor { get; } 242 | 243 | public string Action(UrlActionContext actionContext) 244 | { 245 | throw new NotImplementedException(); 246 | } 247 | 248 | public string Content(string contentPath) 249 | { 250 | if (ContentPath == contentPath) 251 | { 252 | return Url; 253 | } 254 | return ""; 255 | } 256 | 257 | public bool IsLocalUrl(string url) 258 | { 259 | throw new NotImplementedException(); 260 | } 261 | 262 | public string Link(string routeName, object values) 263 | { 264 | throw new NotImplementedException(); 265 | } 266 | 267 | public string RouteUrl(UrlRouteContext routeContext) 268 | { 269 | if (routeContext.Values is RouteValueDictionary dicionary && 270 | dicionary.TryGetValue("page", out var page) && 271 | page is string pagePath && 272 | ContentPath == pagePath) 273 | { 274 | return Url; 275 | } 276 | 277 | return null; 278 | } 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.UI.Test/Microsoft.AspNetCore.Authentication.AzureAD.UI.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | Microsoft.AspNetCore.Authentication.AzureAD.UI 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureAD.UI.Test/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "shadowCopy": false 3 | } 4 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test/AzureAdB2COpenIDConnectEventHandlersTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authentication; 7 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 10 | using Microsoft.Net.Http.Headers; 11 | using Xunit; 12 | 13 | namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI 14 | { 15 | public class AzureADB2COpenIDConnectEventHandlersTests 16 | { 17 | [Fact] 18 | public async Task OnRedirectToIdentityProviderHandler_DoesNothingForTheDefaultPolicy() 19 | { 20 | // Arrange 21 | var handlers = new AzureADB2COpenIDConnectEventHandlers( 22 | AzureADB2CDefaults.AuthenticationScheme, 23 | new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); 24 | 25 | var authenticationProperties = new AuthenticationProperties(new Dictionary 26 | { 27 | [AzureADB2CDefaults.PolicyKey] = "B2C_1_SiUpIn" 28 | }); 29 | var redirectContext = new RedirectContext( 30 | new DefaultHttpContext(), 31 | new AuthenticationScheme(AzureADB2CDefaults.AuthenticationScheme, "", typeof(OpenIdConnectHandler)), 32 | new OpenIdConnectOptions(), 33 | authenticationProperties) 34 | { 35 | ProtocolMessage = new OpenIdConnectMessage 36 | { 37 | Scope = OpenIdConnectScope.OpenId, 38 | ResponseType = OpenIdConnectResponseType.Code, 39 | IssuerAddress = "https://login.microsoftonline.com/tfp/domain.onmicrosoft.com/B2C_1_SiUpIn/v2.0" 40 | } 41 | }; 42 | 43 | // Act 44 | await handlers.OnRedirectToIdentityProvider(redirectContext); 45 | 46 | // Assert 47 | Assert.Equal(OpenIdConnectScope.OpenId, redirectContext.ProtocolMessage.Scope); 48 | Assert.Equal(OpenIdConnectResponseType.Code, redirectContext.ProtocolMessage.ResponseType); 49 | Assert.Equal( 50 | "https://login.microsoftonline.com/tfp/domain.onmicrosoft.com/B2C_1_SiUpIn/v2.0", 51 | redirectContext.ProtocolMessage.IssuerAddress); 52 | Assert.True(authenticationProperties.Items.ContainsKey(AzureADB2CDefaults.PolicyKey)); 53 | } 54 | 55 | [Fact] 56 | public async Task OnRedirectToIdentityProviderHandler_UpdatesRequestForOtherPolicies() 57 | { 58 | // Arrange 59 | 60 | var handlers = new AzureADB2COpenIDConnectEventHandlers( 61 | AzureADB2CDefaults.AuthenticationScheme, 62 | new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); 63 | 64 | var authenticationProperties = new AuthenticationProperties(new Dictionary 65 | { 66 | [AzureADB2CDefaults.PolicyKey] = "B2C_1_EP" 67 | }); 68 | var redirectContext = new RedirectContext( 69 | new DefaultHttpContext(), 70 | new AuthenticationScheme(AzureADB2CDefaults.AuthenticationScheme, "", typeof(OpenIdConnectHandler)), 71 | new OpenIdConnectOptions(), 72 | authenticationProperties) 73 | { 74 | ProtocolMessage = new OpenIdConnectMessage 75 | { 76 | Scope = OpenIdConnectScope.OpenId, 77 | ResponseType = OpenIdConnectResponseType.Code, 78 | IssuerAddress = "https://login.microsoftonline.com/tfp/domain.onmicrosoft.com/B2C_1_EP/v2.0" 79 | } 80 | }; 81 | 82 | // Act 83 | await handlers.OnRedirectToIdentityProvider(redirectContext); 84 | 85 | // Assert 86 | Assert.Equal(OpenIdConnectScope.OpenIdProfile, redirectContext.ProtocolMessage.Scope); 87 | Assert.Equal(OpenIdConnectResponseType.IdToken, redirectContext.ProtocolMessage.ResponseType); 88 | Assert.Equal( 89 | "https://login.microsoftonline.com/tfp/domain.onmicrosoft.com/b2c_1_ep/v2.0", 90 | redirectContext.ProtocolMessage.IssuerAddress); 91 | Assert.False(authenticationProperties.Items.ContainsKey(AzureADB2CDefaults.PolicyKey)); 92 | } 93 | 94 | [Fact] 95 | public async Task OnRemoteError_HandlesResponseWhenTryingToResetPasswordFromTheLoginPage() 96 | { 97 | // Arrange 98 | 99 | var handlers = new AzureADB2COpenIDConnectEventHandlers( 100 | AzureADB2CDefaults.AuthenticationScheme, 101 | new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); 102 | 103 | var remoteFailureContext = new RemoteFailureContext( 104 | new DefaultHttpContext(), 105 | new AuthenticationScheme( 106 | AzureADB2CDefaults.AuthenticationScheme, 107 | displayName: null, 108 | handlerType: typeof(OpenIdConnectHandler)), 109 | new OpenIdConnectOptions(), 110 | new OpenIdConnectProtocolException("AADB2C90118")); 111 | 112 | // Act 113 | await handlers.OnRemoteFailure(remoteFailureContext); 114 | 115 | // Assert 116 | Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); 117 | Assert.Equal("/AzureADB2C/Account/ResetPassword/AzureADB2C", remoteFailureContext.Response.Headers[HeaderNames.Location]); 118 | Assert.True(remoteFailureContext.Result.Handled); 119 | } 120 | 121 | [Fact] 122 | public async Task OnRemoteError_HandlesResponseWhenUserCancelsFlowFromTheAzureADB2CUserInterface() 123 | { 124 | // Arrange 125 | 126 | var handlers = new AzureADB2COpenIDConnectEventHandlers( 127 | AzureADB2CDefaults.AuthenticationScheme, 128 | new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); 129 | 130 | var remoteFailureContext = new RemoteFailureContext( 131 | new DefaultHttpContext(), 132 | new AuthenticationScheme( 133 | AzureADB2CDefaults.AuthenticationScheme, 134 | displayName: null, 135 | handlerType: typeof(OpenIdConnectHandler)), 136 | new OpenIdConnectOptions(), 137 | new OpenIdConnectProtocolException("access_denied")); 138 | 139 | // Act 140 | await handlers.OnRemoteFailure(remoteFailureContext); 141 | 142 | // Assert 143 | Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); 144 | Assert.Equal("/", remoteFailureContext.Response.Headers[HeaderNames.Location]); 145 | Assert.True(remoteFailureContext.Result.Handled); 146 | } 147 | 148 | [Fact] 149 | public async Task OnRemoteError_HandlesResponseWhenErrorIsUnknown() 150 | { 151 | // Arrange 152 | 153 | var handlers = new AzureADB2COpenIDConnectEventHandlers( 154 | AzureADB2CDefaults.AuthenticationScheme, 155 | new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); 156 | 157 | var remoteFailureContext = new RemoteFailureContext( 158 | new DefaultHttpContext(), 159 | new AuthenticationScheme( 160 | AzureADB2CDefaults.AuthenticationScheme, 161 | displayName: null, 162 | handlerType: typeof(OpenIdConnectHandler)), 163 | new OpenIdConnectOptions(), 164 | new OpenIdConnectProtocolException("some_other_error")); 165 | 166 | // Act 167 | await handlers.OnRemoteFailure(remoteFailureContext); 168 | 169 | // Assert 170 | Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); 171 | Assert.Equal("/AzureADB2C/Account/Error", remoteFailureContext.Response.Headers[HeaderNames.Location]); 172 | Assert.True(remoteFailureContext.Result.Handled); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | Microsoft.AspNetCore.Authentication.AzureADB2C.UI 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Test/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "shadowCopy": false 3 | } 4 | -------------------------------------------------------------------------------- /test/WebSites/AzureAD.WebSite/AzureAD.WebSite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/WebSites/AzureAD.WebSite/Controllers/TestController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace AzureAD.WebSite.Controllers 8 | { 9 | public class TestController : Controller 10 | { 11 | [Authorize] 12 | [HttpGet("/api/get")] 13 | public IActionResult Get() => Ok(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/WebSites/AzureAD.WebSite/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Reflection; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using Microsoft.AspNetCore; 11 | using Microsoft.AspNetCore.Hosting; 12 | using Microsoft.Extensions.Configuration; 13 | using Microsoft.Extensions.Logging; 14 | 15 | namespace AzureAD.WebSite 16 | { 17 | public class Program 18 | { 19 | public static void Main(string[] args) 20 | { 21 | CreateWebHostBuilder(args).Build().Run(); 22 | } 23 | 24 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) 25 | { 26 | var builder = new WebHostBuilder() 27 | .UseKestrel((builderContext, options) => 28 | { 29 | options.Configure(builderContext.Configuration.GetSection("Kestrel")); 30 | }) 31 | .UseContentRoot(Directory.GetCurrentDirectory()) 32 | .ConfigureAppConfiguration((hostingContext, config) => 33 | { 34 | var env = hostingContext.HostingEnvironment; 35 | 36 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 37 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); 38 | 39 | if (env.IsDevelopment()) 40 | { 41 | var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); 42 | if (appAssembly != null) 43 | { 44 | config.AddUserSecrets(appAssembly, optional: true); 45 | } 46 | } 47 | 48 | config.AddEnvironmentVariables(); 49 | 50 | if (args != null) 51 | { 52 | config.AddCommandLine(args); 53 | } 54 | }) 55 | .ConfigureLogging((hostingContext, logging) => 56 | { 57 | logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); 58 | logging.AddConsole(); 59 | logging.AddDebug(); 60 | }) 61 | .UseIISIntegration() 62 | .UseDefaultServiceProvider((context, options) => 63 | { 64 | options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); 65 | }); 66 | 67 | if (args != null) 68 | { 69 | builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build()); 70 | } 71 | 72 | builder.UseStartup(); 73 | 74 | return builder; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/WebSites/AzureAD.WebSite/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace AzureAD.WebSite 9 | { 10 | public class Startup 11 | { 12 | public void ConfigureServices(IServiceCollection services) 13 | { 14 | services.AddMvc(); 15 | } 16 | 17 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 18 | { 19 | app.UseAuthentication(); 20 | 21 | app.UseMvc(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/WebSites/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /version.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3.0.0 4 | 0.5.0 5 | alpha1 6 | $(VersionPrefix) 7 | $(VersionPrefix)-$(VersionSuffix)-final 8 | t000 9 | $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) 10 | $(VersionSuffix)-$(BuildNumber) 11 | 12 | 13 | --------------------------------------------------------------------------------