Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0'
dotnet-version: '10.0'
include-prerelease: True
- name: Restore dependencies
run: dotnet restore
Expand Down
10 changes: 5 additions & 5 deletions BlazorAuth0Bff/Client/BlazorAuth0Bff.Client.csproj
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.8" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.8" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 5 additions & 5 deletions BlazorAuth0Bff/Server/BlazorAuth0Bff.Server.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>de0b7f31-65d4-46d6-8382-30c94073cf4a</UserSecretsId>
Expand All @@ -13,10 +13,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.1" NoWarn="NU1605" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders" Version="1.0.0-preview.1" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders.TagHelpers" Version="1.0.0-preview.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.8" NoWarn="NU1605" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders" Version="1.3.1" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders.TagHelpers" Version="1.3.1" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion BlazorAuth0Bff/Server/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MyApiUrl": "https://localhost:44390",
"MyApiUrl": "https://localhost:5014",
"AllowedHosts": "*"
//"Auth0": {
// "Domain": "your-domain-in-auth0",
Expand Down
2 changes: 1 addition & 1 deletion BlazorAuth0Bff/Shared/BlazorAuth0Bff.Shared.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using Swashbuckle.AspNetCore.Annotations;
using System.Collections.Generic;

namespace MyApi.Controllers;

/// <summary>
/// API protected with Microsoft.Identity.Web and Microsoft Entra ID
/// scope from App registration used to authorize.
/// </summary>
[SwaggerTag("API protected with Microsoft.Identity.Web and Microsoft Entra ID")]
[AuthorizeForScopes(Scopes = ["api://b2a09168-54e2-4bc4-af92-a710a64ef1fa/access_as_user"],
AuthenticationScheme = "myADscheme")]
[Authorize(AuthenticationSchemes = "myADscheme")]
[ApiController]
[Route("api/[controller]")]
public class AzureADUserOneController : ControllerBase
{
/// <summary>
/// returns data id the correct Microsoft Entra ID access token is used with the correct scope.
/// </summary>
/// <returns>protected data</returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public IEnumerable<string> Get()
{
return new List<string> { "Microsoft Entra ID user one data" };
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using System.Collections.Generic;

namespace MyApi.Controllers;

/// <summary>
/// API protected with Microsoft.Identity.Web and Microsoft Entra ID
/// scope from App registration used to authorize.
/// </summary>
[AuthorizeForScopes(Scopes = ["api://b2a09168-54e2-4bc4-af92-a710a64ef1fa/access_as_user"], AuthenticationScheme = "myADscheme")]
[Authorize(AuthenticationSchemes = "myADscheme")]
[ApiController]
[Route("api/[controller]")]
public class EntraIdUserOneController : ControllerBase
{
/// <summary>
/// returns data id the correct Microsoft Entra ID access token is used with the correct scope.
/// </summary>
/// <returns>protected data</returns>
[HttpGet("")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public IEnumerable<string> Get()
{
return ["Microsoft Entra ID user one data"];
}
}
2 changes: 0 additions & 2 deletions MyApi/Controllers/ServiceTwoController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Collections.Generic;

namespace MyApi.Controllers;
Expand All @@ -10,7 +9,6 @@ namespace MyApi.Controllers;
/// Service access token protected using Auth0
/// protected using "p-service-api-auth0" policy defined in the Startup
/// </summary>
[SwaggerTag("Service access token protected using Auth0 ")]
[Authorize(Policy = "p-service-api-auth0")]
[ApiController]
[Route("api/[controller]")]
Expand Down
2 changes: 0 additions & 2 deletions MyApi/Controllers/UserOneController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Collections.Generic;

namespace MyApi.Controllers;
Expand All @@ -10,7 +9,6 @@ namespace MyApi.Controllers;
/// User access token protected using Auth0
/// protected using "p-user-api-auth0" policy defined in the Startup
/// </summary>
[SwaggerTag("User access token protected using Auth0")]
[Authorize(Policy = "p-user-api-auth0")]
[ApiController]
[Route("api/[controller]")]
Expand Down
26 changes: 13 additions & 13 deletions MyApi/MyApi.csproj
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<UserSecretsId>7b15921c-6a17-41fd-90cc-86a09d128527</UserSecretsId>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Identity.Web" Version="3.7.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders" Version="1.0.0-preview.1" />
<PackageReference Include="Microsoft.Identity.Web" Version="4.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders" Version="1.3.1" />

<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.8">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.2.1" />
</ItemGroup>

</Project>
104 changes: 54 additions & 50 deletions MyApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using MyApi;
using NetEscapades.AspNetCore.SecurityHeaders.Infrastructure;
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

var builder = WebApplication.CreateBuilder(args);

Expand Down Expand Up @@ -54,47 +57,19 @@
options.Audience = "https://auth0-api1";
});

services.AddSwaggerGen(c =>
services.AddOpenApi(options =>
{
c.EnableAnnotations();
// add JWT Authentication
var securityScheme = new OpenApiSecurityScheme
{
Name = "JWT Authentication",
Description = "Enter JWT Bearer token **_only_**",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer", // must be lower case
BearerFormat = "JWT",
Reference = new OpenApiReference
{
Id = JwtBearerDefaults.AuthenticationScheme,
Type = ReferenceType.SecurityScheme
}
};
c.AddSecurityDefinition(securityScheme.Reference.Id, securityScheme);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{securityScheme, Array.Empty<string>()}
});

c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My API",
Version = "v1",
Description = "My API",
Contact = new OpenApiContact
{
Name = "damienbod",
Email = string.Empty,
Url = new Uri("https://damienbod.com/"),
}
});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
//options.UseTransformer((document, context, cancellationToken) =>
//{
// document.Info = new()
// {
// Title = "My API",
// Version = "v1",
// Description = "API for Damien"
// };
// return Task.CompletedTask;
//});
options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

services.AddSingleton<IAuthorizationHandler, UserApiScopeHandler>();
Expand Down Expand Up @@ -130,18 +105,18 @@

app.UseSecurityHeaders();

app.UseSwagger();
app.UseSwaggerUI(c =>
//app.MapOpenApi(); // /openapi/v1.json
app.MapOpenApi("/openapi/v1/openapi.json");
//app.MapOpenApi("/openapi/{documentName}/openapi.json");

app.UseSwaggerUI(options =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "User API");
c.RoutePrefix = string.Empty;
options.SwaggerEndpoint("/openapi/v1/openapi.json", "v1");
});

// only needed for browser clients
// app.UseCors("AllowAllOrigins");

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();
Expand All @@ -150,3 +125,32 @@
app.MapControllers();

app.Run();

internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
var requirements = new Dictionary<string, IOpenApiSecurityScheme>
{
["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer", // "bearer" refers to the header name here
In = ParameterLocation.Header,
BearerFormat = "Json Web Token"
}
};
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = requirements;
}
document.Info = new()
{
Title = "My API Bearer scheme",
Version = "v1",
Description = "API for Damien"
};
}
}
4 changes: 2 additions & 2 deletions MyApi/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"MyApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44390"
"applicationUrl": "https://localhost:5014"
}
}
}
4 changes: 2 additions & 2 deletions RazorMicrosoftEntraID/CallMyApiOne/MyApiOneService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public async Task<List<string>> GetApiDataAsync()
var client = _clientFactory.CreateClient();

var scope = _configuration["MyApiOne:ScopeForAccessToken"];
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new List<string> { scope! });
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync([scope!]);

client.BaseAddress = new Uri(_configuration["MyApiOne:ApiBaseAddress"]!);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var response = await client.GetAsync("api/AzureADUserOne");
var response = await client.GetAsync("api/EntraIdUserOne");
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
Expand Down
2 changes: 1 addition & 1 deletion RazorMicrosoftEntraID/Pages/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

<footer class="border-top footer text-muted">
<div class="container">
&copy; 2025 - Microsoft Entra ID
&copy; 2026 - Microsoft Entra ID
</div>
</footer>

Expand Down
Loading
Loading