Join our Newsletter — 33% off our NHI Course
Home› Guides› Blazor Security Guide: Server and WebAssembly Trust Boundaries…
Guide Application Security

Blazor Security Guide: Server and WebAssembly Trust Boundaries Explained

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 27 October 2026 14 min read
On this page

Blazor lets one C# codebase run on the server, in the browser through WebAssembly, or both, and teams often forget that the security model changes completely depending on where a component renders. In interactive server rendering, component code runs on the server and the browser holds a SignalR connection; in WebAssembly the compiled assemblies are downloaded to the user, who can read and change them. An [Authorize] attribute or an AuthorizeView that is a real control on the server is only a display hint in the browser. This guide explains how identity and authorisation actually work across Blazor render modes, where tokens and secrets belong, how to harden circuits and the SignalR channel, and what to log. It is for .NET developers, application security engineers and reviewers assessing Blazor Web Apps, Blazor Server and standalone Blazor WebAssembly applications, and it builds on the ASP.NET Core Security Guide rather than repeating it.

Key takeaways

  • Client-side authorisation is not a control. Microsoft's Blazor documentation states that authorisation checks in client-side code can be bypassed; every rule must also be enforced in a server endpoint or server-rendered component.
  • Interactive Auto has two enforcement points. The component's [Authorize] protects the server render path and the web API protects the WebAssembly path; securing one does not secure the other.
  • Nothing secret ships in WebAssembly. Connection strings, client secrets, API keys and private business logic in a WASM assembly are public; call your own server API, which holds the credentials.
  • Prefer a backend for frontend for tokens. Keeping access and refresh tokens server side in the authentication cookie (OIDC with SaveTokens) removes them from browser JavaScript and storage.
  • Treat every circuit event as untrusted input. Event arguments, JS interop results and calls into .NET from JavaScript can carry any payload, and server memory and connections are shared across all users.

How identity and access work in Blazor

Blazor in .NET 8 and later uses per-component render modes. Where a component runs decides what its security checks are worth.

Render modeWhere code runsHow the user is identifiedWhat enforces access
Static server-side rendering (SSR)Server, per HTTP requestNormal ASP.NET Core authentication from HttpContext.User (cookie, OIDC)[Authorize] on the routable component, endpoint policies, the authentication middleware redirect (for example LoginPath)
Interactive ServerServer, inside a SignalR circuitAuthentication state captured when the circuit's WebSocket connects, held for the connection's lifetime and re-evaluated on reconnect[Authorize], checks in event handlers and services, revalidation of the circuit
Interactive WebAssemblyBrowser, .NET runtime in WebAssemblySerialised state from the server (PersistentAuthenticationStateProvider) or tokens from Microsoft.AspNetCore.Components.WebAssembly.AuthenticationOnly the server API the client calls. Client checks are user experience only
Interactive AutoServer first, then browser once the runtime is cachedBoth of the aboveBoth the component (server path) and the API (client path)

Server-side authentication state

  • Circuit identity: navigation inside a circuit does not send cookies, so the circuit keeps the principal it received at connect time. A user whose account is disabled stays signed in to an open circuit until it is revalidated.
  • Revalidation: RevalidatingServerAuthenticationStateProvider rechecks the principal on a RevalidationInterval. Microsoft documents a default of 30 minutes for Identity or cookie authentication. Returning false from ValidateAuthenticationStateAsync marks the circuit unauthenticated but does not invalidate the authentication cookie, so a full page load can sign the user back in until the cookie is rejected as well.
  • Forced sign-out with ASP.NET Core Identity: shorten the interval in IdentityRevalidatingAuthenticationStateProvider, set SecurityStampValidatorOptions.ValidationInterval just inside it, and call UserManager<TUser>.UpdateSecurityStampAsync on disable, password reset or role removal. Without Identity, check a data store in CookieAuthenticationEvents.OnValidatePrincipal and call RejectPrincipal.
  • Do not validate in navigation: Microsoft advises against a custom NavigationManager for authentication checks; use a custom AuthenticationStateProvider.
  • Identity UI belongs in Razor Pages: SignInManager<TUser> and UserManager<TUser> are not supported inside Razor components, so sign-in, registration and account management pages run as static SSR or Razor Pages.

WebAssembly authentication state

  • Serialised state: a Blazor Web App flows the server principal to the client with AddAuthenticationStateSerialization on the server and AddAuthenticationStateDeserialization on the client. The SerializeAllClaims option controls whether every claim or only name and role claims travel; send only what the UI needs, because the client can read all of it.
  • Fixed for the session: client authentication state is fixed for the lifetime of the WebAssembly app; sign-in and sign-out require a full page reload, which matters when roles change mid-session.
  • Standalone WASM with OIDC: the authentication library supports only the authorisation code flow with PKCE. The implicit grant is not supported. Microsoft notes that refresh tokens cannot be secured in a WebAssembly app and recommends short lifetimes, rotation and a maximum lifetime that forces interactive sign-in.
  • Fallback policy: AuthorizationOptions.FallbackPolicy with RequireAuthenticatedUser is not supported in WebAssembly. Apply @attribute [Authorize] in _Imports.razor and mark the Authentication component [AllowAnonymous] so the sign-in redirect works.

What AuthorizeView does and does not do

AuthorizeView and role-gated NavLink elements decide what is rendered. They do not stop a user calling an event handler, navigating to a route or calling an API directly. Put the check in the handler, the service and the endpoint, and load protected data from an authorised server call instead of embedding it in the client. Use the cascading Task<AuthenticationState> parameter for procedural decisions. See the Broken Access Control Prevention Guide.

Admin roles and privileged access

  • Policy, not role strings in markup: define named authorisation policies (AddAuthorization(o => o.AddPolicy("CanApprovePayments", ...))) and apply them to components with [Authorize(Policy = "...")] and to endpoints with .RequireAuthorization("..."). AuthorizeView Roles="Admin, Superuser" means either role; requiring both needs nested views, which is easy to get wrong, so prefer a policy.
  • Resource-based checks on the server: for "may this user edit this record", inject IAuthorizationService into the server service and call AuthorizeAsync(user, resource, policy). A WASM client that sends a record ID must never decide this itself. See the OWASP API Top 10 API1 Broken Object Level Authorization Guide.
  • Separate admin surfaces: admin pages that only work as Interactive Server or static SSR keep admin logic and data off the client entirely. If an admin area must be WebAssembly, assume its code is read by every authenticated user and keep the logic in the API.
  • Step-up for dangerous actions: require a recent authentication or a stronger method for role changes, payouts and exports, enforced by a policy that checks an authentication time or method claim from the identity provider.
  • Revoke quickly: removing a role in the directory does not reach an open circuit or a running WASM app until revalidation or reload. Pair role removal with a security stamp update and a revalidation interval measured in minutes for privileged users.

Integrations, API tokens and service accounts

CredentialWrong placeRight place
Database connection stringWASM wwwroot/appsettings.json, client assemblyServer only, ideally a managed identity with no password at all
OIDC client secretClient project, source controlServer configuration from Secret Manager in development and a vault in staging and production
Third-party API keyClient HttpClient default headersServer API or YARP forwarder that adds the key server side
User access and refresh tokensBrowser storage readable by scriptServer, in the authentication cookie's properties (SaveTokens = true), attached to outgoing calls by a DelegatingHandler
SignalR hub accessAnonymous hub[Authorize] on the hub; standalone WASM passes the token through options.AccessTokenProvider
  • Backend for frontend: Microsoft's Blazor Web App OIDC sample keeps tokens on the server, refreshes them non-interactively using the offline_access scope, and either calls downstream APIs from server code or forwards client calls with YARP MapForwarder, attaching the user's token. The browser sees only a same-site cookie. See the OAuth for Browser-Based Applications and the BFF Pattern Guide.
  • Separate registrations: Microsoft recommends separate identity provider registrations for the client and the server API. Scope the client registration to the API only and do not enable implicit grant token issuance on either.
  • Claims mapping: set MapInboundClaims = false on the OIDC handler for most providers so claim names are not rewritten, and base policies on the issuer's real claim names.
  • Environment variables: Microsoft's guidance is to avoid environment variables for sensitive data outside local development and to use managed identities for Azure services. See the Secrets Management Guide.
  • Machine callers: background jobs and server-to-server calls from the Blazor host use their own workload identity with the narrowest scopes, never a user's saved token or a shared admin key. See the Service Account Security Guide.

Logging and detection

Detailed circuit errors go to server logs while the client receives a generic message, so the server log is the only place many Blazor attacks show up.

SignalSourceWhy it matters
Authorisation failures on API endpoints called by WASMASP.NET Core authorisation logs, API gatewayA user probing endpoints the UI hides; repeated 403s on admin routes from a non-admin
Circuit exceptions and disconnectsServer logs for the circuit hostMalformed event payloads, interop abuse or resource exhaustion attempts
Rejected antiforgery and cross-origin posts (400)Antiforgery middlewareCSRF attempts against SSR forms
Concurrent circuits per user and per IPCustom CircuitHandler metricsConnection flooding, since there is no per-user limit by default
Token refresh failures and reuseIdentity provider sign-in logsStolen refresh tokens in standalone WASM apps
Sign-in, role and security stamp changesIdentity store auditEvidence that revocation reached active sessions

Use a CircuitHandler to record circuit open and close events with the user identifier, and never log tokens or full claims sets. See the Secure Logging Vocabulary and Application Security Events Guide.

Metrics that show the controls work:

  • Share of WASM-called API endpoints with an explicit authorisation policy (target 100%).
  • Number of secrets or keys found by scanning published wwwroot and _framework output (target zero).
  • Time from account disable to loss of access in open circuits (should be at or under the revalidation interval).
  • Peak concurrent circuits per user against the configured limit.
  • Count of components using AddMarkupContent or MarkupString with non-constant input.

Hardening baseline

  1. Inventory render modes. List every routable component and its render mode; flag any WebAssembly or Auto component that touches sensitive data, and confirm the data arrives from an authorised API.
  2. Enforce on the server first. Add [Authorize] or a policy to every server-rendered routable component and .RequireAuthorization() to every API endpoint; then add client checks for usability. Test each endpoint with a low-privilege token.
  3. Configure antiforgery. The header-based protection added by the template inspects Sec-Fetch-Site and Origin on unsafe methods; for token-based protection call UseAntiforgery after UseRouting, UseAuthentication, UseAuthorization and UseHttpsRedirection. Never set DisableCsrfProtection without an alternative. See the CSRF Prevention Guide.
  4. Tune circuits. Review CircuitOptions: DisconnectedCircuitMaxRetained, DisconnectedCircuitRetentionPeriod, JSInteropDefaultCallTimeout (documented default one minute) and MaxBufferedUnacknowledgedRenderBatches, plus HubConnectionContextOptions.MaximumReceiveMessageSize. Require authentication before a circuit starts where the app allows, and cap circuits per user.
  5. Restrict origins. Blazor's SignalR endpoint can be reached cross-origin by default; restrict it with SignalR CORS configuration or DisableCorsAttribute. See the CORS Misconfiguration Guide.
  6. Render safely. Razor expressions encode output; do not pass untrusted strings to AddMarkupContent or MarkupString, never write user data through innerHTML in interop, and add a restrictive Content Security Policy. See the Content Security Policy Guide.
  7. Block framing and side channels. Set CSP frame-ancestors (and X-Frame-Options for older clients). Microsoft warns that WebSocket compression enables CRIME and BREACH style attacks, so do not render secrets or personal data in the same render batch as attacker-controlled content, and keep the default iframe block when compression is on.
  8. Validate redirects. Do not pass user input to NavigationManager.NavigateTo without an allowlist. See the Open Redirect Guide.
  9. Disable detailed errors outside development and serve the app only over HTTPS with HSTS.
  10. Roll back safely. Ship authorisation changes behind configuration so a policy that locks out legitimate users can be relaxed without redeploying the client, and stage them through a pilot group first.

Common misconfigurations

  • Hidden menu equals protected page: a role check removes the NavLink, but the routable component has no [Authorize], so typing the URL loads it.
  • API trusts the WASM client: the client checks IsInRole("Admin") before calling DELETE /api/users/{id}, and the endpoint has no policy. Anyone with a valid session can call it. This is the pattern ASVS 5.0 requirement V8.3.1 targets: authorisation must sit at a trusted service layer, not in code the consumer controls.
  • Auto render secured once: the team secures the API used by the WebAssembly path but the server render path calls the service directly with no component attribute, or the reverse.
  • Secrets in the client bundle: a key placed in wwwroot/appsettings.json or a constant in a shared class library is published inside the downloadable assemblies.
  • Singleton user state: a singleton service caches per-user data with keys a user can influence, leaking one user's data into another user's circuit.
  • Revocation assumed instant: an account is disabled during an incident but its circuit lives on for the default 30-minute revalidation window, and the cookie keeps working.
  • Interop trusted: values returned by IJSRuntime.InvokeAsync or methods exposed with [JSInvokable] are used without validation, although any page script can call them.

Framework mapping

Blazor controlNIST SP 800-53 Rev. 5NIST CSF 2.0OWASP ASVS 5.0ISO/IEC 27001:2022 Annex A
Server-side authorisation on components and APIsAC-3, AC-6PR.AA-05V8.3.1A.8.3, A.8.26
Server-side input validation of events and interopSI-10PR.PS-06V2.2.2A.8.28
Tokens and secrets kept off the clientIA-5, SC-28PR.AA-05V14.3.3A.5.17, A.8.24
Circuit revalidation and session controlSC-23PR.AA-05n/aA.8.5
HTTPS for the SignalR channelSC-8PR.DS-02n/aA.8.24
Circuit and authorisation loggingAU-2DE.CM-09n/aA.8.15

Relevant ATT&CK techniques for threat modelling are T1190 Exploit Public-Facing Application, T1539 Steal Web Session Cookie and T1552.001 Credentials In Files (secrets left in published client files). CIS Controls v8.1 Control 16, Application Software Security, covers the secure development practices here.

Where identity fits

Blazor apps hold more non-human credentials than they appear to: the OIDC client secret, the data protection key ring that protects the authentication cookie, downstream API keys and the managed identity of the host. The data protection keys deserve special care in a web farm, because anyone who can read them can forge cookies; persist them to protected storage and encrypt them at rest. Inventory each credential, give it an owner and a rotation date, and prefer workload identity federation or managed identities over stored secrets. See the .NET Security Guide.

Practitioner checklist

  • Every routable server-rendered component carries [Authorize] or a named policy, and every API endpoint uses .RequireAuthorization().
  • No authorisation decision relies only on AuthorizeView, hidden links or client-side role checks.
  • Published client output (wwwroot, _framework) is scanned for secrets in CI and contains none.
  • User tokens are held server side in a BFF design, or standalone WASM uses PKCE, short-lived rotating refresh tokens and a maximum session lifetime.
  • Serialised claims sent to the client are limited to what the UI needs.
  • Revalidation interval and security stamp validation are set so disabled privileged users lose circuit access within minutes.
  • Antiforgery is configured in the correct middleware order and SignalR origins are restricted.
  • CircuitOptions and hub message size limits are reviewed, and circuits per user are capped and monitored.
  • No untrusted input reaches AddMarkupContent, MarkupString, innerHTML or NavigateTo; CSP and frame-ancestors are set.
  • Detailed errors are disabled in production and circuit events are logged without tokens.

Standards and references

Related NHI Mgmt Group resources: ASP.NET Core Security Guide · OAuth for Browser-Based Applications and the BFF Pattern Guide · Client-Side Security Guide · Broken Access Control Prevention Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 27 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.