This sample shows how to build a confidential interactive web client against MrWhoOidc using ASP.NET Core Razor Pages and the MrWhoOidc.Client package.
For the easiest local issuer, run the root-level compose stack from this repository first.
cd demos/dotnet-mvc-client
dotnet run
Then open https://localhost:5003.
The demo is typically pointed at the seeded local tenant:
https://localhost:8443/t/defaulthttps://localhost:8443/t/default/.well-known/openid-configurationhttps://localhost:5003/signin-oidchttps://localhost:5003/signout-callback-oidcAddMrWhoOidcClient registers discovery, token, authorization, logout, and JWKS helpers.Use this demo when you want a server-rendered .NET reference for:
Cause: MrWhoOidc uses self-signed certificate by default.
Solution:
dotnet dev-certs https --trusthttps://localhost:8443 to browser trusted sitesCause: MrWhoOidc container not running.
Solution:
# Check MrWhoOidc is running
docker ps | grep mrwho-oidc
# Start if not running
cd MrWhoOidc/MrWho
docker compose up -d
Cause: refresh_token grant not enabled for client.
Solution:
refresh_token is in Grant Typesbuilder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = configuration["MrWhoOidc:Issuer"];
options.ClientId = configuration["MrWhoOidc:ClientId"];
options.ClientSecret = configuration["MrWhoOidc:ClientSecret"];
options.ResponseType = "code"; // Authorization Code flow
options.UsePkce = true; // Enable PKCE
options.SaveTokens = true; // Save tokens to authentication ticket
options.GetClaimsFromUserInfoEndpoint = true;
// Request scopes
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access"); // For refresh token
});
Displays authenticated user information:
@if (User.Identity?.IsAuthenticated == true)
{
<h2>Welcome, @User.Identity.Name!</h2>
<h3>User Claims</h3>
<ul>
@foreach (var claim in User.Claims)
{
<li><strong>@claim.Type:</strong> @claim.Value</li>
}
</ul>
<a asp-controller="Account" asp-action="Logout">Logout</a>
}
else
{
<a asp-controller="Account" asp-action="Login">Login</a>
}