Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Keycloak component #4289

Merged
merged 25 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9e8b32b
Add Keycloak component
julioct May 24, 2024
033c190
Use ReferenceExpression and default password generation
julioct May 24, 2024
743cf73
Use tag 24.0
julioct May 25, 2024
24cf23d
Add Keycloak component
julioct Jun 11, 2024
0d34dbc
Remove Keycloak icon
julioct Jun 11, 2024
c2be071
Switch to service discovery and populate full endpoint on host.
julioct Jun 12, 2024
0a03849
Add resource name argument and use service discovery for Keycloak bas…
julioct Jun 12, 2024
9ff4a64
Disable package validation
julioct Jun 12, 2024
742c4a7
Don't set a base address for the HttpClient
julioct Jun 13, 2024
258df28
Remove blank lines in README
julioct Jun 14, 2024
5717d72
Moved realm from AppHost to component
julioct Jun 14, 2024
9f865fd
Extend AuthenticationBuilder instead of IHostApplicationBuilder
julioct Jun 18, 2024
2c3b8f2
Improve docs
julioct Jun 19, 2024
ed2f91e
Add tests
julioct Jun 20, 2024
75b3b49
Use data volume in Playground
julioct Jun 20, 2024
79ca77d
Address feedback
julioct Jul 2, 2024
87ae126
Added WithRealmImport test
julioct Jul 2, 2024
df0e2ca
Address feedback
julioct Jul 5, 2024
89e4861
Address feedback
julioct Jul 9, 2024
4d48146
Use a fixed port
julioct Jul 9, 2024
57e8c0a
Rename component to Aspire.Keycloak.Authentication
julioct Jul 10, 2024
c114b37
Added missing tests
julioct Jul 12, 2024
94b7f8f
Add SuppressFinalPackageVersion for the initial version of the Keyclo…
eerhardt Jul 16, 2024
9f1b503
Minor PR feedback
eerhardt Jul 16, 2024
d8b5a0f
Apply minor feedback
julioct Jul 17, 2024
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
58 changes: 52 additions & 6 deletions Aspire.sln
Original file line number Diff line number Diff line change
Expand Up @@ -502,12 +502,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "python", "python", "{7123AB
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.AppHost", "playground\python\Python.AppHost\Python.AppHost.csproj", "{173BDA6E-F175-4457-BF64-58CD184E9A81}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{C424395C-1235-41A4-BF55-07880A04368C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosting", "Hosting", "{830A89EC-4029-4753-B25A-068BAE37DEC7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Redis.Tests", "tests\Aspire.Hosting.Redis.Tests\Aspire.Hosting.Redis.Tests.csproj", "{1BC02557-B78B-48CE-9D3C-488A6B7672F4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.PostgreSQL.Tests", "tests\Aspire.Hosting.PostgreSQL.Tests\Aspire.Hosting.PostgreSQL.Tests.csproj", "{7425E5B2-BC47-4521-AC40-B8CECA329E08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Qdrant.Tests", "tests\Aspire.Hosting.Qdrant.Tests\Aspire.Hosting.Qdrant.Tests.csproj", "{8E2AA85E-C351-47B4-AF91-58557FAD5840}"
Expand All @@ -518,6 +512,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Python.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.Hosting.Valkey.Tests", "tests\Aspire.Hosting.Valkey.Tests\Aspire.Hosting.Valkey.Tests.csproj", "{1C16DC2D-3B79-4081-AC1E-F3F965C61216}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Keycloak.Authentication", "src\Components\Aspire.Keycloak.Authentication\Aspire.Keycloak.Authentication.csproj", "{C87D9F7D-300A-4880-A7E1-835772749912}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Hosting.Keycloak", "src\Aspire.Hosting.Keycloak\Aspire.Hosting.Keycloak.csproj", "{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "keycloak", "keycloak", "{EBC55A17-B0D6-4E0A-9DC2-7D264E96F631}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.ApiService", "playground\keycloak\Keycloak.ApiService\Keycloak.ApiService.csproj", "{14BA6E7B-1726-4F23-9C32-72B953BC392B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.Web", "playground\keycloak\Keycloak.Web\Keycloak.Web.csproj", "{0BE14FA4-3F09-426D-BF5A-F9102D36DE33}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.AppHost", "playground\keycloak\Keycloak.AppHost\Keycloak.AppHost.csproj", "{C556D61C-7E11-43EC-9098-C8D170FEA905}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Hosting.Keycloak.Tests", "tests\Aspire.Hosting.Keycloak.Tests\Aspire.Hosting.Keycloak.Tests.csproj", "{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Keycloak.Authentication.Tests", "tests\Aspire.Keycloak.Authentication.Tests\Aspire.Keycloak.Authentication.Tests.csproj", "{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1356,6 +1366,34 @@ Global
{1C16DC2D-3B79-4081-AC1E-F3F965C61216}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C16DC2D-3B79-4081-AC1E-F3F965C61216}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C16DC2D-3B79-4081-AC1E-F3F965C61216}.Release|Any CPU.Build.0 = Release|Any CPU
{C87D9F7D-300A-4880-A7E1-835772749912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C87D9F7D-300A-4880-A7E1-835772749912}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C87D9F7D-300A-4880-A7E1-835772749912}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C87D9F7D-300A-4880-A7E1-835772749912}.Release|Any CPU.Build.0 = Release|Any CPU
{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40}.Release|Any CPU.Build.0 = Release|Any CPU
{14BA6E7B-1726-4F23-9C32-72B953BC392B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14BA6E7B-1726-4F23-9C32-72B953BC392B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14BA6E7B-1726-4F23-9C32-72B953BC392B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14BA6E7B-1726-4F23-9C32-72B953BC392B}.Release|Any CPU.Build.0 = Release|Any CPU
{0BE14FA4-3F09-426D-BF5A-F9102D36DE33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BE14FA4-3F09-426D-BF5A-F9102D36DE33}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BE14FA4-3F09-426D-BF5A-F9102D36DE33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BE14FA4-3F09-426D-BF5A-F9102D36DE33}.Release|Any CPU.Build.0 = Release|Any CPU
{C556D61C-7E11-43EC-9098-C8D170FEA905}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C556D61C-7E11-43EC-9098-C8D170FEA905}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C556D61C-7E11-43EC-9098-C8D170FEA905}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C556D61C-7E11-43EC-9098-C8D170FEA905}.Release|Any CPU.Build.0 = Release|Any CPU
{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD}.Release|Any CPU.Build.0 = Release|Any CPU
{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1604,6 +1642,14 @@ Global
{8E2AA85E-C351-47B4-AF91-58557FAD5840} = {830A89EC-4029-4753-B25A-068BAE37DEC7}
{0A83AA67-221E-44B4-9BA9-DC64DC17949E} = {830A89EC-4029-4753-B25A-068BAE37DEC7}
{1C16DC2D-3B79-4081-AC1E-F3F965C61216} = {830A89EC-4029-4753-B25A-068BAE37DEC7}
{C87D9F7D-300A-4880-A7E1-835772749912} = {27381127-6C45-4B4C-8F18-41FF48DFE4B2}
{1F8D77E1-AF1B-4CCA-A2CB-12AB40282B40} = {B80354C7-BE58-43F6-8928-9F3A74AB7F47}
{EBC55A17-B0D6-4E0A-9DC2-7D264E96F631} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
{14BA6E7B-1726-4F23-9C32-72B953BC392B} = {EBC55A17-B0D6-4E0A-9DC2-7D264E96F631}
{0BE14FA4-3F09-426D-BF5A-F9102D36DE33} = {EBC55A17-B0D6-4E0A-9DC2-7D264E96F631}
{C556D61C-7E11-43EC-9098-C8D170FEA905} = {EBC55A17-B0D6-4E0A-9DC2-7D264E96F631}
{5867BAF2-FEF0-4661-BFDE-9ADCDC2921CD} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{48FF09E9-7D33-4A3F-9FF2-4C43A219C7B7} = {C424395C-1235-41A4-BF55-07880A04368C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6DCEDFEC-988E-4CB3-B45B-191EB5086E0C}
Expand Down
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<PackageVersion Include="Azure.Provisioning.WebPubSub" Version="0.1.0-beta.1" />
<!-- ASP.NET Core dependencies -->
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Certificate" Version="$(MicrosoftAspNetCoreAuthenticationCertificatePackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="$(MicrosoftAspNetCoreOpenApiPackageVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.OutputCaching.StackExchangeRedis" Version="$(MicrosoftAspNetCoreOutputCachingStackExchangeRedisPackageVersion)" />
Expand Down
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<MicrosoftExtensionsOptionsPackageVersion>8.0.2</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>8.0.0</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftAspNetCoreAuthenticationCertificatePackageVersion>8.0.6</MicrosoftAspNetCoreAuthenticationCertificatePackageVersion>
<MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>8.0.6</MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>
<MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>8.0.6</MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion>
<MicrosoftAspNetCoreOpenApiPackageVersion>8.0.6</MicrosoftAspNetCoreOpenApiPackageVersion>
<MicrosoftAspNetCoreOutputCachingStackExchangeRedisPackageVersion>8.0.6</MicrosoftAspNetCoreOutputCachingStackExchangeRedisPackageVersion>
Expand Down
14 changes: 14 additions & 0 deletions playground/keycloak/Keycloak.ApiService/Keycloak.ApiService.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Components\Aspire.Keycloak.Authentication\Aspire.Keycloak.Authentication.csproj" />
<ProjectReference Include="..\..\Playground.ServiceDefaults\Playground.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
49 changes: 49 additions & 0 deletions playground/keycloak/Keycloak.ApiService/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
var builder = WebApplication.CreateBuilder(args);

// Add service defaults & Aspire components.
builder.AddServiceDefaults();

// Add services to the container.
builder.Services.AddProblemDetails();

builder.Services.AddAuthentication()
.AddKeycloakJwtBearer("keycloak", realm: "WeatherShop", options =>
{
options.RequireHttpsMetadata = false;
options.Audience = "weather.api";
});

builder.Services.AddAuthorizationBuilder();

var app = builder.Build();

// Configure the HTTP request pipeline.
app.UseExceptionHandler();

var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.RequireAuthorization();

app.MapDefaultEndpoints();

app.Run();

sealed record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5502",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:7492;http://localhost:5502",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions playground/keycloak/Keycloak.ApiService/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
8 changes: 8 additions & 0 deletions playground/keycloak/Keycloak.AppHost/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>

<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

<!-- NOTE: This line is only required because we are using P2P references, not NuGet. It will not exist in real apps. -->
<Import Project="../../../src/Aspire.Hosting.AppHost/build/Aspire.Hosting.AppHost.props" />

</Project>
9 changes: 9 additions & 0 deletions playground/keycloak/Keycloak.AppHost/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>

<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />

<!-- NOTE: These lines are only required because we are using P2P references, not NuGet. They will not exist in real apps. -->
<Import Project="..\..\..\src\Aspire.Hosting.AppHost\build\Aspire.Hosting.AppHost.targets" />
<Import Project="..\..\..\src\Aspire.Hosting.Sdk\SDK\Sdk.targets" />

</Project>
19 changes: 19 additions & 0 deletions playground/keycloak/Keycloak.AppHost/Keycloak.AppHost.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
<UserSecretsId>230093c1-93fe-469d-bcdb-9c8a3c1f699c</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj" IsAspireProjectResource="False" />
<ProjectReference Include="..\..\..\src\Aspire.Hosting.Keycloak\Aspire.Hosting.Keycloak.csproj" IsAspireProjectResource="False" />
<ProjectReference Include="..\Keycloak.ApiService\Keycloak.ApiService.csproj" />
<ProjectReference Include="..\Keycloak.Web\Keycloak.Web.csproj" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions playground/keycloak/Keycloak.AppHost/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var builder = DistributedApplication.CreateBuilder(args);

var keycloak = builder.AddKeycloak("keycloak", 8080)
julioct marked this conversation as resolved.
Show resolved Hide resolved
.WithDataVolume()
.WithRealmImport("../realms");
julioct marked this conversation as resolved.
Show resolved Hide resolved

var apiService = builder.AddProject<Projects.Keycloak_ApiService>("apiservice")
.WithReference(keycloak);

builder.AddProject<Projects.Keycloak_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService);

builder.Build().Run();
julioct marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:17241;http://localhost:15079",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21125",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22112"
}
},
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15079",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19191",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20230"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions playground/keycloak/Keycloak.AppHost/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
}
}
22 changes: 22 additions & 0 deletions playground/keycloak/Keycloak.Web/AuthorizationHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Authentication;

namespace Keycloak.Web;

public class AuthorizationHandler(IHttpContextAccessor httpContextAccessor) : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var httpContext = httpContextAccessor.HttpContext ??
throw new InvalidOperationException("No HttpContext available from the IHttpContextAccessor!");

var accessToken = await httpContext.GetTokenAsync("access_token");

if (!string.IsNullOrEmpty(accessToken))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}

return await base.SendAsync(request, cancellationToken);
}
}
20 changes: 20 additions & 0 deletions playground/keycloak/Keycloak.Web/Components/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="Keycloak.Web.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>

<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@using Microsoft.AspNetCore.Components.Authorization
@using System.Security.Claims;
@using System.Security.Principal;
@using System.Security.Cryptography
@using System.Text
@using System.IdentityModel.Tokens.Jwt

<AuthorizeView>
<Authorized>
<div>
<span>Welcome @context.User.Identity?.Name!</span>
<form method="post" action="authentication/logout" style="display:inline;">
<AntiforgeryToken />
<button type="submit" class="btn btn-link">Logout</button>
</form>
</div>
</Authorized>
<NotAuthorized>
<a href="authentication/login" class="btn btn-primary">Login</a>
</NotAuthorized>
</AuthorizeView>
Loading