Logto client integration

Este conteúdo não está disponível em sua língua ainda.

⭐ Community Toolkit

The Aspire Community Toolkit Logto client integration configures ASP.NET Core authentication against a Logto instance. Use OIDC for interactive browser sign-in or JWT bearer authentication to protect an API.

This page assumes a Logto resource is referenced from the consuming app in your AppHost. For resource setup, see Logto hosting integration.

The Logto resource exposes this exact connection-string structure:

Connection string format
Endpoint={primaryEndpointUrl}

For a host endpoint at port 3001, an example is:

Example connection string
Endpoint=http://localhost:3001

Referencing a resource named logto supplies ConnectionStrings__logto to the consuming process. .NET configuration reads it as ConnectionStrings:logto.

Aspire also exposes the following connection properties:

PropertyEnvironment variable for logtoValue
HostLOGTO_HOSTHost of the primary HTTP endpoint.
PortLOGTO_PORTPort of the primary HTTP endpoint as resolved for the consuming app.
UriLOGTO_URIFull primary HTTP endpoint URL.

The values are resolved for the consuming resource’s network context. Don’t assume a container port or localhost address when reading them. The admin endpoint is not part of this connection contract.

Install 📦 CommunityToolkit.Aspire.Logto.Client in the consuming ASP.NET Core project:

.NET CLI — Add CommunityToolkit.Aspire.Logto.Client package
dotnet add package CommunityToolkit.Aspire.Logto.Client

The extension methods are in the Microsoft.Extensions.Hosting namespace. They register authentication services, not a keyed client or a Logto Management API service.

Create a traditional web application in the Logto Admin Console. Store its application ID and secret in the consuming project’s configuration. For local development, use .NET user secrets:

Terminal in the web project
dotnet user-secrets init
dotnet user-secrets set "Aspire:Logto:Client:AppId" "<application-id>"
dotnet user-secrets set "Aspire:Logto:Client:AppSecret" "<application-secret>"

Call AddLogtoOIDC on the host application builder:

Program.cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.AddLogtoOIDC("logto", oidcOptions: options =>
{
options.RequireHttpsMetadata = !builder.Environment.IsDevelopment();
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", () => "Visit /signin to sign in.");
app.MapGet("/signin", async (HttpContext context) =>
{
await context.ChallengeAsync("Logto",
new AuthenticationProperties { RedirectUri = "/me" });
});
app.MapGet("/me", (HttpContext context) => new
{
Name = context.User.Identity?.Name,
IsAuthenticated = context.User.Identity?.IsAuthenticated
}).RequireAuthorization();
app.Run();

The connectionName value, logto, must match the AppHost resource name. AddLogtoOIDC defaults to the authentication scheme Logto and cookie scheme Logto.Cookie.

Register the consuming web app’s full callback URL in Logto. The underlying .NET SDK defaults to /Callback for sign-in and /SignedOutCallback for sign-out. Match the scheme, host, port, and path of your app. Configure the corresponding sign-out redirect if implementing sign-out.

For an API, call AddLogtoJwtBearer on an AuthenticationBuilder. Supply the API resource identifier registered in Logto as appIdentification:

Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddLogtoJwtBearer("logto",
appIdentification: "https://api.example.com",
configureOptions: options =>
{
options.RequireHttpsMetadata = !builder.Environment.IsDevelopment();
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", () => "API is running.");
app.MapGet("/secure", (HttpContext context) => new
{
Subject = context.User.FindFirst("sub")?.Value
}).RequireAuthorization();
app.Run();

Replace https://api.example.com with the API resource identifier from the Admin Console. This value is an audience, not the browser application’s client ID.

The integration trims a trailing slash from the configured endpoint, then appends /oidc. It uses that URL for both Authority and ValidIssuer, enables issuer and audience validation, and assigns the supplied identifiers to ValidAudiences.

An overload accepts IEnumerable<string> for multiple audiences. The collection must contain at least one identifier, and no identifier can be empty or whitespace. The default authentication scheme is Bearer. The JWT registration requires an endpoint but does not require AppId or AppSecret.

Require the scopes or roles your API needs through ASP.NET Core authorization policies. Validating an audience does not by itself enforce application permissions.

This integration has no AddKeyedLogtoClient API. Use distinct ASP.NET Core authentication schemes to configure multiple identities. For OIDC, use a distinct cookie scheme and configuration section for each registration.

For example, configure separate CustomerLogto and StaffLogto sections with the respective endpoint, application ID, and secret, then register two OIDC handlers:

Program.cs
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.AddLogtoOIDC(
configurationSectionName: "CustomerLogto",
authenticationScheme: "Customer",
cookieScheme: "Customer.Cookie",
oidcOptions: options =>
{
options.CallbackPath = "/customer/callback";
options.SignedOutCallbackPath = "/customer/signed-out";
});
builder.AddLogtoOIDC(
configurationSectionName: "StaffLogto",
authenticationScheme: "Staff",
cookieScheme: "Staff.Cookie",
oidcOptions: options =>
{
options.CallbackPath = "/staff/callback";
options.SignedOutCallbackPath = "/staff/signed-out";
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("StaffOnly", policy =>
{
policy.AddAuthenticationSchemes("Staff.Cookie");
policy.RequireAuthenticatedUser();
});
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/staff", () => "Staff area").RequireAuthorization("StaffOnly");
app.Run();

Challenge the desired OIDC scheme explicitly from your sign-in endpoint. Authentication schemes select handlers; they aren’t .NET dependency injection keyed services.

The multiple-scheme example assigns a distinct sign-in and sign-out callback path to each OIDC handler. Register both complete callback URLs in the corresponding Logto applications.

Outside an AppHost, configure a connection string yourself:

appsettings.json
{
"ConnectionStrings": {
"logto": "Endpoint=https://identity.example.com/"
},
"Aspire": {
"Logto": {
"Client": {
"AppId": "<application-id>"
}
}
}
}

Supply the application secret through user secrets, an environment variable such as Aspire__Logto__Client__AppSecret, or another secret configuration provider.

The connection-string parser accepts an absolute URI directly or a key-value connection string containing an Endpoint whose value is an absolute URI. It returns no endpoint for malformed strings, a missing Endpoint key, or an invalid endpoint URI.

The client binds Logto.AspNetCore.Authentication.LogtoOptions from Aspire:Logto:Client by default. Override the section name with configurationSectionName on either registration API.

appsettings.json
{
"Aspire": {
"Logto": {
"Client": {
"Endpoint": "https://identity.example.com",
"AppId": "<application-id>"
}
}
}
}

The effective settings are resolved in this order:

  1. Bind the chosen configuration section.
  2. If its Endpoint is blank, fill it from the named connection string.
  3. For OIDC, apply the logtoOptions delegate, then require a non-blank Endpoint and AppId.

An endpoint in the configuration section takes precedence over the AppHost-injected connection string. Omit Endpoint from that section when the AppHost should supply it. Passing a connection name does not select a child section under Aspire:Logto:Client.

Only Endpoint, AppId, and AppSecret are copied from the resolved LogtoOptions into the underlying OIDC registration. Other Logto SDK options, such as Scopes, Resource, and CallbackPath, are not forwarded by this wrapper. Use oidcOptions to customize the underlying OpenIdConnectOptions.

The OIDC API accepts a logtoOptions delegate for the resolved Logto settings and an oidcOptions delegate for the named OIDC handler:

Program.cs
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.AddLogtoOIDC("logto",
logtoOptions: options =>
{
options.AppId = builder.Configuration["Identity:AppId"]
?? throw new InvalidOperationException("Configure Identity:AppId.");
options.AppSecret = builder.Configuration["Identity:AppSecret"];
},
oidcOptions: options =>
{
options.CallbackPath = "/auth/callback";
options.Scope.Add("email");
options.RequireHttpsMetadata = !builder.Environment.IsDevelopment();
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/profile", (HttpContext context) => new
{
Name = context.User.Identity?.Name
}).RequireAuthorization();
app.Run();

Register /auth/callback with the consuming app’s full URL in Logto when using this example.

The JWT API’s configureOptions delegate runs after the integration assigns the authority and token-validation parameters. Use it to customize JwtBearerOptions, but preserve issuer and audience validation.

The hosting connection properties work independently of the .NET client package. Use LOGTO_URI as the endpoint for the official Logto SDKs. Supply application credentials separately; they are not injected by the Logto resource reference.

The following local-development web apps read the injected endpoint and provide sign-in and callback routes. Supply LOGTO_APP_ID, LOGTO_APP_SECRET, SESSION_SECRET, and WEB_BASE_URL yourself. Use the full browser-facing URL of the consuming web app for WEB_BASE_URL, without a trailing slash.

Use the Express SDK guide for a Node.js web app:

Terminal
npm install express @logto/express cookie-parser express-session
npm install --save-dev typescript tsx @types/express @types/cookie-parser @types/express-session
app.ts
import express from 'express';
import cookieParser from 'cookie-parser';
import session from 'express-session';
import { handleAuthRoutes, withLogto } from '@logto/express';
import type { LogtoExpressConfig } from '@logto/express';
function required(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(`Configure ${name}.`);
}
return value;
}
const config: LogtoExpressConfig = {
endpoint: required('LOGTO_URI'),
appId: required('LOGTO_APP_ID'),
appSecret: required('LOGTO_APP_SECRET'),
baseUrl: required('WEB_BASE_URL'),
};
const app = express();
app.use(cookieParser());
app.use(
session({
secret: required('SESSION_SECRET'),
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true, sameSite: 'lax' },
})
);
app.use(handleAuthRoutes(config));
app.get('/', withLogto(config), (request, response) => {
response
.type('html')
.send(
request.user.isAuthenticated
? 'Signed in. <a href="/logto/sign-out">Sign out</a>'
: '<a href="/logto/sign-in">Sign in</a>'
);
});
app.listen(Number(process.env.PORT ?? '3000'));
Terminal
npx tsx app.ts

Register {WEB_BASE_URL}/logto/sign-in-callback as the redirect URI and WEB_BASE_URL as the post sign-out redirect URI in Logto. The SDK creates these routes through handleAuthRoutes.

LOGTO_APP_ID, LOGTO_APP_SECRET, SESSION_SECRET, and WEB_BASE_URL are application-defined configuration variables. Use a random 32- or 64-byte value for SESSION_SECRET. PORT controls the consuming web app’s listener, not Logto’s port. Aspire only supplies LOGTO_URI through the Logto connection-property contract.

The .NET client package does not register health checks. The hosting health check checks server readiness, not client credentials, callback registration, or successful token validation.

The client package does not add Logto-specific logging, metrics, or OpenTelemetry instrumentation. Authentication handlers use ASP.NET Core’s logging, including the Microsoft.AspNetCore.Authentication.OpenIdConnect and Microsoft.AspNetCore.Authentication.JwtBearer categories.

Use your app’s existing telemetry configuration for request tracing. View the Logto container’s stdout and stderr in the Aspire dashboard. Keep secrets, tokens, and personally identifiable claims out of diagnostic logs.