Skip to main content

C# / ASP.NET Core Quickstart

Wire LumoAuth into an ASP.NET Core 8 app with the official LumoAuth.AspNetCore package. It registers the SDK from appsettings.json, signs browsers in through OpenID Connect, resolves LumoAuth bearer tokens on API requests, and enforces permissions server-side with [RequirePermission].

Prerequisites​

  • .NET 8 SDK or newer
  • An OAuth client registered with redirect URI https://localhost:5001/signin-lumoauth (the port dotnet run prints).

Register the client in the portal under Applications → New application: enter an Application name, choose Web application, enter the Redirect URI, and click Create application. The client secret is shown once, on the page you land on.

Install​

dotnet new web -o lumo-demo && cd lumo-demo
dotnet add package LumoAuth.AspNetCore

appsettings.json:

{
"LumoAuth": {
"BaseUrl": "https://app.lumoauth.dev",
"OrgId": "your-org-slug",
"ApiKey": "lmk_...",
"Login": {
"ClientId": "lumo_...",
"ClientSecret": "..."
}
}
}

Keep the secrets out of source control: dotnet user-secrets set "LumoAuth:ApiKey" "lmk_..." in development, environment variables (LUMOAUTH_API_KEY, LumoAuth__Login__ClientSecret) in production. Every LumoAuth:* key has an environment-variable fallback.

Use it​

Program.cs
using System.Security.Claims;
using LumoAuth.AspNetCore;
using LumoAuth.AspNetCore.Authentication;
using LumoAuth.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLumoAuth(builder.Configuration); // LumoAuthClient + ILumoAuthorization + [Require*] policies
builder.Services.AddLumoAuthWebAppAuthentication(builder.Configuration) // cookie session + OpenID Connect sign-in (LumoAuth:Login)
.AddLumoAuthBearer(); // and LumoAuth bearer tokens on the same app
builder.Services.AddAuthorization();
builder.Services.AddHealthChecks().AddLumoAuth();

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/", () => "home");

// Browser: an unauthenticated visit redirects to LumoAuth and comes back signed in.
app.MapGet("/dashboard", (ClaimsPrincipal user) => $"Hello {user.FindFirst("name")?.Value ?? user.Identity!.Name}")
.RequireAuthorization();

// API: Authorization: Bearer <LumoAuth access token>
app.MapGet("/api/me", (ClaimsPrincipal user) => new { sub = user.GetLumoAuthSubject(), roles = user.FindAll("roles").Select(c => c.Value) })
.RequireAuthorization(new Microsoft.AspNetCore.Authorization.AuthorizeAttribute { AuthenticationSchemes = LumoAuthDefaults.BearerScheme });

// Permission checks run live against LumoAuth, as the caller.
app.MapPost("/invoices/{id}/approve", (string id) => Results.Ok($"approved {id}"))
.RequirePermission("invoice.approve");

app.MapGet("/documents/{id}", (string id) => Results.Ok($"document {id}"))
.RequireRelation("viewer", "document:{id}");

app.MapDelete("/documents/{id}", async (string id, ILumoAuthorization authz) =>
await authz.IsOwnerAsync($"document:{id}") ? Results.NoContent() : Results.Forbid());

app.MapGet("/logout", (HttpContext context) => context.SignOutAsync());
app.MapHealthChecks("/health");

app.Run();

In MVC controllers the same guards are attributes:

[RequirePermission("document.edit")]
public IActionResult Edit(string id) { ... }

[RequirePermission("document.edit", "document.publish", Mode = RequirementMode.Any)]
public IActionResult Publish(string id) { ... }

[RequireAbac("document", "delete", "{id}")]
public IActionResult Delete(string id) { ... }

Run it​

dotnet run
  • https://localhost:5001/dashboard redirects to LumoAuth, then greets you.
  • curl -H "Authorization: Bearer $TOKEN" https://localhost:5001/api/me returns the token's subject and roles.
  • curl -X POST -H "Authorization: Bearer $TOKEN" https://localhost:5001/invoices/42/approve is 200 when the user holds invoice.approve, 403 otherwise.
  • https://localhost:5001/health reports Healthy while the instance answers.

Without ASP.NET Core​

The LumoAuth package alone serves workers, console apps and agents:

var lumo = LumoAuthClient.FromEnvironment(); // LUMOAUTH_URL, LUMOAUTH_ORG_ID, LUMOAUTH_API_KEY
bool ok = await lumo.Permissions.CheckAsync("document.edit", CheckOptions.ForUser(userId));

var agent = LumoAgent.FromEnvironment(); // AGENT_CLIENT_ID, AGENT_CLIENT_SECRET
if (await agent.IsAllowedAsync("send_email", new { to = "cfo@acme.com" })) { ... }

For sign-in outside the OpenID Connect handler, LumoAuth.Web.AuthorizationCodeFlow runs the authorization-code + PKCE flow against any session store.

Next steps​

Standards used on this page​

Plain nameStandard
Signed HTTP requests (HTTP message signatures)RFC 9421

See the standards reference for what each one covers and how LumoAuth uses it.