Secure Your Blazor App with Authelia OIDC
Implement self-hosted Single Sign-On (SSO) for Blazor Server using Authelia and OpenID Connect (OIDC).
Introduction
Before integrating Authelia, BlueRobin’s web app had its own user table with bcrypt-hashed passwords and a hand-rolled JWT system. It worked, but every new feature—password reset, 2FA, session management—was another surface area to secure. Migrating to Authelia OIDC deleted over 2,000 lines of authentication code and replaced it with 40 lines of Program.cs configuration. The security posture improved dramatically because I was no longer responsible for implementing cryptographic protocols correctly.
In a manufacturing environment or a homelab, you don’t want to manage separate passwords for your Wiki, your Dashboard, and your Document System. You want Single Sign-On (SSO).
Authelia is a lightweight authentication server that acts as your Identity Provider (IdP). Your Blazor app acts as the Client. They speak OpenID Connect (OIDC) to securely exchange user identity without your app ever touching a password. [OpenID Connect Core 1.0] — OpenID Foundation , 2014
Why Authelia OIDC?
- Centralized User Management: One place to ban users or reset passwords. [Authelia Configuration - Identity Providers] — Authelia , 2024
- 2FA Enforcement: Authelia handles TOTP/Duo; your app doesn’t need to know.
- Standard Protocol: If you switch to Entra ID (Azure AD) later, the code changes are minimal. [Microsoft Identity Platform OIDC] — Microsoft , 2024
What We’ll Build
- Authelia Config: Register your Blazor app as a client.
- Blazor Program.cs: Configure the OIDC middleware.
- Token Handling: Map claims from Authelia (groups, email) to .NET ClaimsPrincipal.
Architecture Overview
sequenceDiagram
participant User
participant Blazor as 🛡️ Blazor App
participant Authelia as 🔐 Authelia (IdP)
User->>Blazor: Access Protected Page
Blazor->>User: 302 Redirect to Authelia
User->>Authelia: Login (User + Pass + 2FA)
Authelia->>User: 302 Redirect to /signin-oidc?code=XYZ
User->>Blazor: GET /signin-oidc?code=XYZ
Blazor->>Authelia: POST /api/oidc/token (Exchange Code)
Authelia->>Blazor: Return ID Token + Access Token
Blazor->>User: Set Auth Cookie (Session Established)
User->>Blazor: Request Page
Blazor->>User: Render Authorized Content
Section 1: Authelia Configuration
First, tell Authelia about your application. It needs a client_id and a client_secret.
# configuration.yml (Authelia)
identity_providers:
oidc:
clients:
- client_id: my-web-client
client_name: My Web App
client_secret: '$pbkdf2-sha512$...' # Hashed secret
public: false
authorization_policy: two_factor # Force 2FA
redirect_uris:
- https://web.bluerobin.local/signin-oidc
scopes:
- openid
- profile
- email
- groups
token_endpoint_auth_method: client_secret_post
[OAuth 2.0 Security Best Current Practice]
— IETF , 2023
Section 2: .NET 8/9 Configuration
In Program.cs, we use the standard Microsoft.AspNetCore.Authentication.OpenIdConnect library.
[ASP.NET Core Authentication]
— Microsoft , 2024
// Program.cs
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.Name = "MyApp.Session";
options.Cookie.SameSite = SameSiteMode.Lax;
})
.AddOpenIdConnect(options =>
{
options.Authority = "https://auth.bluerobin.local";
options.ClientId = "my-web-client";
options.ClientSecret = builder.Configuration["Auth:ClientSecret"];
options.ResponseType = "code";
// Scopes request specific data
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("groups");
// Map Authelia's "groups" claim to .NET's Role claim
options.TokenValidationParameters = new()
{
NameClaimType = "preferred_username",
RoleClaimType = "groups"
};
// Secure by default
options.RequireHttpsMetadata = true;
options.SaveTokens = true;
});
Section 3: Protecting Pages
In Blazor, use [Authorize] to protect pages.
@page "/dashboard"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<h1>Dashboard</h1>
<p>Welcome, @context.User.Identity?.Name!</p>
@if (context.User.IsInRole("admin"))
{
<button class="btn-danger">Delete Database</button>
}
[Blazor Authentication and Authorization]
— Microsoft , 2024
Conclusion
By offloading authentication to Authelia, you make your application simpler and more secure. You no longer store password hashes. You get multi-factor authentication “for free”. And your users get a seamless Single Sign-On experience across your entire suite of apps.
The migration from custom auth to Authelia OIDC was one of the highest-ROI changes I’ve made to BlueRobin. Not only did it eliminate an entire class of security vulnerabilities (password storage, session fixation, CSRF on login forms), but it also enabled features I hadn’t planned for—like group-based access control that lets me share specific sections of the app with family members without giving them admin access.
Next Steps:
- Deploy Authelia as your Identity Provider if you haven’t already.
- Learn how Zero Trust Architecture extends this identity layer to service-to-service communication.
- Expose your authenticated app safely with Cloudflare Tunnel.
Further Reading
- [OpenID Connect Core 1.0] — OpenID Foundation , 2014 — The specification underlying all OIDC authentication flows used in this article.
- [ASP.NET Core Authentication] — Microsoft , 2024 — Official Microsoft documentation on authentication middleware, cookie handling, and OIDC integration.
- [Authelia Configuration - Identity Providers] — Authelia , 2024 — Detailed configuration reference for Authelia’s OIDC provider settings.