ASP.NET Core (OpenID Connect)
See the Applications overview for prerequisites, configuration endpoints, and available scopes.
ASP.NET Core includes built-in OpenID Connect middleware via the Microsoft.AspNetCore.Authentication.OpenIdConnect package. Requires .NET 10.0 or later.
Add the package:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
Authentication configuration
Configure cookie and OpenID Connect authentication in Program.cs:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://us.vouch.sh";
options.ClientId = Environment.GetEnvironmentVariable("VOUCH_CLIENT_ID");
options.ClientSecret = Environment.GetEnvironmentVariable("VOUCH_CLIENT_SECRET");
options.ResponseType = OpenIdConnectResponseType.Code;
options.UsePkce = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("email");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapJsonKey("hardware_verified", "hardware_verified");
options.ClaimActions.MapJsonKey("hardware_aaguid", "hardware_aaguid");
});
builder.Services.AddAuthorization();
The ClaimActions.MapJsonKey calls map the Vouch-specific hardware_verified and hardware_aaguid claims from the UserInfo response into the user’s ClaimsPrincipal.
Login and logout endpoints
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/login", () =>
Results.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
[OpenIdConnectDefaults.AuthenticationScheme]));
app.MapPost("/logout", async (HttpContext context) =>
{
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Results.Redirect("/");
});
Accessing claims
After authentication, read claims from the ClaimsPrincipal:
app.MapGet("/", (HttpContext context) =>
{
if (context.User.Identity?.IsAuthenticated == true)
{
var email = context.User.FindFirst("email")?.Value ?? "unknown";
var hwVerified = context.User.FindFirst("hardware_verified")?.Value == "true";
// Use email and hwVerified as needed
}
});
Rich Authorization Requests
To request structured permissions beyond scopes, add authorization_details as an extra parameter in the redirect event:
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter(
"authorization_details",
"""[{"type":"account_access","actions":["read","transfer"]}]""");
return Task.CompletedTask;
},
};
See the Rich Authorization Requests section for the full authorization_details format.