Logto#1241
Conversation
- Introduced `CommunityToolkit.Aspire.Hosting.Logto` project for integrating Logto with PostgreSQL and Redis. - Added extension methods for configuring Logto containers, health checks, and resource dependencies. - Created test projects for validating Logto container configuration and health checks. - Added example projects under `examples/logto` showcasing Logto integration with PostgreSQL and Redis. - Updated solution file and package references to include the new Logto project.
- Introduced `CommunityToolkit.Aspire.Hosting.Logto.Client` project for integrating Logto client configuration. - Added `LogtoClientBuilder` for seamless setup of Logto client services in `IHostApplicationBuilder`. - Implemented connection string helper for parsing Logto connection strings. - Updated solution and centralized package references to include the new project.
- Introduced `CommunityToolkit.Aspire.Hosting.Logto.ClientApi` under `examples/logto` to demonstrate Logto client integration. - Added project configuration files (`Program.cs`, `appsettings.json`, `launchSettings.json`) for application setup. - Renamed `AddLogtoClient` to `AddLogtoSDKClient` in `LogtoClientBuilder`. - Updated solution and centralized package references to include the new example project and dependencies.
- Introduced a new test project `CommunityToolkit.Aspire.Hosting.Logto.Client.Tests` for validating Logto client behavior. - Added integration and unit tests for `LogtoClientBuilder` and `LogtoConnectionStringHelper`. - Implemented OIDC authentication and JWT bearer support in `LogtoClientBuilder`. - Extended `Program.cs` in `ClientApi` example with authentication routes (`/me`, `/signin`, `/signout`). - Updated dependencies and centralized package references for added functionalities. - Modified project and solution files to include updated references.
- Updated method names from `AddLogtoSDKClient` to `AddLogtoOIDC` for better alignment with OIDC usage. - Enhanced `AddLogtoOIDC` and `AddLogtoJwtBearer` methods to support additional configuration options. - Added `Microsoft.Extensions.DependencyInjection.Abstractions` package reference to support service registration. - Updated tests to reflect the method renaming and new configuration capabilities. - Extended `Program.cs` in the ClientApi example to include `UseAuthentication` and `UseAuthorization`. - Improved consistency and readability of XML documentation across updated methods. - Centralized package references for additional dependencies in `Directory.Packages.props`.
- Changed the `ClientApi` project to `ClientOIDC` for better alignment with OIDC standards. - Updated method signatures in `LogtoClientBuilder` to use `appIndeficator` instead of `appId` and support multiple audience identifiers. - Improved XML documentation consistency for updated methods. - Adjusted solution, project references, and configuration files to reflect the renaming and API changes.
- Introduced `CommunityToolkit.Aspire.Hosting.Logto.ClientJWT` project under `examples/logto` to demonstrate Logto JWT authentication. - Configured authentication and authorization middleware with Logto's JWT Bearer scheme in `Program.cs`. - Added example routes (`/secure` and `/tokens`) for testing secured endpoint access and token retrieval. - Updated `AppHost` to include `ClientJWT` project as a dependency. - Improved XML documentation for `AddLogtoJwtBearer` methods, including updated parameter descriptions and exception handling.
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1241Or
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1241" |
aaronpowell
left a comment
There was a problem hiding this comment.
Some questions and comments but the main thing is that the client project shouldn't have Hosting in the name (or namespace).
| builder.AddServiceDefaults(); | ||
|
|
||
| builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) | ||
| .AddLogtoJwtBearer("logto", "http://localhost:5072/", |
There was a problem hiding this comment.
Shouldn't the endpoint come from Aspire?
There was a problem hiding this comment.
It does. logto is the Aspire resource name, so the endpoint is resolved from Aspire via .WithReference(logto). The second parameter is the JWT appIdentification/audience, not the Logto endpoint, so I updated the sample to make that clearer.
| config.AppId = "s6zda5bqn1qlsjzaiklqn"; | ||
| config.AppSecret = "Df77aDt13MG3nSTgo8eKZP2HdeSfbed0"; |
There was a problem hiding this comment.
I assume these are things that could come from Aspire
There was a problem hiding this comment.
Not directly from Aspire today. These values are Logto client credentials, so they need to come from a Logto application registration first. Aspire can pass them through configuration/secrets, but it doesn't create the Logto application automatically.
It would be possible to automate that through the Logto Management API, but that would add a separate provisioning workflow, which felt out of scope for this sample.
| <PropertyGroup> | ||
| <Description>.NET Aspire hosting extensions for Logto (includes PostgreSQL and Redis integration).</Description> | ||
| <AdditionalPackageTags>logto redis postgres hosting extensions</AdditionalPackageTags> | ||
| <IsPreview>true</IsPreview> |
There was a problem hiding this comment.
Why are we marking this as preview? Should we be putting Experimental attributes in?
| builderWithResource | ||
| .WithEntrypoint("sh") | ||
| .WithArgs("-c", "npm run cli db seed -- --swe && npm start"); |
There was a problem hiding this comment.
it could be very opaque to the user that the entrypoint is being overridden, what's the reason we do it?
There was a problem hiding this comment.
We override the entrypoint because Logto requires the DB seed step before the app starts in our Aspire scenario, otherwise the container doesn't come up in a usable state. I agree this is not obvious from AddLogtoContainer(), so I can make it explicit either by documenting it clearly or by moving it behind an opt-in method like WithDatabaseSeeding()/WithSeededStartup().
There was a problem hiding this comment.
I think we should move it to a method like WithDatabaseSeeding (or WithSeededStartup - naming things is hard and I'm not fussed either way) just so that we make it obvious.
That is, I assume that Logto will run without having to run this seed right?
| <<<<<<< Logto | ||
| <PackageVersion Include="Logto.AspNetCore.Authentication" Version="0.2.0" /> | ||
| <PackageVersion Include="Microsoft.AspNetCore.Authentication" Version="2.3.0" /> | ||
| <PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" /> | ||
| <PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.0" /> | ||
| <PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" /> | ||
| <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" /> | ||
| ======= | ||
| <PackageVersion Include="AspNetCore.HealthChecks.Network" Version="9.0.0" /> | ||
| >>>>>>> main |
There was a problem hiding this comment.
Think this is a merge gone bad
…ommunityToolkit.Aspire.Hosting.Logto.AppHost.csproj Co-authored-by: Aaron Powell <me@aaron-powell.com>
…kit.Aspire.Hosting.Logto.Client.csproj Co-authored-by: Aaron Powell <me@aaron-powell.com>
…t and package configuration files
- Upgraded `Aspire.AppHost.Sdk` from `13.0.0` to `13.2.0` in `examples/logto/CommunityToolkit.Aspire.Hosting.Logto.AppHost.csproj`. - Added `Microsoft.AspNetCore.Authentication.JwtBearer` and `Microsoft.AspNetCore.Authentication.OpenIdConnect` package versions to `Directory.Packages.props`.
…o JWT configuration - Replaced hardcoded API audience with a `const` string in `Program.cs` for improved readability and maintainability.
…ferences - Renamed `CommunityToolkit.Aspire.Hosting.Logto.Client` to `CommunityToolkit.Aspire.Logto.Client` for improved namespace consistency. - Updated all project, namespace, and solution references to reflect the renaming. - Adjusted example projects (`ClientJWT` and `ClientOIDC`) and `AppHost` references accordingly.
…cing in Logto container
aaronpowell
left a comment
There was a problem hiding this comment.
Need to update the test list to include the new test projects
|
Something wrong? Can it be reopened? |
…and add support for data volume mapping.
…pHost` project reference to test project
…dom host port assignment.
…ed APIs and tests. Streamline naming for consistency.
…toBuilderExtensions`.
|
Can you please reopen and check? |
| builderWithResource | ||
| .WithEntrypoint("sh") | ||
| .WithArgs("-c", "npm run cli db seed -- --swe && npm start"); |
There was a problem hiding this comment.
I think we should move it to a method like WithDatabaseSeeding (or WithSeededStartup - naming things is hard and I'm not fussed either way) just so that we make it obvious.
That is, I assume that Logto will run without having to run this seed right?
| public const string Image = "svhd/logto"; | ||
|
|
||
| /// <summary>1.38</summary> | ||
| public const string Tag = "1.38"; |
There was a problem hiding this comment.
| public const string Tag = "1.38"; | |
| public const string Tag = "1.39"; |
That looks like latest since the PR has been delayed.
|
Need to bump the SDK version on the example to match the rest of repo - that'd be why the tests are failing |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Logto integration to the Aspire Community Toolkit, including a hosting resource for running Logto in an AppHost and a client library for configuring OIDC/JWT authentication from configuration/connection strings, along with examples and test coverage.
Changes:
- Added
CommunityToolkit.Aspire.Hosting.Logtocontainer resource + builder extensions (PostgreSQL/Redis wiring, health checks, env-var helpers). - Added
CommunityToolkit.Aspire.Logto.Clientextensions for OIDC and JWT bearer setup, including connection-string endpoint parsing. - Added examples, tests, solution/workflow wiring, and central package versions needed for the new projects.
Show a summary per file
| File | Description |
|---|---|
| tests/CommunityToolkit.Aspire.Logto.Client.Tests/LogtoConnectionStringHelperTests.cs | Unit tests for extracting Logto endpoint from connection strings. |
| tests/CommunityToolkit.Aspire.Logto.Client.Tests/LogtoClientBuilderTests.cs | Unit tests for client builder validation/config resolution. |
| tests/CommunityToolkit.Aspire.Logto.Client.Tests/LogtoClientBuilderIntegrationTests.cs | Integration tests asserting authentication scheme/options registration. |
| tests/CommunityToolkit.Aspire.Logto.Client.Tests/CommunityToolkit.Aspire.Logto.Client.Tests.csproj | Test project for Logto client integration. |
| tests/CommunityToolkit.Aspire.Hosting.Logto.Tests/ResourceCreationTests.cs | Unit tests asserting Logto hosting resource creation + health check annotation. |
| tests/CommunityToolkit.Aspire.Hosting.Logto.Tests/CommunityToolkit.Aspire.Hosting.Logto.Tests.csproj | Test project for Logto hosting integration. |
| tests/CommunityToolkit.Aspire.Hosting.Logto.Tests/AppHostTest.cs | Docker-based integration test verifying Logto container starts and responds. |
| src/CommunityToolkit.Aspire.Logto.Client/LogtoConnectionStringHelper.cs | Helper to parse/validate endpoint from connection strings. |
| src/CommunityToolkit.Aspire.Logto.Client/LogtoClientBuilder.cs | Client extensions to add Logto OIDC + JWT bearer authentication. |
| src/CommunityToolkit.Aspire.Logto.Client/CommunityToolkit.Aspire.Logto.Client.csproj | Logto client library project definition + package refs. |
| src/CommunityToolkit.Aspire.Hosting.Logto/README.md | Hosting integration documentation for Logto. |
| src/CommunityToolkit.Aspire.Hosting.Logto/LogtoTags.cs | Container image registry/name/tag constants for Logto. |
| src/CommunityToolkit.Aspire.Hosting.Logto/LogtoResource.cs | Logto container resource model + connection string expression. |
| src/CommunityToolkit.Aspire.Hosting.Logto/LogtoBuilderExtensions.cs | Hosting builder extensions for adding/configuring Logto + Postgres/Redis + health checks. |
| src/CommunityToolkit.Aspire.Hosting.Logto/CommunityToolkit.Aspire.Hosting.Logto.csproj | Hosting integration project definition + NuGet metadata. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/Properties/launchSettings.json | Launch profiles for OIDC sample. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/Program.cs | Minimal OIDC client sample using AddLogtoOIDC. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/CommunityToolkit.Aspire.Logto.ClientOIDC.csproj | OIDC sample project definition. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/CommunityToolkit.Aspire.Hosting.Logto.Client.http | HTTP scratch file for OIDC sample. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/appsettings.json | App settings for OIDC sample. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientJWT/Properties/launchSettings.json | Launch profiles for JWT sample. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientJWT/Program.cs | Minimal JWT bearer sample using AddLogtoJwtBearer. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientJWT/CommunityToolkit.Aspire.Logto.ClientJWT.csproj | JWT sample project definition. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientJWT/CommunityToolkit.Aspire.Hosting.Logto.ClientJWT.http | HTTP scratch file for JWT sample. |
| examples/logto/CommunityToolkit.Aspire.Logto.ClientJWT/appsettings.json | App settings for JWT sample. |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.ServiceDefaults/Extensions.cs | ServiceDefaults helpers for the Logto examples (OTel/health/etc.). |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.ServiceDefaults/CommunityToolkit.Aspire.Hosting.Logto.ServiceDefaults.csproj | ServiceDefaults project definition for Logto examples. |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.AppHost/Properties/launchSettings.json | Launch profiles for Logto AppHost example. |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.AppHost/CommunityToolkit.Aspire.Hosting.Logto.AppHost.csproj | AppHost example project definition. |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.AppHost/appsettings.json | AppHost example logging configuration. |
| examples/logto/CommunityToolkit.Aspire.Hosting.Logto.AppHost/AppHost.cs | AppHost wiring for Postgres + Redis + Logto + client sample projects. |
| Directory.Packages.props | Central package versions for Logto/auth-related packages. |
| CommunityToolkit.Aspire.slnx | Adds new Logto src/tests/examples projects to the solution. |
| .github/workflows/tests.yaml | Adds new Logto test projects to CI test matrix. |
Copilot's findings
Comments suppressed due to low confidence (1)
examples/logto/CommunityToolkit.Aspire.Logto.ClientOIDC/Program.cs:17
- The sample sets
RequireHttpsMetadata = false, which disables HTTPS metadata requirement for OIDC and is unsafe outside local development. If this is intended only for local testing, gate it onbuilder.Environment.IsDevelopment()(or clearly document it) to reduce the chance of copying insecure defaults into production.
},oidcOptions: opt =>
{
opt.RequireHttpsMetadata = false;
});
- Files reviewed: 34/34 changed files
- Comments generated: 25
| public sealed class LogtoResource(string name) | ||
| : ContainerResource(name), IResourceWithConnectionString | ||
| { | ||
| internal const string PrimaryEndpointName = "http"; |
| var builder = new ReferenceExpressionBuilder(); | ||
|
|
||
| builder.Append( | ||
| $"Endpoint={PrimaryEndpointName}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); |
| @@ -0,0 +1,66 @@ | |||
| using Aspire.Hosting.ApplicationModel; | |||
|
|
|||
| namespace CommunityToolkit.Aspire.Hosting.Logto; | |||
| using Aspire.Hosting.ApplicationModel; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
|
|
||
| namespace CommunityToolkit.Aspire.Hosting.Logto; |
| public static void WithDeprecationTracing(this IResourceBuilder<LogtoResource> builderWithResource) | ||
| { | ||
| builderWithResource.WithEnvironment("NODE_OPTIONS", "--trace-deprecation"); |
| @@ -0,0 +1,21 @@ | |||
| <Project Sdk="Aspire.AppHost.Sdk/13.2.0"> | |||
| [Fact] | ||
| public void AddLogtoSDKClient_UsesConnectionStringEndpoint_WhenSectionEndpointMissing() | ||
| { | ||
| // Arrange: удаляем Endpoint из секции, оставляем только в connection string | ||
| var extraConfig = new Dictionary<string, string?> | ||
| { | ||
| ["Aspire:Logto:Client:Endpoint"] = null, | ||
| ["ConnectionStrings:Logto"] = "Endpoint=https://logto-from-cs.example.com" | ||
| }; | ||
|
|
||
| var builder = CreateBuilderWithBaseConfig(extraConfig); | ||
|
|
||
| // Act | ||
| builder.AddLogtoOIDC(connectionName: "Logto"); | ||
| using var host = builder.Build(); | ||
|
|
||
| // Assert: как минимум убедимся, что всё собралось | ||
| // и LogtoOptions вообще зарегистрированы (если библиотека их регистрирует) | ||
| var optionsMonitor = host.Services.GetService<IOptionsMonitor<LogtoOptions>>(); |
| using Logto.AspNetCore.Authentication; | ||
| using Microsoft.AspNetCore.Authentication; | ||
| using Microsoft.AspNetCore.Builder; | ||
| using Microsoft.Extensions.Configuration; | ||
| using Microsoft.Extensions.Options; | ||
|
|
| public class LogtoClientBuilderTests | ||
| { | ||
| [Fact] | ||
| public void AddLogtoSDKClient_ThrowsArgumentNull_WhenBuilderIsNull() | ||
| { |
| /// <summary> | ||
| /// Represents a collection of constants for container tags related to the Logto application. | ||
| /// </summary> | ||
| public class LogtoTags | ||
| { | ||
| /// <summary>docker.io</summary> | ||
| public const string Registry = "docker.io"; | ||
|
|
||
| /// <summary>svhd/logto</summary> | ||
| public const string Image = "svhd/logto"; | ||
|
|
||
| /// <summary>1.38</summary> | ||
| public const string Tag = "1.38"; | ||
| } No newline at end of file |
Closes #<ISSUE_NUMBER>
PR Checklist
Other information