├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── dotnet-core.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Deploy-to-Azure ├── README.md └── ReadmeFiles │ └── topology.png ├── LICENSE.md ├── README.md ├── WebApp-Connect-To-Azure-Sql-Database ├── Client │ ├── AAD │ │ └── UserAADService.cs │ ├── App.razor │ ├── AppCreationScripts │ │ ├── AppCreationScripts.md │ │ ├── Cleanup.ps1 │ │ ├── Configure.ps1 │ │ └── sample.json │ ├── Data │ │ ├── WeatherForecast.cs │ │ └── WeatherForecastService.cs │ ├── Database │ │ └── SqlDatabaseService.cs │ ├── Pages │ │ ├── Counter.razor │ │ ├── Error.cshtml │ │ ├── Error.cshtml.cs │ │ ├── FetchData.razor │ │ ├── Index.razor │ │ ├── _Host.cshtml │ │ └── _Layout.cshtml │ ├── Program.cs │ ├── Properties │ │ ├── ServiceDependencies │ │ │ └── BlazorAzureSql - Web Deploy │ │ │ │ └── profile.arm.json │ │ ├── launchSettings.json │ │ ├── serviceDependencies.BlazorAzureSql - Web Deploy.json │ │ ├── serviceDependencies.json │ │ └── serviceDependencies.local.json │ ├── ReadmeFiles │ │ ├── AppRegistrationSteps.md │ │ ├── CreateProjectSteps.md │ │ ├── ReadmeAboutTheCode.md │ │ ├── ReadmeAzureDeploy.md │ │ ├── ReadmeContributing.md │ │ ├── ReadmeLearnMore.md │ │ ├── ReadmeTroubleshooting.md │ │ ├── ReadmeUsingTheSample.md │ │ ├── fetch-data-page.png │ │ ├── topology.png │ │ └── topology.vsdx │ ├── Shared │ │ ├── LoginDisplay.razor │ │ ├── MainLayout.razor │ │ ├── MainLayout.razor.css │ │ ├── NavMenu.razor │ │ ├── NavMenu.razor.css │ │ └── SurveyPrompt.razor │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── ms-identity-dotnet-blazor-azure-sql.csproj │ └── wwwroot │ │ ├── Images │ │ └── topology.png │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ │ └── favicon.ico ├── README.md └── blazorserver-Connect-To-Azure-SQL-Database.sln ├── WebApp-OIDC ├── B2C │ ├── README.md │ ├── ReadmeFiles │ │ ├── UserClaims.png │ │ └── topology.png │ ├── blazorserver-B2C.sln │ └── blazorserver-B2C │ │ ├── App.razor │ │ ├── Pages │ │ ├── Error.cshtml │ │ ├── Index.razor │ │ ├── UserClaims.razor │ │ ├── UserClaimsBase.cs │ │ └── _Host.cshtml │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Shared │ │ ├── LoginDisplay.razor │ │ ├── MainLayout.razor │ │ ├── NavMenu.razor │ │ └── SurveyPrompt.razor │ │ ├── Startup.cs │ │ ├── _Imports.razor │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── blazorserver-B2C.csproj │ │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ │ └── favicon.ico └── MyOrg │ ├── AppCreationScripts │ ├── AppCreationScripts.md │ ├── Cleanup.ps1 │ ├── Configure.ps1 │ └── sample.json │ ├── README.md │ ├── ReadmeFiles │ ├── UserClaims.png │ └── topology.png │ ├── blazorserver-singleOrg.sln │ └── blazorserver-singleOrg │ ├── App.razor │ ├── Pages │ ├── Error.cshtml │ ├── Index.razor │ ├── UserClaims.razor │ ├── UserClaimsBase.cs │ └── _Host.cshtml │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Shared │ ├── LoginDisplay.razor │ ├── MainLayout.razor │ ├── NavMenu.razor │ └── SurveyPrompt.razor │ ├── Startup.cs │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── blazorserver-singleOrg.csproj │ └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ │ ├── css │ │ │ └── open-iconic-bootstrap.min.css │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.svg │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ └── site.css │ └── favicon.ico ├── WebApp-graph-user └── Call-MSGraph │ ├── AppCreationScripts │ ├── AppCreationScripts.md │ ├── Cleanup.ps1 │ ├── Configure.ps1 │ └── sample.json │ ├── README-Incremental.md │ ├── README.md │ ├── ReadmeFiles │ ├── UserClaims.png │ ├── UserProfile.png │ └── topology.png │ ├── blazorserver-calls-MS-graph.sln │ └── blazorserver-calls-MS-graph │ ├── App.razor │ ├── Pages │ ├── Error.cshtml │ ├── Index.razor │ ├── ShowProfile.razor │ ├── UserClaims.razor │ ├── UserClaimsBase.cs │ ├── UserProfile.razor │ ├── UserProfileBase.cs │ └── _Host.cshtml │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Shared │ ├── LoginDisplay.razor │ ├── MainLayout.razor │ ├── NavMenu.razor │ └── SurveyPrompt.razor │ ├── Startup.cs │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── blazorserver-calls-MS-graph.csproj │ └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ │ ├── css │ │ │ └── open-iconic-bootstrap.min.css │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.svg │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ └── site.css │ └── favicon.ico ├── WebApp-your-API ├── B2C │ ├── Client │ │ ├── App.razor │ │ ├── Data │ │ │ └── ToDoListService.cs │ │ ├── Pages │ │ │ ├── Error.cshtml │ │ │ ├── Index.razor │ │ │ ├── ToDoPages │ │ │ │ ├── CommonForm.razor │ │ │ │ ├── Create.razor │ │ │ │ ├── Edit.razor │ │ │ │ ├── ToDoList.razor │ │ │ │ └── ToDoListBase.cs │ │ │ ├── UserClaims.razor │ │ │ ├── UserClaimsBase.cs │ │ │ └── _Host.cshtml │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Shared │ │ │ ├── LoginDisplay.razor │ │ │ ├── MainLayout.razor │ │ │ ├── NavMenu.razor │ │ │ └── SurveyPrompt.razor │ │ ├── Startup.cs │ │ ├── _Imports.razor │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── blazorserver-client.csproj │ │ └── wwwroot │ │ │ ├── css │ │ │ ├── bootstrap │ │ │ │ ├── bootstrap.min.css │ │ │ │ └── bootstrap.min.css.map │ │ │ ├── open-iconic │ │ │ │ ├── FONT-LICENSE │ │ │ │ ├── ICON-LICENSE │ │ │ │ ├── README.md │ │ │ │ └── font │ │ │ │ │ ├── css │ │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ │ └── fonts │ │ │ │ │ ├── open-iconic.eot │ │ │ │ │ ├── open-iconic.otf │ │ │ │ │ ├── open-iconic.svg │ │ │ │ │ ├── open-iconic.ttf │ │ │ │ │ └── open-iconic.woff │ │ │ └── site.css │ │ │ └── favicon.ico │ ├── README-Incremental.md │ ├── README.md │ ├── ReadmeFiles │ │ ├── ToDoList.png │ │ ├── UserClaims.png │ │ └── topology.png │ ├── Service │ │ ├── AuthorizationPolicies │ │ │ └── ScopesRequirement.cs │ │ ├── Controllers │ │ │ └── ToDoListController.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ ├── launchSettings.json │ │ │ ├── serviceDependencies.json │ │ │ └── serviceDependencies.local.json │ │ ├── Startup.cs │ │ ├── ToDoListService.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── ToDoListModel │ │ ├── ToDo.cs │ │ └── ToDoListModel.csproj │ └── blazorserver-Calls-WebAPI-B2C.sln └── MyOrg │ ├── AppCreationScripts │ ├── AppCreationScripts.md │ ├── Cleanup.ps1 │ ├── Configure.ps1 │ └── sample.json │ ├── Client │ ├── App.razor │ ├── Pages │ │ ├── Error.cshtml │ │ ├── Index.razor │ │ ├── ToDoPages │ │ │ ├── CommonForm.razor │ │ │ ├── Create.razor │ │ │ ├── Edit.razor │ │ │ ├── ToDoList.razor │ │ │ └── ToDoListBase.cs │ │ ├── UserClaims.razor │ │ ├── UserClaimsBase.cs │ │ └── _Host.cshtml │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Shared │ │ ├── LoginDisplay.razor │ │ ├── MainLayout.razor │ │ ├── NavMenu.razor │ │ └── SurveyPrompt.razor │ ├── Startup.cs │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── blazorserver-client.csproj │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ │ └── favicon.ico │ ├── README-Incremental.md │ ├── README.md │ ├── ReadmeFiles │ ├── ToDoList.png │ ├── UserClaims.png │ └── topology.png │ ├── Service │ ├── Controllers │ │ └── ToDoListController.cs │ ├── Program.cs │ ├── Properties │ │ ├── launchSettings.json │ │ ├── serviceDependencies.json │ │ └── serviceDependencies.local.json │ ├── Startup.cs │ ├── ToDoListService.csproj │ ├── appsettings.Development.json │ └── appsettings.json │ ├── ToDoListModel │ ├── ToDo.cs │ └── ToDoListModel.csproj │ └── blazorserver-Calls-WebAPI.sln ├── build.bat └── buildAllSlns.proj /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.github/workflows/dotnet-core.yml: -------------------------------------------------------------------------------- 1 | name: .NET Core 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Setup .NET 17 | uses: actions/setup-dotnet@v3 18 | with: 19 | dotnet-version: 7.x 20 | - name: Build 21 | run: dotnet build buildAllSlns.proj -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [project-title] Changelog 2 | 3 | 4 | # x.y.z (yyyy-mm-dd) 5 | 6 | *Features* 7 | * ... 8 | 9 | *Bug Fixes* 10 | * ... 11 | 12 | *Breaking Changes* 13 | * ... 14 | -------------------------------------------------------------------------------- /Deploy-to-Azure/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/Deploy-to-Azure/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 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 all 13 | 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 THE 21 | SOFTWARE -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Sorry, there's nothing at this address.

9 |
10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/AppCreationScripts/Cleanup.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [Parameter(Mandatory=$False, HelpMessage='Tenant ID (This is a GUID which represents the "Directory ID" of the AzureAD tenant into which you want to create the apps')] 4 | [string] $tenantId, 5 | [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script. Default = Global')] 6 | [string] $azureEnvironmentName 7 | ) 8 | 9 | Function Cleanup 10 | { 11 | if (!$azureEnvironmentName) 12 | { 13 | $azureEnvironmentName = "Global" 14 | } 15 | 16 | <# 17 | .Description 18 | This function removes the Azure AD applications for the sample. These applications were created by the Configure.ps1 script 19 | #> 20 | 21 | # $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant 22 | # into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD. 23 | 24 | # Connect to the Microsoft Graph API 25 | Write-Host "Connecting to Microsoft Graph" 26 | if ($tenantId -eq "") { 27 | Connect-MgGraph -Scopes "Application.ReadWrite.All" -Environment $azureEnvironmentName 28 | $tenantId = (Get-MgContext).TenantId 29 | } 30 | else { 31 | Connect-MgGraph -TenantId $tenantId -Scopes "Application.ReadWrite.All" -Environment $azureEnvironmentName 32 | } 33 | 34 | # Removes the applications 35 | Write-Host "Cleaning-up applications from tenant '$tenantId'" 36 | 37 | Write-Host "Removing 'client' (ClientApp-blazor-azuresql) if needed" 38 | try 39 | { 40 | Get-MgApplication -Filter "DisplayName eq 'ClientApp-blazor-azuresql'" | ForEach-Object {Remove-MgApplication -ApplicationId $_.Id } 41 | } 42 | catch 43 | { 44 | Write-Host "Unable to remove the application 'ClientApp-blazor-azuresql' . Try deleting manually." -ForegroundColor White -BackgroundColor Red 45 | } 46 | 47 | Write-Host "Making sure there are no more (ClientApp-blazor-azuresql) applications found, will remove if needed..." 48 | $apps = Get-MgApplication -Filter "DisplayName eq 'ClientApp-blazor-azuresql'" 49 | 50 | if ($apps) 51 | { 52 | Remove-MgApplication -ApplicationId $apps.Id 53 | } 54 | 55 | foreach ($app in $apps) 56 | { 57 | Remove-MgApplication -ApplicationId $app.Id 58 | Write-Host "Removed ClientApp-blazor-azuresql.." 59 | } 60 | 61 | # also remove service principals of this app 62 | try 63 | { 64 | Get-MgServicePrincipal -filter "DisplayName eq 'ClientApp-blazor-azuresql'" | ForEach-Object {Remove-MgServicePrincipal -ApplicationId $_.Id -Confirm:$false} 65 | } 66 | catch 67 | { 68 | Write-Host "Unable to remove ServicePrincipal 'ClientApp-blazor-azuresql' . Try deleting manually from Enterprise applications." -ForegroundColor White -BackgroundColor Red 69 | } 70 | } 71 | 72 | if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Applications")) { 73 | Install-Module "Microsoft.Graph.Applications" -Scope CurrentUser 74 | } 75 | Import-Module Microsoft.Graph.Applications 76 | $ErrorActionPreference = "Stop" 77 | 78 | 79 | Cleanup -tenantId $tenantId -environment $azureEnvironmentName 80 | 81 | Write-Host "Disconnecting from tenant" 82 | Disconnect-MgGraph 83 | 84 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Data/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ms_identity_dotnet_blazor_azure_sql.Data 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Data/WeatherForecastService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Authorization; 2 | using Microsoft.Data.SqlClient; 3 | using Microsoft.IdentityModel.Tokens; 4 | using ms_identity_dotnet_blazor_azure_sql.AAD; 5 | using ms_identity_dotnet_blazor_azure_sql.Database; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Data; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace ms_identity_dotnet_blazor_azure_sql.Data 13 | { 14 | public class WeatherForecastService 15 | { 16 | private readonly UserAADService _userAAD; 17 | private readonly SqlDatabaseService _databaseService; 18 | 19 | public WeatherForecastService(UserAADService userAAD, SqlDatabaseService databaseService) 20 | { 21 | _userAAD = userAAD; 22 | _databaseService = databaseService; 23 | } 24 | 25 | public async Task GetForecastAsync(DateTime startDate, AuthenticationState authState) 26 | { 27 | //database call 28 | var dbSummaries = await GetSummaries(authState); 29 | 30 | var rnd = new Random(); 31 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 32 | { 33 | Date = startDate.AddDays(index), 34 | TemperatureC = rnd.Next(-20, 55), 35 | Summary = dbSummaries[rnd.Next(dbSummaries.Count)] 36 | }).ToArray(); 37 | } 38 | 39 | //get summaries strings from underlying Azure SQL Database 40 | private async Task> GetSummaries(AuthenticationState authState) 41 | { 42 | var summaryList = new List(); 43 | 44 | //Lets acquire a access token from Azure Ad for your database connection string 45 | var accessToken = await _userAAD.GetAccessTokenForSqlDatabase(authState); 46 | if (accessToken.IsNullOrEmpty()) 47 | { 48 | return summaryList; 49 | } 50 | 51 | //connect to database with connection string from configuration and access token 52 | using (SqlConnection conn = _databaseService.GetSqlConnection(accessToken)) 53 | { 54 | try 55 | { 56 | if (conn.State == ConnectionState.Closed) 57 | { 58 | await conn.OpenAsync(); 59 | } 60 | 61 | SqlCommand cmd = new(@"select * from Summary", conn); 62 | 63 | var myReader = await cmd.ExecuteReaderAsync(); 64 | 65 | while (myReader.Read()) 66 | { 67 | summaryList.Add(myReader["Summary"].ToString()); 68 | } 69 | } 70 | catch (SqlException ex) 71 | { 72 | //throw any sql exception to the page 73 | throw new Exception(ex.Message); 74 | } 75 | finally 76 | { 77 | //close connection anyways 78 | if (conn.State == ConnectionState.Open) 79 | { 80 | await conn.CloseAsync(); 81 | } 82 | } 83 | } 84 | 85 | return summaryList; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Database/SqlDatabaseService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Data.SqlClient; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace ms_identity_dotnet_blazor_azure_sql.Database 5 | { 6 | //simple SQL Database Service intended to encapsulate SQL related configuration and functionality 7 | public class SqlDatabaseService 8 | { 9 | readonly IConfiguration _configuration; 10 | 11 | public SqlDatabaseService(IConfiguration configuration) 12 | { 13 | _configuration = configuration; 14 | } 15 | 16 | public SqlConnection GetSqlConnection(string accessToken, string connStringName = "SqlDbContext") 17 | { 18 | SqlConnection conn = new(_configuration.GetConnectionString(connStringName)); 19 | 20 | //use the obtained token inside Azure SQL Database connection string 21 | conn.AccessToken = accessToken; 22 | 23 | return conn; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/Counter.razor: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 | 3 | Counter 4 | 5 |

Counter

6 | 7 |

Current count: @currentCount

8 | 9 | 10 | 11 | @code { 12 | private int currentCount = 0; 13 | 14 | private void IncrementCount() 15 | { 16 | currentCount++; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ms_identity_dotnet_blazor_azure_sql.Pages.ErrorModel 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Error 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |

Error.

19 |

An error occurred while processing your request.

20 | 21 | @if (Model.ShowRequestId) 22 | { 23 |

24 | Request ID: @Model.RequestId 25 |

26 | } 27 | 28 |

Development Mode

29 |

30 | Swapping to the Development environment displays detailed information about the error that occurred. 31 |

32 |

33 | The Development environment shouldn't be enabled for deployed applications. 34 | It can result in displaying sensitive information from exceptions to end users. 35 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 36 | and restarting the app. 37 |

38 |
39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.RazorPages; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace ms_identity_dotnet_blazor_azure_sql.Pages 11 | { 12 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 13 | [IgnoreAntiforgeryToken] 14 | public class ErrorModel : PageModel 15 | { 16 | public string RequestId { get; set; } 17 | 18 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 19 | 20 | private readonly ILogger _logger; 21 | 22 | public ErrorModel(ILogger logger) 23 | { 24 | _logger = logger; 25 | } 26 | 27 | public void OnGet() 28 | { 29 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/FetchData.razor: -------------------------------------------------------------------------------- 1 | @page "/fetchdata" 2 | 3 | @using ms_identity_dotnet_blazor_azure_sql.AAD 4 | @using ms_identity_dotnet_blazor_azure_sql.Data 5 | @inject WeatherForecastService ForecastService 6 | @inject UserAADService UserAADService 7 | @inject AuthenticationStateProvider GetAuthenticationStateAsync 8 | 9 |

Weather forecast

10 |

@_greetingsMessage

11 | 12 |

This component demonstrates fetching data from a service that is connected to SQL database.

13 | 14 | @if (forecasts == null) 15 | { 16 |

Loading...

17 | } 18 | else 19 | { 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @foreach (var forecast in forecasts) 31 | { 32 | 33 | 34 | 35 | 36 | 37 | 38 | } 39 | 40 |
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
41 | } 42 | 43 | @code { 44 | private WeatherForecast[] forecasts; 45 | private string _loggedUser; 46 | private string _greetingsMessage; 47 | 48 | protected override async Task OnInitializedAsync() 49 | { 50 | //obtain current authentication state of the application from HttpContext.User - https://docs.microsoft.com/aspnet/core/blazor/security/server/ 51 | var authstate = await GetAuthenticationStateAsync.GetAuthenticationStateAsync(); 52 | 53 | //obtain user name from the underlying database based on logged-in user information 54 | _loggedUser = await UserAADService.GetDatabaseLoggedInUser(authstate); 55 | 56 | if (_loggedUser == "N/A") 57 | { 58 | _greetingsMessage = "Could not obtian logged-in user. Please Log Out of the current user and re-login."; 59 | } 60 | else 61 | { 62 | //set greetings message with user name obtained from database 63 | _greetingsMessage = $"The user logged into SQL Database is {_loggedUser}"; 64 | 65 | //fetch data for the user 66 | forecasts = await ForecastService.GetForecastAsync(DateTime.Now, authstate); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

Blazor with SQL Server

4 |

Go fetch your data

5 | 6 | Welcome to your new app. 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace ms_identity_dotnet_blazor_azure_sql.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | ms-identity-dotnet-blazor-azure-sql 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | An error has occurred. This application may no longer respond until reloaded. 25 | 26 | 27 | An unhandled exception has occurred. See browser dev tools for details. 28 | 29 | Reload 30 | 🗙 31 |
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Pages/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @namespace ms_identity_dotnet_blazor_azure_sql.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | @RenderBody() 18 | 19 |
20 | 21 | An error has occurred. This application may no longer respond until reloaded. 22 | 23 | 24 | An unhandled exception has occurred. See browser dev tools for details. 25 | 26 | Reload 27 | 🗙 28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Identity.Web; 7 | using Microsoft.Identity.Web.UI; 8 | using ms_identity_dotnet_blazor_azure_sql.AAD; 9 | using ms_identity_dotnet_blazor_azure_sql.Data; 10 | using ms_identity_dotnet_blazor_azure_sql.Database; 11 | 12 | var builder = WebApplication.CreateBuilder(args); 13 | 14 | // Add services to the container. 15 | builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) 16 | .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) 17 | .EnableTokenAcquisitionToCallDownstreamApi() 18 | .AddInMemoryTokenCaches(); 19 | 20 | builder.Services.AddControllersWithViews() 21 | .AddMicrosoftIdentityUI(); 22 | 23 | //uncomment this part in case when Index page should proceed to authorization UI immediately after the application starts 24 | //with the below lines enabled there will be impossible to be "Not logged in" because it will re-login automatically 25 | //builder.Services.AddAuthorization(options => 26 | //{ 27 | // // By default, all incoming requests will be authorized according to the default policy 28 | // options.FallbackPolicy = options.DefaultPolicy; 29 | //}); 30 | 31 | // Add services to the container. 32 | builder.Services.AddRazorPages(); 33 | builder.Services.AddServerSideBlazor() 34 | .AddMicrosoftIdentityConsentHandler(); 35 | 36 | builder.Services 37 | .AddScoped() 38 | .AddScoped() 39 | .AddSingleton(); 40 | 41 | builder.Services.Configure(OpenIdConnectDefaults.AuthenticationScheme, options => 42 | { 43 | options.Events.OnSignedOutCallbackRedirect = async context => 44 | { 45 | await System.Threading.Tasks.Task.Run(() => 46 | { 47 | context.HttpContext.Response.Redirect(builder.Configuration.GetSection("AzureAd:OnSignOutRedirectPage").Value); 48 | context.HandleResponse(); 49 | }); 50 | }; 51 | }); 52 | 53 | var app = builder.Build(); 54 | 55 | // Configure the HTTP request pipeline. 56 | if (!app.Environment.IsDevelopment()) 57 | { 58 | app.UseExceptionHandler("/Error"); 59 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 60 | app.UseHsts(); 61 | } 62 | 63 | app.UseHttpsRedirection(); 64 | 65 | app.UseStaticFiles(); 66 | 67 | app.UseRouting(); 68 | 69 | app.UseAuthentication(); 70 | app.UseAuthorization(); 71 | 72 | app.MapControllers(); 73 | app.MapBlazorHub(); 74 | app.MapFallbackToPage("/_Host"); 75 | 76 | app.Run(); 77 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:32562", 7 | "sslPort": 44348 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "ms-identity-dotnet-blazor-azure-sql": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "dotnetRunMessages": "true", 25 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Properties/serviceDependencies.BlazorAzureSql - Web Deploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "identityapp1": { 4 | "resourceId": null, 5 | "type": "identityapp.aad", 6 | "connectionId": null, 7 | "secretStore": null 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "identityapp1": { 4 | "type": "identityapp", 5 | "connectionId": null 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "identityapp1": { 4 | "type": "identityapp.aad" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/CreateProjectSteps.md: -------------------------------------------------------------------------------- 1 | ### Step 1: Clone or download this repository 2 | 3 | From your shell or command line: 4 | 5 | ```console 6 | git clone https://github.com/Azure-Samples/ms-identity-blazor-server.git 7 | ``` 8 | 9 | or download and extract the repository .zip file. 10 | 11 | >:warning: To avoid path length limitations on Windows, we recommend cloning into a directory near the root of your drive. 12 | 13 | ### Step 2: Setup Azure SQL Database and grant user permissions for managed identity 14 | 15 | 1. Create an [Azure SQL Database](https://docs.microsoft.com/azure/azure-sql/database/single-database-create-quickstart). 16 | * The Sql database Server should have either `Use only Azure Active Directory (Azure AD) authentication` or `Use both SQL and Azure AD authentication` set up as Authentication method. 17 | 2. Add one or more of this Azure AD tenant's user as or "Azure Active Directory admin". You would use this user to execute the next set of Sql statements. 18 | 3. Install [SQL Server Management Studio](https://docs.microsoft.com/sql/ssms/download-sql-server-management-studio-ssms) and connect to your newly created Azure SQL database using the account you set as "Azure Active Directory admin". 19 | 4. In your newly created Database, run the following SQL statements to create and populate a database table to be used in this sample. 20 | 21 | ```sql 22 | CREATE TABLE [dbo].[Summary]( 23 | [Summary] [nvarchar](50) NOT NULL) 24 | ``` 25 | 26 | ```sql 27 | Insert into [dbo].Summary values ('Freezing'),('Bracing'),('Chilly'),('Cool'),('Mild'),('Warm'),('Balmy'),('Hot'),('Sweltering'),('Scorching') 28 | ``` 29 | 30 | ```sql 31 | CREATE FUNCTION [dbo].[UsernamePrintFn]() 32 | RETURNS nvarchar(500) 33 | AS 34 | BEGIN 35 | declare @host nvarchar(100), @user nvarchar(100); 36 | SELECT @host = HOST_NAME() , @user = SUSER_NAME() 37 | declare @result nvarchar(500) = cast(@user + ' at ' + @host as nvarchar(500)) 38 | -- Return the result of the function 39 | return @result 40 | END 41 | ``` 42 | 43 | ```sql 44 | /** 45 | You can use the following command to ensure that the table and function were correctly created and work as expected 46 | **/ 47 | SELECT * FROM [dbo].Summary 48 | GO 49 | 50 | SELECT [dbo].[UsernamePrintFn] () 51 | GO 52 | ``` 53 | 54 | ```Sql 55 | /** 56 | Create a user in database from users in your Tenant and grant them EXECUTE permission by running next set of commands. 57 | You can add more directory users to this database by running these statements repeatedly. 58 | **/ 59 | DECLARE @AADDBUser nvarchar(128) 60 | SET @AADDBUser = '@.onmicrosoft.com' 61 | 62 | DECLARE @sql as varchar(max) 63 | SET @SQL = 'CREATE USER [' + @AADDBUser + '] FROM EXTERNAL PROVIDER; 64 | EXECUTE sp_addrolemember db_datareader, ''' + @AADDBUser + '''; 65 | grant execute to ''' + @AADDBUser +'''' 66 | 67 | EXEC @SQL 68 | ``` 69 | 70 | 5. Update connection string inside appsettings.json with server and database names 71 | 6. You might need to [update the database Firewall](https://docs.microsoft.com/azure/azure-sql/database/firewall-configure?view=azuresql#from-the-database-overview-page) with your IP address. 72 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeAboutTheCode.md: -------------------------------------------------------------------------------- 1 | ## About the code 2 | 3 |
4 | Expand the section 5 | 6 | The main purpose of this sample is to show how to propagate AAD user to SQL server. The scenario is as follows: 7 | 8 | 1. Get Access Token through interactive log-in process and cache it. To enable caching we have to add the 2 last lines to AAD configuration inside Program.cs: 9 | 10 | ```csharp 11 | builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) 12 | .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) 13 | .EnableTokenAcquisitionToCallDownstreamApi() 14 | .AddInMemoryTokenCaches(); 15 | ``` 16 | 17 | 2. Every time, the new SQL connection is created, acquire the cached token and add it to the connection object. If the cached token is unavailable, the MsalUiRequiredException will be thrown and interactive Authorization process will be kicked-off. Here is relevant code snippet from UserAADServices.cs: 18 | 19 | ```csharp 20 | public async Task GetAccessToken(AuthenticationState authState) 21 | { 22 | string accessToken = string.Empty; 23 | 24 | //https://database.windows.net/.default 25 | var scopes = new string[] { _azureSettings["Scopes"] }; 26 | 27 | try 28 | { 29 | var accountIdentifier = GetAccountIdentifier(authState); 30 | 31 | IAccount account = await _app.GetAccountAsync(accountIdentifier); 32 | 33 | AuthenticationResult authResult = await _app.AcquireTokenSilent(scopes, account).ExecuteAsync(); 34 | accessToken = authResult.AccessToken; 35 | } 36 | catch (MsalUiRequiredException) 37 | { 38 | _consentHandler.ChallengeUser(scopes); 39 | return accessToken; 40 | } 41 | 42 | return accessToken; 43 | } 44 | ``` 45 | 46 | > Notice that the code is using a special default scope to be able to work with SQL Server - **https://database.windows.net/.default** 47 | 48 |
-------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeAzureDeploy.md: -------------------------------------------------------------------------------- 1 | ## How to deploy this sample to Azure 2 | 3 |
4 | Expand the section 5 | 6 | To deploy the sample to Azure you will need Azure SQL Database setup 7 | The deployment is straightforward out of [Visual Studio](https://visualstudio.microsoft.com/downloads/) - right click on the project, select Publish. 8 | Follow the [steps](https://docs.microsoft.com/aspnet/core/tutorials/publish-to-azure-webapp-using-vs?view=aspnetcore-6.0) 9 | 10 | Once succeeded the site will open on default browser. 11 | 12 |
13 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeContributing.md: -------------------------------------------------------------------------------- 1 | 2 | Additional information about AAD authentication can be found [here](https://docs.microsoft.com/azure/azure-sql/database/authentication-aad-overview) 3 | 4 | If you'd like to contribute to this sample, see [CONTRIBUTING.MD](/CONTRIBUTING.md). 5 | 6 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeLearnMore.md: -------------------------------------------------------------------------------- 1 | For more information, visit the following links: 2 | 3 | To learn more about the application registration, visit: 4 | 5 | * [Configure and manage Azure AD authentication with Azure SQL](https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure?view=azuresql&tabs=azure-powershell) 6 | 7 | * [Quickstart: Register an application with the Microsoft identity platform](https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app) 8 | * [Quickstart: Configure a client application to access web APIs](https://docs.microsoft.com/azure/active-directory/develop/quickstart-configure-app-access-web-apis) 9 | * [Quickstart: Configure an application to expose web APIs](https://docs.microsoft.com/azure/active-directory/develop/quickstart-configure-app-expose-web-apis) 10 | 11 | * To learn more about the code, visit: 12 | * [Conceptual documentation for MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki#conceptual-documentation) and in particular: 13 | * [Acquiring tokens with authorization codes on web apps](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-with-authorization-codes-on-web-apps) 14 | * [Customizing Token cache serialization](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/token-cache-serialization) 15 | 16 | * To learn more about security in aspnetcore, 17 | * [Introduction to Identity on ASP.NET Core](https://docs.microsoft.com/aspnet/core/security/authentication/identity) 18 | * [AuthenticationBuilder](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.authentication.authenticationbuilder) 19 | * [Azure Active Directory with ASP.NET Core](https://docs.microsoft.com/aspnet/core/security/authentication/azure-active-directory) 20 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeTroubleshooting.md: -------------------------------------------------------------------------------- 1 | ## Troubleshooting 2 | 3 |
4 | Expand for troubleshooting info 5 | 6 | Use [Stack Overflow](http://stackoverflow.com/questions/tagged/msal) to get support from the community. 7 | Ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before. 8 | Make sure that your questions or comments are tagged with [`azure-active-directory` `adal` `msal` `dotnet`]. 9 | 10 | If you find a bug in the sample, please raise the issue on [GitHub Issues](../../issues). 11 | 12 | To provide a recommendation, visit the following [User Voice page](https://feedback.azure.com/forums/169401-azure-active-directory). 13 |
-------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/ReadmeUsingTheSample.md: -------------------------------------------------------------------------------- 1 | ## Using the sample 2 | 3 |
4 | Expand to see how to use the sample 5 | 6 | Running from **VS Code**: 7 | 8 | ```powershell 9 | dotnet run 10 | ``` 11 | 12 | If you're running from Visual Studio, press **F5** or **Ctrl+F5** (for no debug run) 13 | 14 | On the main page you will be offered to Log In or to go to a "Fetch data" page 15 | If you choose to go to "Fetch data" page without logging-in, you will be asked to login with a standard UI. 16 | When the application will be logged in, it will try to connect to Azure SQL Database with an [Access Token](https://aka.ms/access-tokens) it acquired for the currently logged-in user. 17 | Successful connection will be indicated when the page will state that the user is logged-in into the database and a table with mock forecast data is displayed. 18 | 19 | ![fetch_data_page](./Client/ReadmeFiles/fetch-data-page.png) 20 | 21 | The page displays a message with user and host names that are values of @user and @host on SQL Database. 22 | 23 | Did the sample not work for you as expected? Did you encounter issues trying this sample? Then please reach out to us using the [GitHub Issues](../../../../issues) page. 24 | 25 | [Consider taking a moment to share your experience with us.](https://forms.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR73pcsbpbxNJuZCMKN0lURpUN0FTWEJKSlBBWEZPV1JQMVBMMzBLNjFHRyQlQCN0PWcu) 26 | 27 |
28 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/fetch-data-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/fetch-data-page.png -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/topology.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/ReadmeFiles/topology.vsdx -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello, @context.User.Identity.Name! 4 | Log out 5 | 6 | 7 | Log in 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 |
9 |
10 | 11 | About 12 |
13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | } 28 | 29 | .top-row a:first-child { 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | } 33 | 34 | @media (max-width: 640.98px) { 35 | .top-row:not(.auth) { 36 | display: none; 37 | } 38 | 39 | .top-row.auth { 40 | justify-content: space-between; 41 | } 42 | 43 | .top-row a, .top-row .btn-link { 44 | margin-left: 0; 45 | } 46 | } 47 | 48 | @media (min-width: 641px) { 49 | .page { 50 | flex-direction: row; 51 | } 52 | 53 | .sidebar { 54 | width: 250px; 55 | height: 100vh; 56 | position: sticky; 57 | top: 0; 58 | } 59 | 60 | .top-row { 61 | position: sticky; 62 | top: 0; 63 | z-index: 1; 64 | } 65 | 66 | .main > div { 67 | padding-left: 2rem !important; 68 | padding-right: 1.5rem !important; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 21 |
22 | 23 | @code { 24 | private bool collapseNavMenu = true; 25 | 26 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 27 | 28 | private void ToggleNavMenu() 29 | { 30 | collapseNavMenu = !collapseNavMenu; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .navbar-toggler { 2 | background-color: rgba(255, 255, 255, 0.1); 3 | } 4 | 5 | .top-row { 6 | height: 3.5rem; 7 | background-color: rgba(0,0,0,0.4); 8 | } 9 | 10 | .navbar-brand { 11 | font-size: 1.1rem; 12 | } 13 | 14 | .oi { 15 | width: 2rem; 16 | font-size: 1.1rem; 17 | vertical-align: text-top; 18 | top: -2px; 19 | } 20 | 21 | .nav-item { 22 | font-size: 0.9rem; 23 | padding-bottom: 0.5rem; 24 | } 25 | 26 | .nav-item:first-of-type { 27 | padding-top: 1rem; 28 | } 29 | 30 | .nav-item:last-of-type { 31 | padding-bottom: 1rem; 32 | } 33 | 34 | .nav-item ::deep a { 35 | color: #d7d7d7; 36 | border-radius: 4px; 37 | height: 3rem; 38 | display: flex; 39 | align-items: center; 40 | line-height: 3rem; 41 | } 42 | 43 | .nav-item ::deep a.active { 44 | background-color: rgba(255,255,255,0.25); 45 | color: white; 46 | } 47 | 48 | .nav-item ::deep a:hover { 49 | background-color: rgba(255,255,255,0.1); 50 | color: white; 51 | } 52 | 53 | @media (min-width: 641px) { 54 | .navbar-toggler { 55 | display: none; 56 | } 57 | 58 | .collapse { 59 | /* Never collapse the sidebar for wide screens */ 60 | display: block; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  10 | 11 | @code { 12 | // Demonstrates how a parent component can supply parameters 13 | [Parameter] 14 | public string Title { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using ms_identity_dotnet_blazor_azure_sql 10 | @using ms_identity_dotnet_blazor_azure_sql.Shared 11 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAd": { 3 | "Instance": "https://login.microsoftonline.com/", 4 | "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", 5 | "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", 6 | "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]", 7 | 8 | //in a production application the secret value should be stored in KeyVault and retreived during configuration step 9 | "ClientSecret": "[Copy the client secret added to the app from the Azure portal]", 10 | 11 | "SignedOutCallbackPath": "/signout-callback-oidc", 12 | "Scopes": "https://database.windows.net/.default", 13 | "OnSignOutRedirectPage": "https://localhost:44348" 14 | }, 15 | "Logging": { 16 | "LogLevel": { 17 | "Default": "Information", 18 | "Microsoft": "Warning", 19 | "Microsoft.Hosting.Lifetime": "Information" 20 | } 21 | }, 22 | "AllowedHosts": "*", 23 | "ConnectionStrings": { 24 | "SqlDbContext": "Server=;database=;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/ms-identity-dotnet-blazor-azure-sql.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | aspnet-ms_identity_dotnet_blazor_azure_sql-155F8F70-0D13-46EE-8E76-E4CA27E4FBC6 6 | 0 7 | ms_identity_dotnet_blazor_azure_sql 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/Images/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/Images/topology.png -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | a, .btn-link { 8 | color: #0366d6; 9 | } 10 | 11 | .btn-primary { 12 | color: #fff; 13 | background-color: #1b6ec2; 14 | border-color: #1861ac; 15 | } 16 | 17 | .content { 18 | padding-top: 1.1rem; 19 | } 20 | 21 | .valid.modified:not([type=checkbox]) { 22 | outline: 1px solid #26b050; 23 | } 24 | 25 | .invalid { 26 | outline: 1px solid red; 27 | } 28 | 29 | .validation-message { 30 | color: red; 31 | } 32 | 33 | #blazor-error-ui { 34 | background: lightyellow; 35 | bottom: 0; 36 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 37 | display: none; 38 | left: 0; 39 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 40 | position: fixed; 41 | width: 100%; 42 | z-index: 1000; 43 | } 44 | 45 | #blazor-error-ui .dismiss { 46 | cursor: pointer; 47 | position: absolute; 48 | right: 0.75rem; 49 | top: 0.5rem; 50 | } 51 | -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-Connect-To-Azure-Sql-Database/Client/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-Connect-To-Azure-Sql-Database/blazorserver-Connect-To-Azure-SQL-Database.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32414.318 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ms-identity-dotnet-blazor-azure-sql", "Client\ms-identity-dotnet-blazor-azure-sql.csproj", "{332801D1-882F-4E98-A14D-4A911363C960}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {332801D1-882F-4E98-A14D-4A911363C960}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {332801D1-882F-4E98-A14D-4A911363C960}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {332801D1-882F-4E98-A14D-4A911363C960}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {332801D1-882F-4E98-A14D-4A911363C960}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3EF2D82D-DAC3-43EE-B776-B103A20D4EF3} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/ReadmeFiles/UserClaims.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/ReadmeFiles/UserClaims.png -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorserver-B2C", "blazorserver-B2C\blazorserver-B2C.csproj", "{AB7D10ED-497D-4F2A-8E87-5945753B046F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {AB7D10ED-497D-4F2A-8E87-5945753B046F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {AB7D10ED-497D-4F2A-8E87-5945753B046F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {AB7D10ED-497D-4F2A-8E87-5945753B046F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {AB7D10ED-497D-4F2A-8E87-5945753B046F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {C9068823-845E-4B42-B827-793AF01DBEE4} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

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

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Pages/UserClaims.razor: -------------------------------------------------------------------------------- 1 | @inherits UserClaimsBase 2 | 3 |

4 | @context.User.Identity.Name has successfully signed-in 5 |

6 | Claims from the ID token 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (var claim in _claims) 16 | { 17 | 18 | 19 | 20 | 21 | } 22 | 23 |
Claim TypeValue
@claim.Type@claim.Value
24 |
-------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Pages/UserClaimsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorserver_B2C.Pages 9 | { 10 | /// 11 | /// Base class for UserClaims component. 12 | /// Retrieves claims present in the ID Token issued by Azure AD. 13 | /// 14 | public class UserClaimsBase : ComponentBase 15 | { 16 | // AuthenticationStateProvider service provides the current user's ClaimsPrincipal data. 17 | [Inject] 18 | private AuthenticationStateProvider AuthenticationStateProvider { get; set; } 19 | 20 | protected string _authMessage; 21 | protected IEnumerable _claims = Enumerable.Empty(); 22 | 23 | // Defines list of claim types that will be displayed after successfull sign-in. 24 | private string[] printClaims = { "name", "idp", "oid", "jobTitle", "emails" }; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetClaimsPrincipalData(); 29 | } 30 | 31 | /// 32 | /// Retrieves user claims for the signed-in user. 33 | /// 34 | /// 35 | private async Task GetClaimsPrincipalData() 36 | { 37 | // Gets an AuthenticationState that describes the current user. 38 | var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 39 | 40 | var user = authState.User; 41 | 42 | // Checks if the user has been authenticated. 43 | if (user.Identity.IsAuthenticated) 44 | { 45 | _authMessage = $"{user.Identity.Name} is authenticated."; 46 | 47 | // Sets the claims value in _claims variable. 48 | // The claims mentioned in printClaims variable are selected only. 49 | _claims = user.Claims.Where(x => printClaims.Contains(x.Type)); 50 | } 51 | else 52 | { 53 | _authMessage = "The user is NOT authenticated."; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace blazorserver_B2C.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | BlazorServer 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | An error has occurred. This application may no longer respond until reloaded. 26 | 27 | 28 | An unhandled exception has occurred. See browser dev tools for details. 29 | 30 | Reload 31 | 🗙 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace blazorserver_B2C 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53223", 7 | "sslPort": 44365 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "BlazorServer": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:44365;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello, @context.User.Identity.Name! 4 | Edit Profile 5 | Log out 6 | 7 | 8 | Log in 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | @Body 14 |
15 | 16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 16 |
17 | 18 | @code { 19 | private bool collapseNavMenu = true; 20 | 21 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 22 | 23 | private void ToggleNavMenu() 24 | { 25 | collapseNavMenu = !collapseNavMenu; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Were we successful in addressing your learning objective? 6 | Do consider taking a moment to share your experience with us. 7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Mvc.Authorization; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Identity.Web; 9 | using Microsoft.Identity.Web.UI; 10 | using System.IdentityModel.Tokens.Jwt; 11 | 12 | namespace blazorserver_B2C 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | // This is required to be instantiated before the OpenIdConnectOptions starts getting configured. 28 | // By default, the claims mapping will map claim names in the old format to accommodate older SAML applications. 29 | // 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' instead of 'roles' 30 | // This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token. 31 | JwtSecurityTokenHandler.DefaultMapInboundClaims = false; 32 | 33 | // Configuration to sign-in users with Azure AD B2C. 34 | services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C"); 35 | 36 | services.AddHttpContextAccessor(); 37 | 38 | services.AddControllersWithViews(options => 39 | { 40 | var policy = new AuthorizationPolicyBuilder() 41 | .RequireAuthenticatedUser() 42 | .Build(); 43 | options.Filters.Add(new AuthorizeFilter(policy)); 44 | }).AddMicrosoftIdentityUI(); 45 | 46 | services.AddRazorPages(); 47 | services.AddServerSideBlazor(); 48 | } 49 | 50 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 51 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 52 | { 53 | if (env.IsDevelopment()) 54 | { 55 | app.UseDeveloperExceptionPage(); 56 | } 57 | else 58 | { 59 | app.UseExceptionHandler("/Error"); 60 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 61 | app.UseHsts(); 62 | } 63 | 64 | app.UseHttpsRedirection(); 65 | app.UseStaticFiles(); 66 | 67 | app.UseRouting(); 68 | 69 | app.UseAuthentication(); 70 | app.UseAuthorization(); 71 | 72 | app.UseEndpoints(endpoints => 73 | { 74 | endpoints.MapControllers(); 75 | endpoints.MapBlazorHub(); 76 | endpoints.MapFallbackToPage("/_Host"); 77 | }); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using blazorserver_B2C 9 | @using blazorserver_B2C.Shared 10 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAdB2C": { 3 | "Instance": "https://fabrikamb2c.b2clogin.com", 4 | "ClientId": "fdb91ff5-5ce6-41f3-bdbd-8267c817015d", 5 | "Domain": "fabrikamb2c.onmicrosoft.com", 6 | "SignedOutCallbackPath": "/signout/B2C_1_susi", 7 | "SignUpSignInPolicyId": "b2c_1_susi", 8 | "ResetPasswordPolicyId": "b2c_1_reset", 9 | "EditProfilePolicyId": "b2c_1_edit_profile" 10 | }, 11 | "Logging": { 12 | "LogLevel": { 13 | "Default": "Information", 14 | "Microsoft": "Warning", 15 | "Microsoft.Hosting.Lifetime": "Information" 16 | } 17 | }, 18 | "AllowedHosts": "*" 19 | } 20 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/blazorserver-B2C.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | aspnet-BlazorServer-262E896B-5298-4EF8-8C09-D6328097A1E7 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/B2C/blazorserver-B2C/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/AppCreationScripts/Cleanup.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [PSCredential] $Credential, 4 | [Parameter(Mandatory=$False, HelpMessage='Tenant ID (This is a GUID which represents the "Directory ID" of the AzureAD tenant into which you want to create the apps')] 5 | [string] $tenantId, 6 | [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script (it defaults to AzureCloud)')] 7 | [string] $azureEnvironmentName 8 | ) 9 | 10 | #Requires -Modules AzureAD -RunAsAdministrator 11 | 12 | 13 | if ($null -eq (Get-Module -ListAvailable -Name "AzureAD")) { 14 | Install-Module "AzureAD" -Scope CurrentUser 15 | } 16 | Import-Module AzureAD 17 | $ErrorActionPreference = "Stop" 18 | 19 | Function Cleanup 20 | { 21 | if (!$azureEnvironmentName) 22 | { 23 | $azureEnvironmentName = "AzureCloud" 24 | } 25 | 26 | <# 27 | .Description 28 | This function removes the Azure AD applications for the sample. These applications were created by the Configure.ps1 script 29 | #> 30 | 31 | # $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant 32 | # into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD. 33 | 34 | # Login to Azure PowerShell (interactive if credentials are not already provided: 35 | # you'll need to sign-in with creds enabling your to create apps in the tenant) 36 | if (!$Credential -and $TenantId) 37 | { 38 | $creds = Connect-AzureAD -TenantId $tenantId -AzureEnvironmentName $azureEnvironmentName 39 | } 40 | else 41 | { 42 | if (!$TenantId) 43 | { 44 | $creds = Connect-AzureAD -Credential $Credential -AzureEnvironmentName $azureEnvironmentName 45 | } 46 | else 47 | { 48 | $creds = Connect-AzureAD -TenantId $tenantId -Credential $Credential -AzureEnvironmentName $azureEnvironmentName 49 | } 50 | } 51 | 52 | if (!$tenantId) 53 | { 54 | $tenantId = $creds.Tenant.Id 55 | } 56 | $tenant = Get-AzureADTenantDetail 57 | $tenantName = ($tenant.VerifiedDomains | Where-Object { $_._Default -eq $True }).Name 58 | 59 | # Removes the applications 60 | Write-Host "Cleaning-up applications from tenant '$tenantName'" 61 | 62 | Write-Host "Removing 'webApp' (WebApp-blazor-server) if needed" 63 | Get-AzureADApplication -Filter "DisplayName eq 'WebApp-blazor-server'" | ForEach-Object {Remove-AzureADApplication -ObjectId $_.ObjectId } 64 | $apps = Get-AzureADApplication -Filter "DisplayName eq 'WebApp-blazor-server'" 65 | if ($apps) 66 | { 67 | Remove-AzureADApplication -ObjectId $apps.ObjectId 68 | } 69 | 70 | foreach ($app in $apps) 71 | { 72 | Remove-AzureADApplication -ObjectId $app.ObjectId 73 | Write-Host "Removed WebApp-blazor-server.." 74 | } 75 | # also remove service principals of this app 76 | Get-AzureADServicePrincipal -filter "DisplayName eq 'WebApp-blazor-server'" | ForEach-Object {Remove-AzureADServicePrincipal -ObjectId $_.Id -Confirm:$false} 77 | 78 | } 79 | 80 | Cleanup -Credential $Credential -tenantId $TenantId -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/AppCreationScripts/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sample": { 3 | "Title": "Enable your Blazor Server app to sign-in users with the Microsoft identity platform", 4 | "Level": 200, 5 | "Client": "ASP.NET Core Blazor Server", 6 | "RepositoryUrl": "ms-identity-blazor-server", 7 | "Endpoint": "AAD v2.0" 8 | }, 9 | 10 | /* 11 | This section describes the Azure AD Applications to configure, and their dependencies 12 | */ 13 | "AADApps": [ 14 | { 15 | "Id": "webApp", 16 | "Name": "WebApp-blazor-server", 17 | "Kind": "WebApp", 18 | "Audience": "AzureADMyOrg", 19 | "HomePage": "https://localhost:44318/", 20 | "ReplyUrls": "https://localhost:44318/, https://localhost:44318/signin-oidc", 21 | "LogoutUrl": "https://localhost:44318/signout-oidc" 22 | } 23 | ], 24 | 25 | /* 26 | This section describes how to update the code in configuration files from the apps coordinates, once the apps 27 | are created in Azure AD. 28 | Each section describes a configuration file, for one of the apps, it's type (XML, JSon, plain text), its location 29 | with respect to the root of the sample, and the mappping (which string in the config file is mapped to which value 30 | */ 31 | "CodeConfiguration": [ 32 | { 33 | "App": "webApp", 34 | "SettingKind": "JSON", 35 | "SettingFile": "\\..\\blazorserver-singleOrg\\appsettings.json", 36 | "Mappings": [ 37 | { 38 | "key": "ClientId", 39 | "value": ".AppId" 40 | }, 41 | { 42 | "key": "TenantId", 43 | "value": "$tenantId" 44 | }, 45 | { 46 | "key": "Domain", 47 | "value": "$tenantName" 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/ReadmeFiles/UserClaims.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/ReadmeFiles/UserClaims.png -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorserver-singleOrg", "blazorserver-singleOrg\blazorserver-singleOrg.csproj", "{2FF54779-8716-4816-910F-62278E3D0D71}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2FF54779-8716-4816-910F-62278E3D0D71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {2FF54779-8716-4816-910F-62278E3D0D71}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {2FF54779-8716-4816-910F-62278E3D0D71}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {2FF54779-8716-4816-910F-62278E3D0D71}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {C9068823-845E-4B42-B827-793AF01DBEE4} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

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

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Pages/UserClaims.razor: -------------------------------------------------------------------------------- 1 | @inherits UserClaimsBase 2 | 3 |

4 | @context.User.Identity.Name has successfully signed-in 5 |

6 | Claims from the ID token 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (var claim in _claims) 16 | { 17 | 18 | 19 | 20 | 21 | } 22 | 23 |
Claim TypeValue
@claim.Type@claim.Value
24 |
-------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Pages/UserClaimsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorserver_singleOrg.Pages 9 | { 10 | /// 11 | /// Base class for UserClaims component. 12 | /// Retrieves claims present in the ID Token issued by Azure AD. 13 | /// 14 | public class UserClaimsBase : ComponentBase 15 | { 16 | // AuthenticationStateProvider service provides the current user's ClaimsPrincipal data. 17 | [Inject] 18 | private AuthenticationStateProvider AuthenticationStateProvider { get; set; } 19 | 20 | protected string _authMessage; 21 | protected IEnumerable _claims = Enumerable.Empty(); 22 | 23 | // Defines list of claim types that will be displayed after successfull sign-in. 24 | private string[] printClaims = { "name", "preferred_username", "tid", "oid" }; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetClaimsPrincipalData(); 29 | } 30 | 31 | /// 32 | /// Retrieves user claims for the signed-in user. 33 | /// 34 | /// 35 | private async Task GetClaimsPrincipalData() 36 | { 37 | // Gets an AuthenticationState that describes the current user. 38 | var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 39 | 40 | var user = authState.User; 41 | 42 | // Checks if the user has been authenticated. 43 | if (user.Identity.IsAuthenticated) 44 | { 45 | _authMessage = $"{user.Identity.Name} is authenticated."; 46 | 47 | // Sets the claims value in _claims variable. 48 | // The claims mentioned in printClaims variable are selected only. 49 | _claims = user.Claims.Where(x => printClaims.Contains(x.Type)); 50 | } 51 | else 52 | { 53 | _authMessage = "The user is NOT authenticated."; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace blazorserver_singleOrg.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | BlazorServer 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | An error has occurred. This application may no longer respond until reloaded. 26 | 27 | 28 | An unhandled exception has occurred. See browser dev tools for details. 29 | 30 | Reload 31 | 🗙 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace blazorserver_singleOrg 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53223", 7 | "sslPort": 44318 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "BlazorServer": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:44318;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello, @context.User.Identity.Name! 4 | Log out 5 | 6 | 7 | Log in 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | @Body 14 |
15 | 16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 16 |
17 | 18 | @code { 19 | private bool collapseNavMenu = true; 20 | 21 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 22 | 23 | private void ToggleNavMenu() 24 | { 25 | collapseNavMenu = !collapseNavMenu; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Were we successful in addressing your learning objective? 6 | Do consider taking a moment to share your experience with us. 7 |
8 |
9 |
-------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Mvc.Authorization; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Identity.Web; 9 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 10 | using Microsoft.Identity.Web.UI; 11 | using System.IdentityModel.Tokens.Jwt; 12 | 13 | namespace blazorserver_singleOrg 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | // This is required to be instantiated before the OpenIdConnectOptions starts getting configured. 29 | // By default, the claims mapping will map claim names in the old format to accommodate older SAML applications. 30 | // 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' instead of 'roles' 31 | // This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token. 32 | JwtSecurityTokenHandler.DefaultMapInboundClaims = false; 33 | 34 | // Add authentication with Microsoft identity platform. 35 | services.AddMicrosoftIdentityWebAppAuthentication(Configuration); 36 | 37 | services.AddHttpContextAccessor(); 38 | 39 | services.AddControllersWithViews(options => 40 | { 41 | var policy = new AuthorizationPolicyBuilder() 42 | .RequireAuthenticatedUser() 43 | .Build(); 44 | options.Filters.Add(new AuthorizeFilter(policy)); 45 | }).AddMicrosoftIdentityUI(); 46 | 47 | services.AddRazorPages(); 48 | services.AddServerSideBlazor(); 49 | } 50 | 51 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 52 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 53 | { 54 | if (env.IsDevelopment()) 55 | { 56 | app.UseDeveloperExceptionPage(); 57 | } 58 | else 59 | { 60 | app.UseExceptionHandler("/Error"); 61 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 62 | app.UseHsts(); 63 | } 64 | 65 | app.UseHttpsRedirection(); 66 | app.UseStaticFiles(); 67 | 68 | app.UseRouting(); 69 | 70 | app.UseAuthentication(); 71 | app.UseAuthorization(); 72 | 73 | app.UseEndpoints(endpoints => 74 | { 75 | endpoints.MapControllers(); 76 | endpoints.MapBlazorHub(); 77 | endpoints.MapFallbackToPage("/_Host"); 78 | }); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using blazorserver_singleOrg 9 | @using blazorserver_singleOrg.Shared 10 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAd": { 3 | "Instance": "https://login.microsoftonline.com/", 4 | "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", 5 | "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", 6 | "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]", 7 | "CallbackPath": "/signin-oidc" 8 | }, 9 | "Logging": { 10 | "LogLevel": { 11 | "Default": "Information", 12 | "Microsoft": "Warning", 13 | "Microsoft.Hosting.Lifetime": "Information" 14 | } 15 | }, 16 | "AllowedHosts": "*" 17 | } 18 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/blazorserver-singleOrg.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0 5 | aspnet-BlazorServer-262E896B-5298-4EF8-8C09-D6328097A1E7 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-OIDC/MyOrg/blazorserver-singleOrg/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/AppCreationScripts/Cleanup.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [PSCredential] $Credential, 4 | [Parameter(Mandatory=$False, HelpMessage='Tenant ID (This is a GUID which represents the "Directory ID" of the AzureAD tenant into which you want to create the apps')] 5 | [string] $tenantId, 6 | [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script (it defaults to AzureCloud)')] 7 | [string] $azureEnvironmentName 8 | ) 9 | 10 | #Requires -Modules AzureAD -RunAsAdministrator 11 | 12 | 13 | if ($null -eq (Get-Module -ListAvailable -Name "AzureAD")) { 14 | Install-Module "AzureAD" -Scope CurrentUser 15 | } 16 | Import-Module AzureAD 17 | $ErrorActionPreference = "Stop" 18 | 19 | Function Cleanup 20 | { 21 | if (!$azureEnvironmentName) 22 | { 23 | $azureEnvironmentName = "AzureCloud" 24 | } 25 | 26 | <# 27 | .Description 28 | This function removes the Azure AD applications for the sample. These applications were created by the Configure.ps1 script 29 | #> 30 | 31 | # $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant 32 | # into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD. 33 | 34 | # Login to Azure PowerShell (interactive if credentials are not already provided: 35 | # you'll need to sign-in with creds enabling your to create apps in the tenant) 36 | if (!$Credential -and $TenantId) 37 | { 38 | $creds = Connect-AzureAD -TenantId $tenantId -AzureEnvironmentName $azureEnvironmentName 39 | } 40 | else 41 | { 42 | if (!$TenantId) 43 | { 44 | $creds = Connect-AzureAD -Credential $Credential -AzureEnvironmentName $azureEnvironmentName 45 | } 46 | else 47 | { 48 | $creds = Connect-AzureAD -TenantId $tenantId -Credential $Credential -AzureEnvironmentName $azureEnvironmentName 49 | } 50 | } 51 | 52 | if (!$tenantId) 53 | { 54 | $tenantId = $creds.Tenant.Id 55 | } 56 | $tenant = Get-AzureADTenantDetail 57 | $tenantName = ($tenant.VerifiedDomains | Where-Object { $_._Default -eq $True }).Name 58 | 59 | # Removes the applications 60 | Write-Host "Cleaning-up applications from tenant '$tenantName'" 61 | 62 | Write-Host "Removing 'webApp' (WebApp-blazor-server-call-graph) if needed" 63 | Get-AzureADApplication -Filter "DisplayName eq 'WebApp-blazor-server-call-graph'" | ForEach-Object {Remove-AzureADApplication -ObjectId $_.ObjectId } 64 | $apps = Get-AzureADApplication -Filter "DisplayName eq 'WebApp-blazor-server-call-graph'" 65 | if ($apps) 66 | { 67 | Remove-AzureADApplication -ObjectId $apps.ObjectId 68 | } 69 | 70 | foreach ($app in $apps) 71 | { 72 | Remove-AzureADApplication -ObjectId $app.ObjectId 73 | Write-Host "Removed WebApp-blazor-server-call-graph.." 74 | } 75 | # also remove service principals of this app 76 | Get-AzureADServicePrincipal -filter "DisplayName eq 'WebApp-blazor-server-call-graph'" | ForEach-Object {Remove-AzureADServicePrincipal -ObjectId $_.Id -Confirm:$false} 77 | 78 | } 79 | 80 | Cleanup -Credential $Credential -tenantId $TenantId -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/AppCreationScripts/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sample": { 3 | "Title": "Call Microsoft Graph on behalf-of the signed-in users in your Blazor Server Application", 4 | "Level": 200, 5 | "Client": "ASP.NET Core Blazor Server", 6 | "RepositoryUrl": "ms-identity-blazor-server", 7 | "Endpoint": "AAD v2.0" 8 | }, 9 | 10 | /* 11 | This section describes the Azure AD Applications to configure, and their dependencies 12 | */ 13 | "AADApps": [ 14 | { 15 | "Id": "webApp", 16 | "Name": "WebApp-blazor-server-call-graph", 17 | "Kind": "WebApp", 18 | "Audience": "AzureADMyOrg", 19 | "HomePage": "https://localhost:44318/", 20 | "ReplyUrls": "https://localhost:44318/, https://localhost:44318/signin-oidc", 21 | "LogoutUrl": "https://localhost:44318/signout-oidc", 22 | "PasswordCredentials": "Auto", 23 | "RequiredResourcesAccess": [ 24 | { 25 | "Resource": "Microsoft Graph", 26 | "DelegatedPermissions": [ "User.Read" ] 27 | } 28 | ] 29 | } 30 | ], 31 | 32 | /* 33 | This section describes how to update the code in configuration files from the apps coordinates, once the apps 34 | are created in Azure AD. 35 | Each section describes a configuration file, for one of the apps, it's type (XML, JSon, plain text), its location 36 | with respect to the root of the sample, and the mappping (which string in the config file is mapped to which value 37 | */ 38 | "CodeConfiguration": [ 39 | { 40 | "App": "webApp", 41 | "SettingKind": "Text", 42 | "SettingFile": "\\..\\blazorserver-calls-MS-graph\\appsettings.json", 43 | "Mappings": [ 44 | { 45 | "key": "ClientId", 46 | "value": ".AppId" 47 | }, 48 | { 49 | "key": "TenantId", 50 | "value": "$tenantId" 51 | }, 52 | { 53 | "key": "Domain", 54 | "value": "$tenantName" 55 | }, 56 | { 57 | "key": "ClientSecret", 58 | "value": ".AppKey" 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/ReadmeFiles/UserClaims.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/ReadmeFiles/UserClaims.png -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/ReadmeFiles/UserProfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/ReadmeFiles/UserProfile.png -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30611.23 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorserver-calls-MS-graph", "blazorserver-calls-MS-graph\blazorserver-calls-MS-graph.csproj", "{779FE6FD-B1AD-4CFC-927D-592851166752}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {779FE6FD-B1AD-4CFC-927D-592851166752}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {779FE6FD-B1AD-4CFC-927D-592851166752}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {779FE6FD-B1AD-4CFC-927D-592851166752}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {779FE6FD-B1AD-4CFC-927D-592851166752}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {44AB1D4B-8B10-45BC-8CCF-65B55A808523} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 |

Sorry, there's nothing at this address.

9 |
10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

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

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/ShowProfile.razor: -------------------------------------------------------------------------------- 1 | @page "/showprofile" 2 | 3 | @using Microsoft.Identity.Web 4 | @using Microsoft.Graph 5 | @inject Microsoft.Graph.GraphServiceClient GraphServiceClient 6 | @inject MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler 7 | 8 |

Me

9 | 10 |

This component demonstrates fetching data from a service.

11 | 12 | @if (user == null) 13 | { 14 |

Loading...

15 | } 16 | else 17 | { 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 42 | 43 |
PropertyValue
Name@user.DisplayName
Photo 30 | @{ 31 | if (photo != null) 32 | { 33 | 34 | } 35 | else 36 | { 37 |

NO PHOTO

38 |

Check user profile in Azure Active Directory to add a photo.

39 | } 40 | } 41 |
44 | } 45 | 46 | @code { 47 | User user; 48 | string photo; 49 | 50 | protected override async Task OnInitializedAsync() 51 | { 52 | try 53 | { 54 | user = await GraphServiceClient.Me.Request().GetAsync(); 55 | photo = await GetPhoto(); 56 | } 57 | catch (Exception ex) 58 | { 59 | ConsentHandler.HandleException(ex); 60 | } 61 | } 62 | 63 | protected async Task GetPhoto() 64 | { 65 | string photo; 66 | 67 | try 68 | { 69 | using (var photoStream = await GraphServiceClient.Me.Photo.Content.Request().GetAsync()) 70 | { 71 | byte[] photoByte = ((System.IO.MemoryStream)photoStream).ToArray(); 72 | photo = Convert.ToBase64String(photoByte); 73 | this.StateHasChanged(); 74 | } 75 | 76 | } 77 | catch (Exception) 78 | { 79 | photo = null; 80 | } 81 | return photo; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/UserClaims.razor: -------------------------------------------------------------------------------- 1 | @inherits UserClaimsBase 2 | 3 |

4 | @context.User.Identity.Name has successfully signed-in 5 |

6 | Claims from the ID token 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (var claim in _claims) 16 | { 17 | 18 | 19 | 20 | 21 | } 22 | 23 |
Claim TypeValue
@claim.Type@claim.Value
24 |
-------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/UserClaimsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorserver_calls_MS_graph.Pages 9 | { 10 | /// 11 | /// Base class for UserClaims component. 12 | /// Retrieves claims present in the ID Token issued by Azure AD. 13 | /// 14 | public class UserClaimsBase : ComponentBase 15 | { 16 | // AuthenticationStateProvider service provides the current user's ClaimsPrincipal data. 17 | [Inject] 18 | private AuthenticationStateProvider AuthenticationStateProvider { get; set; } 19 | 20 | protected string _authMessage; 21 | protected IEnumerable _claims = Enumerable.Empty(); 22 | 23 | // Defines list of claim types that will be displayed after successfull sign-in. 24 | private string[] printClaims = { "name", "preferred_username", "tid", "oid" }; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetClaimsPrincipalData(); 29 | } 30 | 31 | /// 32 | /// Retrieves user claims for the signed-in user. 33 | /// 34 | /// 35 | private async Task GetClaimsPrincipalData() 36 | { 37 | // Gets an AuthenticationState that describes the current user. 38 | var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 39 | 40 | var user = authState.User; 41 | 42 | // Checks if the user has been authenticated. 43 | if (user.Identity.IsAuthenticated) 44 | { 45 | _authMessage = $"{user.Identity.Name} is authenticated."; 46 | 47 | // Sets the claims value in _claims variable. 48 | // The claims mentioned in printClaims variable are selected only. 49 | _claims = user.Claims.Where(x => printClaims.Contains(x.Type)); 50 | } 51 | else 52 | { 53 | _authMessage = "The user is NOT authenticated."; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/UserProfile.razor: -------------------------------------------------------------------------------- 1 | @page "/profile" 2 | @using Microsoft.AspNetCore.Authorization 3 | @attribute [Authorize] 4 | @inherits UserProfileBase 5 | 6 |

User Profile

7 | @{ 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
PropertyValue
DisplayName @_user.DisplayName
UserPrincipalName @_user.UserPrincipalName
24 | } 25 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/UserProfileBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.Graph; 3 | using Microsoft.Identity.Web; 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace blazorserver_calls_MS_graph.Pages 8 | { 9 | /// 10 | /// Base class for UserProfile component. 11 | /// Injects GraphServiceClient and calls Microsoft Graph /me endpoint. 12 | /// 13 | public class UserProfileBase : ComponentBase 14 | { 15 | [Inject] 16 | GraphServiceClient GraphClient { get; set; } 17 | [Inject] 18 | MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler { get; set; } 19 | 20 | protected User _user = new User(); 21 | protected override async Task OnInitializedAsync() 22 | { 23 | await GetUserProfile(); 24 | } 25 | 26 | /// 27 | /// Retrieves user information from Microsoft Graph /me endpoint. 28 | /// 29 | /// 30 | private async Task GetUserProfile() 31 | { 32 | try 33 | { 34 | var request = GraphClient.Me.Request(); 35 | _user = await request.GetAsync(); 36 | } 37 | catch (Exception ex) 38 | { 39 | Console.WriteLine(ex.Message); 40 | ConsentHandler.HandleException(ex); 41 | } 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace blazorserver_calls_MS_graph.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | blazorserver-calls-MS-graph 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | An error has occurred. This application may no longer respond until reloaded. 26 | 27 | 28 | An unhandled exception has occurred. See browser dev tools for details. 29 | 30 | Reload 31 | 🗙 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace blazorserver_calls_MS_graph 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:21348", 7 | "sslPort": 44318 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "blazorserver-calls-MS-graph": { 19 | "commandName": "Project", 20 | "dotnetRunMessages": "true", 21 | "launchBrowser": true, 22 | "applicationUrl": "https://localhost:44318;http://localhost:5000", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello, @context.User.Identity.Name! 4 | Log out 5 | 6 | 7 | Log in 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | @Body 14 |
15 | 16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 21 |
22 | 23 | @code { 24 | private bool collapseNavMenu = true; 25 | 26 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 27 | 28 | private void ToggleNavMenu() 29 | { 30 | collapseNavMenu = !collapseNavMenu; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | Were we successful in addressing your learning objective? 6 | Do consider taking a moment to share your experience with us. 7 |
8 |
9 |
-------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using blazorserver_calls_MS_graph 9 | @using blazorserver_calls_MS_graph.Shared 10 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAd": { 3 | "Instance": "https://login.microsoftonline.com/", 4 | "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", 5 | "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", 6 | "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]", 7 | "ClientSecret": "[Copy the client secret added to the app from the Azure portal]", 8 | //"ClientCertificates" : [ 9 | //], 10 | "CallbackPath": "/signin-oidc" 11 | }, 12 | "DownstreamApi": { 13 | /* 14 | 'Scopes' contains space separated scopes of the Web API you want to call. This can be: 15 | - a scope for a V2 application (for instance api:b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user) 16 | - a scope corresponding to a V1 application (for instance /.default, where is the 17 | App ID URI of a legacy v1 Web application 18 | Applications are registered in the https:portal.azure.com portal. 19 | */ 20 | "BaseUrl": "https://graph.microsoft.com/v1.0", 21 | "Scopes": "user.read" 22 | }, 23 | "Logging": { 24 | "LogLevel": { 25 | "Default": "Information", 26 | "Microsoft": "Warning", 27 | "Microsoft.Hosting.Lifetime": "Information" 28 | } 29 | }, 30 | "AllowedHosts": "*" 31 | } 32 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/blazorserver-calls-MS-graph.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-graph-user/Call-MSGraph/blazorserver-calls-MS-graph/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

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

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/ToDoPages/CommonForm.razor: -------------------------------------------------------------------------------- 1 | @using ToDoListModel 2 | 3 | 4 |
5 |
6 |
7 |
8 |
9 | 12 |
13 |
14 | Back to List 15 |
16 |
17 | 18 | @code { 19 | [Parameter] public ToDo ToDoItem { get; set; } 20 | [Parameter] public string ButtonText { get; set; } = "Save"; 21 | [Parameter] public EventCallback OnValidSubmit { get; set; } 22 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/ToDoPages/Create.razor: -------------------------------------------------------------------------------- 1 | @page "/create" 2 | 3 | @using ToDoListModel 4 | 5 | @inject ToDoListService ToDoListService 6 | @inject NavigationManager Navigation 7 | 8 |

Create Task

9 | 10 | 12 | 13 | @code { 14 | protected ToDo toDo = new ToDo(); 15 | protected async Task AddTask() 16 | { 17 | await ToDoListService.AddAsync(toDo); 18 | Navigation.NavigateTo("todolist"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/ToDoPages/Edit.razor: -------------------------------------------------------------------------------- 1 | @page "/edit/{Id:int}" 2 | 3 | @using ToDoListModel 4 | 5 | @inject ToDoListService ToDoListService 6 | @inject NavigationManager Navigation 7 | 8 |

Edit Task

9 | 10 | 12 | 13 | @code { 14 | [Parameter] public int Id { get; set; } 15 | ToDo toDo = new ToDo(); 16 | protected async override Task OnParametersSetAsync() 17 | { 18 | toDo = await ToDoListService.GetAsync(Id); 19 | } 20 | protected async Task EditTask() 21 | { 22 | await ToDoListService.EditAsync(toDo); 23 | Navigation.NavigateTo("todolist"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/ToDoPages/ToDoList.razor: -------------------------------------------------------------------------------- 1 | @page "/todolist" 2 | @inherits ToDoListBase 3 | 4 |

ToDo List

5 |

6 | Create New 7 |

8 | 9 | 10 | 11 | 14 | 17 | 20 | 23 | 24 | 25 | 26 | @foreach (var item in toDoList) 27 | { 28 | 29 | 32 | 35 | 38 | 42 | 43 | } 44 | 45 |
12 | Id 13 | 15 | Title 16 | 18 | Owner 19 | 21 | Actions 22 |
30 | @item.Id 31 | 33 | @item.Title 34 | 36 | @item.Owner 37 | 39 | Edit 40 | 41 |
46 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/ToDoPages/ToDoListBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.Identity.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using ToDoListModel; 7 | 8 | namespace blazorserver_client.Pages.ToDoPages 9 | { 10 | 11 | public class ToDoListBase : ComponentBase 12 | { 13 | [Inject] 14 | ToDoListService ToDoListService { get; set; } 15 | 16 | [Inject] 17 | MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler { get; set; } 18 | 19 | [Inject] 20 | NavigationManager Navigation { get; set; } 21 | 22 | protected IEnumerable toDoList = new List(); 23 | 24 | protected ToDo toDo = new ToDo(); 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetToDoListService(); 29 | } 30 | 31 | /// 32 | /// Gets all todo list items. 33 | /// 34 | /// 35 | [AuthorizeForScopes(ScopeKeySection = "TodoList:TodoListScope")] 36 | private async Task GetToDoListService() 37 | { 38 | try 39 | { 40 | toDoList = await ToDoListService.GetAsync(); 41 | } 42 | catch (Exception ex) 43 | { 44 | Console.WriteLine(ex.Message); 45 | 46 | // Process the exception from a user challenge 47 | ConsentHandler.HandleException(ex); 48 | } 49 | } 50 | 51 | /// 52 | /// Deletes the selected item then retrieves the todo list. 53 | /// 54 | /// 55 | /// 56 | protected async Task DeleteItem(int Id) 57 | { 58 | await ToDoListService.DeleteAsync(Id); 59 | await GetToDoListService(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/UserClaims.razor: -------------------------------------------------------------------------------- 1 | @inherits UserClaimsBase 2 | 3 |

4 | @context.User.Identity.Name has successfully signed-in 5 |

6 | Claims from the ID token 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (var claim in _claims) 16 | { 17 | 18 | 19 | 20 | 21 | } 22 | 23 |
Claim TypeValue
@claim.Type@claim.Value
24 |
-------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/UserClaimsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorserver_client.Pages 9 | { 10 | /// 11 | /// Base class for UserClaims component. 12 | /// Retrieves claims present in the ID Token issued by Azure AD. 13 | /// 14 | public class UserClaimsBase : ComponentBase 15 | { 16 | // AuthenticationStateProvider service provides the current user's ClaimsPrincipal data. 17 | [Inject] 18 | private AuthenticationStateProvider AuthenticationStateProvider { get; set; } 19 | 20 | protected string _authMessage; 21 | protected IEnumerable _claims = Enumerable.Empty(); 22 | 23 | // Defines list of claim types that will be displayed after successfull sign-in. 24 | private string[] printClaims = { "name", "jobTitle", "city" }; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetClaimsPrincipalData(); 29 | } 30 | 31 | /// 32 | /// Retrieves user claims for the signed-in user. 33 | /// 34 | /// 35 | private async Task GetClaimsPrincipalData() 36 | { 37 | // Gets an AuthenticationState that describes the current user. 38 | var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 39 | 40 | var user = authState.User; 41 | 42 | // Checks if the user has been authenticated. 43 | if (user.Identity.IsAuthenticated) 44 | { 45 | _authMessage = $"{user.Identity.Name} is authenticated."; 46 | 47 | // Sets the claims value in _claims variable. 48 | // The claims mentioned in printClaims variable are selected only. 49 | _claims = user.Claims.Where(x => printClaims.Contains(x.Type)); 50 | } 51 | else 52 | { 53 | _authMessage = "The user is NOT authenticated."; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace blazorserver_client.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | BlazorServer 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | An error has occurred. This application may no longer respond until reloaded. 26 | 27 | 28 | An unhandled exception has occurred. See browser dev tools for details. 29 | 30 | Reload 31 | 🗙 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace blazorserver_client 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53223", 7 | "sslPort": 44365 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "BlazorServer": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:44365;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello, @context.User.Identity.Name! 4 | Edit Profile 5 | Log out 6 | 7 | 8 | Log in 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | @Body 14 |
15 | 16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 21 |
22 | 23 | @code { 24 | private bool collapseNavMenu = true; 25 | 26 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 27 | 28 | private void ToggleNavMenu() 29 | { 30 | collapseNavMenu = !collapseNavMenu; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Were we successful in addressing your learning objective? 6 | Do consider taking a moment to share your experience with us. 7 |
8 |
9 |
-------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Mvc.Authorization; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Identity.Web; 9 | using Microsoft.Identity.Web.UI; 10 | using System.IdentityModel.Tokens.Jwt; 11 | 12 | namespace blazorserver_client 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | // Add authentication with Microsoft identity platform. 28 | // EnableTokenAcquisitionToCallDownstreamApi adds support for the web app to acquire tokens to call the web API. 29 | services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C") 30 | .EnableTokenAcquisitionToCallDownstreamApi(new string[] { Configuration["TodoList:TodoListScope"] }) 31 | .AddInMemoryTokenCaches(); 32 | 33 | services.AddHttpContextAccessor(); 34 | 35 | // Enables to add client service to use the HttpClient by dependency injection. 36 | services.AddToDoListService(Configuration); 37 | 38 | services.AddControllersWithViews(options => 39 | { 40 | var policy = new AuthorizationPolicyBuilder() 41 | .RequireAuthenticatedUser() 42 | .Build(); 43 | options.Filters.Add(new AuthorizeFilter(policy)); 44 | }).AddMicrosoftIdentityUI(); 45 | 46 | services.AddRazorPages(); 47 | 48 | // Add the incremental consent and conditional access handler for Blazor server side pages. 49 | services.AddServerSideBlazor() 50 | .AddMicrosoftIdentityConsentHandler(); 51 | } 52 | 53 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 54 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 55 | { 56 | if (env.IsDevelopment()) 57 | { 58 | app.UseDeveloperExceptionPage(); 59 | } 60 | else 61 | { 62 | app.UseExceptionHandler("/Error"); 63 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 64 | app.UseHsts(); 65 | } 66 | 67 | app.UseHttpsRedirection(); 68 | app.UseStaticFiles(); 69 | 70 | app.UseRouting(); 71 | 72 | app.UseAuthentication(); 73 | app.UseAuthorization(); 74 | 75 | app.UseEndpoints(endpoints => 76 | { 77 | endpoints.MapControllers(); 78 | endpoints.MapBlazorHub(); 79 | endpoints.MapFallbackToPage("/_Host"); 80 | }); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using blazorserver_client 9 | @using blazorserver_client.Shared 10 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAdB2C": { 3 | "Instance": "https://fabrikamb2c.b2clogin.com", 4 | "ClientId": "fdb91ff5-5ce6-41f3-bdbd-8267c817015d", 5 | "Domain": "fabrikamb2c.onmicrosoft.com", 6 | "SignedOutCallbackPath": "/signout/B2C_1_susi", 7 | "SignUpSignInPolicyId": "b2c_1_susi", 8 | "ResetPasswordPolicyId": "b2c_1_reset", 9 | "EditProfilePolicyId": "b2c_1_edit_profile", 10 | "ClientSecret": "X330F3#92!z614M4" 11 | }, 12 | "TodoList": { 13 | /* 14 | TodoListScope is the scope of the Web API you want to call. This can be: "api://8f085429-c424-45c4-beb3-75f6f0a7924f/user_impersonation", 15 | - a scope for a V2 application (for instance api://b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user) 16 | - a scope corresponding to a V1 application (for instance /user_impersonation, where is the 17 | clientId of a V1 application, created in the https://portal.azure.com portal. 18 | */ 19 | "TodoListScope": "https://fabrikamb2c.onmicrosoft.com/tasks/access_as_user", 20 | "TodoListBaseAddress": "https://localhost:44332" 21 | 22 | }, 23 | "Logging": { 24 | "LogLevel": { 25 | "Default": "Information", 26 | "Microsoft": "Warning", 27 | "Microsoft.Hosting.Lifetime": "Information" 28 | } 29 | }, 30 | "AllowedHosts": "*" 31 | } 32 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/blazorserver-client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0 5 | aspnet-BlazorServer-262E896B-5298-4EF8-8C09-D6328097A1E7 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Client/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/Client/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-your-API/B2C/ReadmeFiles/ToDoList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/ReadmeFiles/ToDoList.png -------------------------------------------------------------------------------- /WebApp-your-API/B2C/ReadmeFiles/UserClaims.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/ReadmeFiles/UserClaims.png -------------------------------------------------------------------------------- /WebApp-your-API/B2C/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/B2C/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/AuthorizationPolicies/ScopesRequirement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.Identity.Web; 6 | using System.Linq; 7 | using System.Security.Claims; 8 | using System.Threading.Tasks; 9 | 10 | namespace TodoListService.AuthorizationPolicies 11 | { 12 | /// 13 | /// Requirement used in authorization policies, to check if the scope claim has at least one of the requirement values. 14 | /// Since the class also extends AuthorizationHandler, its dependency injection is done out of the box. 15 | /// 16 | public class ScopesRequirement : AuthorizationHandler, IAuthorizationRequirement 17 | { 18 | string[] _acceptedScopes; 19 | 20 | public ScopesRequirement(params string[] acceptedScopes) 21 | { 22 | _acceptedScopes = acceptedScopes; 23 | } 24 | 25 | /// 26 | /// AuthorizationHandler that will check if the scope claim has at least one of the requirement values 27 | /// 28 | protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, 29 | ScopesRequirement requirement) 30 | { 31 | // If there are no scopes, do not process 32 | if (!context.User.Claims.Any(x => x.Type == ClaimConstants.Scope) 33 | && !context.User.Claims.Any(y => y.Type == ClaimConstants.Scp)) 34 | { 35 | return Task.CompletedTask; 36 | } 37 | 38 | Claim scopeClaim = context?.User?.FindFirst(ClaimConstants.Scp); 39 | 40 | if (scopeClaim == null) 41 | scopeClaim = context?.User?.FindFirst(ClaimConstants.Scope); 42 | 43 | if (scopeClaim != null && scopeClaim.Value.Split(' ').Intersect(requirement._acceptedScopes).Any()) 44 | { 45 | context.Succeed(requirement); 46 | } 47 | 48 | return Task.CompletedTask; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Controllers/ToDoListController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using ToDoListModel; 7 | 8 | namespace TodoListService.Controllers 9 | { 10 | [Authorize] 11 | [Route("api/[controller]")] 12 | public class TodoListController : Controller 13 | { 14 | // In-memory TodoList 15 | private static readonly Dictionary TodoStore = new Dictionary(); 16 | 17 | private readonly IHttpContextAccessor _contextAccessor; 18 | 19 | public TodoListController(IHttpContextAccessor contextAccessor) 20 | { 21 | this._contextAccessor = contextAccessor; 22 | } 23 | 24 | // GET: api/values 25 | [HttpGet] 26 | public IEnumerable Get() 27 | { 28 | string owner = User.Identity.Name; 29 | return TodoStore.Values.Where(x => x.Owner == owner); 30 | } 31 | 32 | // GET: api/values 33 | [HttpGet("{id}", Name = "Get")] 34 | public ToDo Get(int id) 35 | { 36 | return TodoStore.Values.FirstOrDefault(t => t.Id == id); 37 | } 38 | 39 | [HttpDelete("{id}")] 40 | public void Delete(int id) 41 | { 42 | TodoStore.Remove(id); 43 | } 44 | 45 | // POST api/values 46 | [HttpPost] 47 | public IActionResult Post([FromBody] ToDo todo) 48 | { 49 | int id = 1; 50 | if (TodoStore.Count > 0) 51 | { 52 | id = TodoStore.Values.OrderByDescending(x => x.Id).FirstOrDefault().Id + 1; 53 | } 54 | ToDo todonew = new ToDo() { Id = id, Owner = HttpContext.User.Identity.Name, Title = todo.Title }; 55 | TodoStore.Add(id, todonew); 56 | 57 | return Ok(todo); 58 | } 59 | 60 | // PATCH api/values 61 | [HttpPatch("{id}")] 62 | public IActionResult Patch(int id, [FromBody] ToDo todo) 63 | { 64 | if (id != todo.Id) 65 | { 66 | return NotFound(); 67 | } 68 | 69 | if (TodoStore.Values.FirstOrDefault(x => x.Id == id) == null) 70 | { 71 | return NotFound(); 72 | } 73 | 74 | TodoStore.Remove(id); 75 | TodoStore.Add(id, todo); 76 | 77 | return Ok(todo); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace TodoListService 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IHostBuilder CreateHostBuilder(string[] args) => 17 | Host.CreateDefaultBuilder(args) 18 | .ConfigureWebHostDefaults(webBuilder => 19 | { 20 | webBuilder.UseStartup(); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44332", 7 | "sslPort": 44332 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "https://localhost:44332/", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "TodoListService": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "http://localhost:1040/" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets.user" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Identity.Web; 10 | 11 | using Microsoft.AspNetCore.Authentication.JwtBearer; 12 | using TodoListService.AuthorizationPolicies; 13 | 14 | namespace TodoListService 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api 29 | services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 30 | .AddMicrosoftIdentityWebApi(options => 31 | { 32 | Configuration.Bind("AzureAdB2C", options); 33 | 34 | options.TokenValidationParameters.NameClaimType = "name"; 35 | }, 36 | options => { Configuration.Bind("AzureAdB2C", options); }); 37 | 38 | services.AddControllers(); 39 | services.AddAuthorization(options => 40 | { 41 | // Create policy to check for the scope 'read' 42 | options.AddPolicy("ReadScope", 43 | policy => policy.Requirements.Add(new ScopesRequirement(Configuration["ReadScope"]))); 44 | }); 45 | } 46 | 47 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 48 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 49 | { 50 | if (env.IsDevelopment()) 51 | { 52 | // Since IdentityModel version 5.2.1 (or since Microsoft.AspNetCore.Authentication.JwtBearer version 2.2.0), 53 | // PII hiding in log files is enabled by default for GDPR concerns. 54 | // For debugging/development purposes, one can enable additional detail in exceptions by setting IdentityModelEventSource.ShowPII to true. 55 | // Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true; 56 | app.UseDeveloperExceptionPage(); 57 | } 58 | else 59 | { 60 | app.UseHsts(); 61 | } 62 | 63 | app.UseHttpsRedirection(); 64 | 65 | app.UseRouting(); 66 | app.UseAuthentication(); 67 | app.UseAuthorization(); 68 | 69 | app.UseEndpoints(endpoints => 70 | { 71 | endpoints.MapControllers(); 72 | }); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/ToDoListService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0 5 | aspnet-TodoListService-03230DB1-5145-408C-A48B-BE3DAFC56C30 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAdB2C": { 3 | "Instance": "https://fabrikamb2c.b2clogin.com", 4 | "ClientId": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6", 5 | "Domain": "fabrikamb2c.onmicrosoft.com", 6 | "SignedOutCallbackPath": "/signout/B2C_1_susi", 7 | "SignUpSignInPolicyId": "b2c_1_susi" 8 | }, 9 | "ReadScope": "access_as_user", 10 | "Kestrel": { 11 | "Endpoints": { 12 | "Http": { 13 | "Url": "https://localhost:44332" 14 | } 15 | } 16 | }, 17 | "Logging": { 18 | "LogLevel": { 19 | "Default": "Warning" 20 | } 21 | }, 22 | "AllowedHosts": "*" 23 | } 24 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/ToDoListModel/ToDo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ToDoListModel 4 | { 5 | public class ToDo 6 | { 7 | public int Id { get; set; } 8 | 9 | public string Title { get; set; } 10 | 11 | public string Owner { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/ToDoListModel/ToDoListModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebApp-your-API/B2C/blazorserver-Calls-WebAPI-B2C.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorserver-client", "Client\blazorserver-client.csproj", "{FC25A49B-59C3-4387-8C3D-C860FF8040B5}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ToDoListService", "Service\ToDoListService.csproj", "{CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ToDoListModel", "ToDoListModel\ToDoListModel.csproj", "{12168CBF-92E5-4866-87A6-C2214E27AC59}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {C9068823-845E-4B42-B827-793AF01DBEE4} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/AppCreationScripts/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sample": { 3 | "Title": "Enable your Blazor Server to sign-in users and call Web API with the Microsoft identity platform", 4 | "Level": 200, 5 | "Client": "ASP.NET Core Blazor Server", 6 | "Service": "ASP.NET Core Web API", 7 | "RepositoryUrl": "ms-identity-blazor-server", 8 | "Endpoint": "AAD v2.0" 9 | }, 10 | 11 | /* 12 | This section describes the Azure AD Applications to configure, and their dependencies 13 | */ 14 | "AADApps": [ 15 | { 16 | "Id": "service", 17 | "Name": "ToDoListService-aspnetcore", 18 | "Kind": "WebApi", 19 | "Audience": "AzureADMyOrg", 20 | "HomePage": "https://localhost:44351" 21 | 22 | }, 23 | { 24 | "Id": "webApp", 25 | "Name": "WebApp-calls-API-blazor-server", 26 | "Kind": "WebApp", 27 | "Audience": "AzureADMyOrg", 28 | "HomePage": "https://localhost:44318/", 29 | "ReplyUrls": "https://localhost:44318/, https://localhost:44318/signin-oidc", 30 | "LogoutUrl": "https://localhost:44318/signout-oidc", 31 | "PasswordCredentials": "Auto", 32 | "RequiredResourcesAccess": [ 33 | { 34 | "Resource": "service", 35 | "DelegatedPermissions": [ "access_as_user" ] 36 | } 37 | ] 38 | } 39 | ], 40 | 41 | /* 42 | This section describes how to update the code in configuration files from the apps coordinates, once the apps 43 | are created in Azure AD. 44 | Each section describes a configuration file, for one of the apps, it's type (XML, JSon, plain text), its location 45 | with respect to the root of the sample, and the mappping (which string in the config file is mapped to which value 46 | */ 47 | "CodeConfiguration": [ 48 | { 49 | "App": "service", 50 | "SettingKind": "Text", 51 | "SettingFile": "\\..\\Service\\appsettings.json", 52 | "Mappings": [ 53 | { 54 | "key": "Domain", 55 | "value": "$tenantName" 56 | }, 57 | { 58 | "key": "TenantId", 59 | "value": "$tenantId" 60 | }, 61 | { 62 | "key": "ClientId", 63 | "value": "service.AppId" 64 | } 65 | ] 66 | }, 67 | { 68 | "App": "webApp", 69 | "SettingKind": "JSON", 70 | "SettingFile": "\\..\\Client\\appsettings.json", 71 | "Mappings": [ 72 | { 73 | "key": "ClientId", 74 | "value": ".AppId" 75 | }, 76 | { 77 | "key": "TenantId", 78 | "value": "$tenantId" 79 | }, 80 | { 81 | "key": "Domain", 82 | "value": "$tenantName" 83 | }, 84 | { 85 | "key": "ClientSecret", 86 | "value": ".AppKey" 87 | }, 88 | { 89 | "key": "TodoListScope", 90 | "value": "service.Scope" 91 | }, 92 | { 93 | "key": "TodoListBaseAddress", 94 | "value": "service.HomePage" 95 | } 96 | ] 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

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

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/ToDoPages/CommonForm.razor: -------------------------------------------------------------------------------- 1 | @using ToDoListModel 2 | 3 | 4 |
5 |
6 |
7 |
8 |
9 | 12 |
13 |
14 | Back to List 15 |
16 |
17 | 18 | @code { 19 | [Parameter] public ToDo ToDoItem { get; set; } 20 | [Parameter] public string ButtonText { get; set; } = "Save"; 21 | [Parameter] public EventCallback OnValidSubmit { get; set; } 22 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/ToDoPages/Create.razor: -------------------------------------------------------------------------------- 1 | @page "/create" 2 | 3 | @using ToDoListModel 4 | @using Microsoft.Identity.Abstractions 5 | 6 | @inject NavigationManager Navigation 7 | @inject IDownstreamApi _downstreamApi 8 | 9 |

Create Task

10 | 11 | 13 | 14 | @code { 15 | protected ToDo toDo = new ToDo(); 16 | 17 | protected async Task AddTask() 18 | { 19 | await _downstreamApi.PostForUserAsync("TodoList", toDo); 20 | Navigation.NavigateTo("todolist"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/ToDoPages/Edit.razor: -------------------------------------------------------------------------------- 1 | @page "/edit/{Id:int}" 2 | 3 | @using ToDoListModel 4 | @using Microsoft.Identity.Abstractions 5 | 6 | @inject NavigationManager Navigation 7 | @inject IDownstreamApi _downstreamApi 8 | 9 |

Edit Task

10 | 11 | 13 | 14 | @code { 15 | [Parameter] public int Id { get; set; } 16 | ToDo toDo = new ToDo(); 17 | protected async override Task OnParametersSetAsync() 18 | { 19 | toDo = await _downstreamApi.GetForUserAsync( 20 | "TodoList", 21 | options => options.RelativePath = $"api/todolist/{Id}"); 22 | } 23 | 24 | protected async Task EditTask() 25 | { 26 | await _downstreamApi.PatchForUserAsync( 27 | "TodoList", toDo, 28 | options => options.RelativePath = $"api/todolist/{Id}"); 29 | 30 | Navigation.NavigateTo("todolist"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/ToDoPages/ToDoList.razor: -------------------------------------------------------------------------------- 1 | @page "/todolist" 2 | @inherits ToDoListBase 3 | 4 |

ToDo List

5 |

6 | Create New 7 |

8 | 9 | 10 | 11 | 14 | 17 | 20 | 23 | 24 | 25 | 26 | @foreach (var item in toDoList) 27 | { 28 | 29 | 32 | 35 | 38 | 42 | 43 | } 44 | 45 |
12 | Id 13 | 15 | Title 16 | 18 | Owner 19 | 21 | Actions 22 |
30 | @item.Id 31 | 33 | @item.Title 34 | 36 | @item.Owner 37 | 39 | Edit 40 | 41 |
46 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/ToDoPages/ToDoListBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.Identity.Abstractions; 4 | using Microsoft.Identity.Web; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Net.Http; 8 | using System.Threading.Tasks; 9 | using ToDoListModel; 10 | 11 | namespace blazorserver_client.Pages.ToDoPages 12 | { 13 | 14 | public class ToDoListBase : ComponentBase 15 | { 16 | 17 | [Inject] 18 | MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler { get; set; } 19 | 20 | [Inject] 21 | IDownstreamApi _downstreamApi { get; set; } 22 | 23 | protected IEnumerable toDoList = new List(); 24 | 25 | protected ToDo toDo = new ToDo(); 26 | 27 | protected override async Task OnInitializedAsync() 28 | { 29 | await GetToDoListService(); 30 | } 31 | 32 | /// 33 | /// Gets all todo list items. 34 | /// 35 | /// 36 | [AuthorizeForScopes(ScopeKeySection = "TodoList:TodoListScope")] 37 | private async Task GetToDoListService() 38 | { 39 | try 40 | { 41 | toDoList = await _downstreamApi.GetForUserAsync>("TodoList"); 42 | } 43 | catch (Exception ex) 44 | { 45 | Console.WriteLine(ex.Message); 46 | 47 | // Process the exception from a user challenge 48 | ConsentHandler.HandleException(ex); 49 | } 50 | } 51 | 52 | /// 53 | /// Deletes the selected item then retrieves the todo list. 54 | /// 55 | /// 56 | /// 57 | protected async Task DeleteItem(int Id) 58 | { 59 | await _downstreamApi.DeleteForUserAsync( 60 | "TodoList", toDo, 61 | options => options.RelativePath = $"api/todolist/{Id}"); 62 | await GetToDoListService(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/UserClaims.razor: -------------------------------------------------------------------------------- 1 | @inherits UserClaimsBase 2 | 3 |

4 | @context.User.Identity.Name has successfully signed-in 5 |

6 | Claims from the ID token 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @foreach (var claim in _claims) 16 | { 17 | 18 | 19 | 20 | 21 | } 22 | 23 |
Claim TypeValue
@claim.Type@claim.Value
24 |
25 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/UserClaimsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | 8 | namespace blazorserver_client.Pages 9 | { 10 | /// 11 | /// Base class for UserClaims component. 12 | /// Retrieves claims present in the ID Token issued by Azure AD. 13 | /// 14 | public class UserClaimsBase : ComponentBase 15 | { 16 | // AuthenticationStateProvider service provides the current user's ClaimsPrincipal data. 17 | [Inject] 18 | private AuthenticationStateProvider AuthenticationStateProvider { get; set; } 19 | 20 | protected string _authMessage; 21 | protected IEnumerable _claims = Enumerable.Empty(); 22 | 23 | // Defines list of claim types that will be displayed after successfull sign-in. 24 | private string[] printClaims = { "name", "preferred_username", "tid", "oid" }; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | await GetClaimsPrincipalData(); 29 | } 30 | 31 | /// 32 | /// Retrieves user claims for the signed-in user. 33 | /// 34 | /// 35 | private async Task GetClaimsPrincipalData() 36 | { 37 | // Gets an AuthenticationState that describes the current user. 38 | var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); 39 | 40 | var user = authState.User; 41 | 42 | // Checks if the user has been authenticated. 43 | if (user.Identity.IsAuthenticated) 44 | { 45 | _authMessage = $"{user.Identity.Name} is authenticated."; 46 | 47 | // Sets the claims value in _claims variable. 48 | // The claims mentioned in printClaims variable are selected only. 49 | _claims = user.Claims.Where(x => printClaims.Contains(x.Type)); 50 | } 51 | else 52 | { 53 | _authMessage = "The user is NOT authenticated."; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace blazorserver_client.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | BlazorServer 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | An error has occurred. This application may no longer respond until reloaded. 26 | 27 | 28 | An unhandled exception has occurred. See browser dev tools for details. 29 | 30 | Reload 31 | 🗙 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace blazorserver_client 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53223", 7 | "sslPort": 44318 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "BlazorServer": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:44318;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Shared/LoginDisplay.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Hello, @context.User.Identity.Name! 4 | Log out 5 | 6 | 7 | Log in 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
13 | @Body 14 |
15 | 16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 21 |
22 | 23 | @code { 24 | private bool collapseNavMenu = true; 25 | 26 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 27 | 28 | private void ToggleNavMenu() 29 | { 30 | collapseNavMenu = !collapseNavMenu; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Were we successful in addressing your learning objective? 6 | Do consider taking a moment to share your experience with us. 7 |
8 |
9 |
-------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using blazorserver_client 9 | @using blazorserver_client.Shared 10 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAd": { 3 | "Instance": "https://login.microsoftonline.com/", 4 | "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", 5 | "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", 6 | "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]", 7 | "ClientSecret": "[Copy the client secret added to the app from the Azure portal]", 8 | "CallbackPath": "/signin-oidc", 9 | "SignedOutCallbackPath": "/signout-oidc" 10 | }, 11 | "TodoList": { 12 | // Scopes is the list of scopes of the Web API you want to call. This is usually in the form of: "api://fc3ef71c-43ab-497d-89f0-332787e09c7c/ToDoList.Read", 13 | // - a list of scopes for a V2 application (for instance ["api://b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/ToDoList.Read", "api://b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/ToDoList.ReadWrite"]) 14 | // - a scope corresponding to a V1 application (for instance ["/user_impersonation"], where is the 15 | // clientId of a V1 application, created in the https://portal.azure.com portal. 16 | 17 | "Scopes": [ "api://[Enter_client_ID_service]/ToDoList.Read", "api://[Enter_client_ID_service]/ToDoList.Write" ], 18 | "BaseUrl": "https://localhost:44351/", 19 | "RelativePath": "api/todolist" 20 | }, 21 | "Logging": { 22 | "LogLevel": { 23 | "Default": "Information", 24 | "Microsoft": "Warning", 25 | "Microsoft.Hosting.Lifetime": "Information" 26 | } 27 | }, 28 | "AllowedHosts": "*" 29 | } 30 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/blazorserver-client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0 5 | aspnet-BlazorServer-262E896B-5298-4EF8-8C09-D6328097A1E7 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 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. -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Client/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/Client/wwwroot/favicon.ico -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/ReadmeFiles/ToDoList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/ReadmeFiles/ToDoList.png -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/ReadmeFiles/UserClaims.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/ReadmeFiles/UserClaims.png -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/ReadmeFiles/topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/ms-identity-blazor-server/732d7e3109e03127034edc284841e73701816245/WebApp-your-API/MyOrg/ReadmeFiles/topology.png -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Controllers/ToDoListController.cs: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 Microsoft Corporation 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 all 14 | 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 THE 22 | SOFTWARE. 23 | */ 24 | 25 | using Microsoft.AspNetCore.Authorization; 26 | using Microsoft.AspNetCore.Http; 27 | using Microsoft.AspNetCore.Mvc; 28 | using Microsoft.Identity.Web; 29 | using System.Collections.Generic; 30 | using System.Linq; 31 | using ToDoListModel; 32 | 33 | namespace TodoListService.Controllers 34 | { 35 | [AuthorizeForScopes(Scopes = new[] {"access_as_user"})] 36 | [Route("api/[controller]")] 37 | public class TodoListController : Controller 38 | { 39 | // In-memory TodoList 40 | private static readonly Dictionary TodoStore = new Dictionary(); 41 | 42 | private readonly IHttpContextAccessor _contextAccessor; 43 | 44 | public TodoListController(IHttpContextAccessor contextAccessor) 45 | { 46 | this._contextAccessor = contextAccessor; 47 | } 48 | 49 | // GET: api/values 50 | [HttpGet] 51 | public IEnumerable Get() 52 | { 53 | string owner = User.Identity.Name; 54 | return TodoStore.Values.Where(x => x.Owner == owner); 55 | } 56 | 57 | // GET: api/values 58 | [HttpGet("{id}", Name = "Get")] 59 | public ToDo Get(int id) 60 | { 61 | return TodoStore.Values.FirstOrDefault(t => t.Id == id); 62 | } 63 | 64 | [HttpDelete("{id}")] 65 | public void Delete(int id) 66 | { 67 | TodoStore.Remove(id); 68 | } 69 | 70 | // POST api/values 71 | [HttpPost] 72 | public IActionResult Post([FromBody] ToDo todo) 73 | { 74 | int id = 1; 75 | if (TodoStore.Count > 0) 76 | { 77 | id = TodoStore.Values.OrderByDescending(x => x.Id).FirstOrDefault().Id + 1; 78 | } 79 | ToDo todonew = new ToDo() { Id = id, Owner = HttpContext.User.Identity.Name, Title = todo.Title }; 80 | TodoStore.Add(id, todonew); 81 | 82 | return Ok(todo); 83 | } 84 | 85 | // PATCH api/values 86 | [HttpPatch("{id}")] 87 | public IActionResult Patch(int id, [FromBody] ToDo todo) 88 | { 89 | if (id != todo.Id) 90 | { 91 | return NotFound(); 92 | } 93 | 94 | if (TodoStore.Values.FirstOrDefault(x => x.Id == id) == null) 95 | { 96 | return NotFound(); 97 | } 98 | 99 | TodoStore.Remove(id); 100 | TodoStore.Add(id, todo); 101 | 102 | return Ok(todo); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace TodoListService 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | 16 | public static IHostBuilder CreateHostBuilder(string[] args) => 17 | Host.CreateDefaultBuilder(args) 18 | .ConfigureWebHostDefaults(webBuilder => 19 | { 20 | webBuilder.UseStartup(); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44351", 7 | "sslPort": 44351 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "https://localhost:44351/", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "TodoListService": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "http://localhost:1040/" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "secrets1": { 4 | "type": "secrets.user" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Identity.Web; 10 | 11 | using Microsoft.AspNetCore.Authentication.JwtBearer; 12 | 13 | namespace TodoListService 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api 28 | services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 29 | .AddMicrosoftIdentityWebApi(Configuration); 30 | 31 | services.AddControllers(); 32 | } 33 | 34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 36 | { 37 | if (env.IsDevelopment()) 38 | { 39 | // Since IdentityModel version 5.2.1 (or since Microsoft.AspNetCore.Authentication.JwtBearer version 2.2.0), 40 | // PII hiding in log files is enabled by default for GDPR concerns. 41 | // For debugging/development purposes, one can enable additional detail in exceptions by setting IdentityModelEventSource.ShowPII to true. 42 | // Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true; 43 | app.UseDeveloperExceptionPage(); 44 | } 45 | else 46 | { 47 | app.UseHsts(); 48 | } 49 | 50 | app.UseHttpsRedirection(); 51 | 52 | app.UseRouting(); 53 | app.UseAuthentication(); 54 | app.UseAuthorization(); 55 | 56 | app.UseEndpoints(endpoints => 57 | { 58 | endpoints.MapControllers(); 59 | }); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/ToDoListService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0 5 | aspnet-TodoListService-03230DB1-5145-408C-A48B-BE3DAFC56C30 6 | 0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AzureAd": { 3 | "Instance": "https://login.microsoftonline.com/", 4 | "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", 5 | "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", 6 | "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]" 7 | }, 8 | "Kestrel": { 9 | "Endpoints": { 10 | "Http": { 11 | "Url": "https://localhost:44351" 12 | } 13 | } 14 | }, 15 | "Logging": { 16 | "LogLevel": { 17 | "Default": "Warning" 18 | } 19 | }, 20 | "AllowedHosts": "*" 21 | } 22 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/ToDoListModel/ToDo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ToDoListModel 4 | { 5 | public class ToDo 6 | { 7 | public int Id { get; set; } 8 | 9 | public string Title { get; set; } 10 | 11 | public string Owner { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/ToDoListModel/ToDoListModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebApp-your-API/MyOrg/blazorserver-Calls-WebAPI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorserver-client", "Client\blazorserver-client.csproj", "{FC25A49B-59C3-4387-8C3D-C860FF8040B5}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ToDoListService", "Service\ToDoListService.csproj", "{CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ToDoListModel", "ToDoListModel\ToDoListModel.csproj", "{12168CBF-92E5-4866-87A6-C2214E27AC59}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {FC25A49B-59C3-4387-8C3D-C860FF8040B5}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {CFC92EB3-F97C-4E92-8A1C-E7E8EA6E50D4}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {12168CBF-92E5-4866-87A6-C2214E27AC59}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {C9068823-845E-4B42-B827-793AF01DBEE4} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | msbuild /t:restore buildAllSlns.proj 2 | msbuild buildAllSlns.proj -------------------------------------------------------------------------------- /buildAllSlns.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------