OsirionCookieConsent
OsirionCookieConsent shows a cookie banner until the visitor accepts, declines or saves their own choice. The
buttons post a form to an endpoint in your app, which stores the decision in a cookie and redirects back, so the
banner works under static SSR without script. Analytics trackers can then wait for that consent.
Setup
Register the services and map the endpoint in Program.cs:
using Osirion.Blazor.Core.Extensions;
builder.Services.AddOsirionCookieConsent();
var app = builder.Build();
app.UseAntiforgery();
app.MapOsirionCookieConsent(); // POST /api/cookie-consent
AddOsirionCookieConsent registers IHttpContextAccessor and the antiforgery services. The endpoint requires an
antiforgery token, so app.UseAntiforgery() must run before the endpoints, as in the Blazor Web App template.
Then place the banner in a statically rendered layout:
@using Osirion.Blazor.Components
<OsirionCookieConsent PolicyLink="/privacy" />
Usage
A banner with your own text and categories:
<OsirionCookieConsent Title="Cookies on this site"
Message="We use a cookie to remember your choice and, if you agree, privacy-friendly statistics."
PolicyLink="/privacy"
PolicyLinkText="Privacy policy"
ShowCustomizeButton="true"
Categories="categories"
ConsentExpiryDays="180" />
@code {
private readonly IReadOnlyList<CookieCategory> categories =
[
new CookieCategory { Id = "necessary", Name = "Necessary", Description = "Keeps the site working.", IsRequired = true, IsEnabled = true },
new CookieCategory { Id = "analytics", Name = "Statistics", Description = "Counts visits so we can improve the docs." }
];
}
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Title |
string |
"Cookie Consent" |
Banner heading (h3) and the region's accessible name. |
Message |
string |
default notice | Banner text, rendered as encoded text. |
PolicyLink |
string? |
null |
Address of your privacy or cookie policy; no link when empty. |
PolicyLinkText |
string |
"Learn more" |
Text of that link. |
AcceptButtonText |
string |
"Accept All" |
Accept button text. |
DeclineButtonText |
string |
"Decline" |
Decline button text. |
ShowDeclineButton |
bool |
true |
Shows the decline button. |
CustomizeButtonText |
string |
"Customize" |
Customize button text. |
ShowCustomizeButton |
bool |
true |
Shows the customize button. |
ShowCustomizationPanel |
bool |
true |
Shows the category checkboxes after the visitor chose Customize. |
CustomizePanelTitle |
string |
"Cookie Preferences" |
Heading (h4) of the category panel. |
SavePreferencesButtonText |
string |
"Save Preferences" |
Button that saves the checked categories. |
Categories |
IReadOnlyList<CookieCategory> |
necessary, analytics, marketing, preferences | Categories in the panel. |
Icon |
RenderFragment? |
null |
Icon next to the text. |
Position |
string |
"bottom" |
Adds osirion-cookie-consent-{Position}; the stylesheet supports bottom and top. |
ConsentExpiryDays |
int |
365 |
Lifetime of the consent cookie, 1 to 3650 days. |
ConsentEndpoint |
string |
"/api/cookie-consent" |
Where the form posts; match the pattern given to MapOsirionCookieConsent. |
CookieCategory has Id, Name, Description, IsRequired (always on, checkbox disabled) and IsEnabled
(checked by default). Class goes on the banner element; unmatched attributes go on the form.
Behavior
- Flow without script. Accept and Decline post the form, the endpoint writes the cookie and redirects to the
same page, and the banner is no longer rendered. Customize redirects to the page with
?customize-cookies=true, where the banner shows the category checkboxes; Save Preferences records the checked ones. - What is recorded. Accept sets
necessary,analytics,marketingandpreferencesto true; Decline setsnecessaryto true and the other three to false. Save Preferences recordsnecessaryplus each category the visitor checked; unchecked ones are left out, which counts as no consent. Custom category IDs are therefore recorded only through the panel. - The cookie.
osirion_cookie_consentholds JSON withVersion,ConsentDate,ConsentTypeandCategories. It isHttpOnly,SecureandSameSite=Lax, so serve the site over HTTPS. Script cannot read it; decisions are made on the server. - Security. The form carries an antiforgery token. A post without a valid token gets 400 and records nothing, and the endpoint redirects only to local paths.
- Rendering. The component reads the cookie from the current request. Without an HTTP request (an interactive
render with no
HttpContext), it renders nothing. - Accessibility. The banner is a region named by its title, so its text is inside a landmark. Available from
4.1. The buttons are real
buttonelements in a form, usable with the keyboard.
Reading consent on the server
CookieConsentHandler in Osirion.Blazor.Core.Handlers reads the cookie:
using Osirion.Blazor.Core.Handlers;
bool statistics = CookieConsentHandler.IsCategoryConsented(httpContext, "analytics");
CookieConsentData? consent = CookieConsentHandler.GetConsentData(httpContext);
ClearConsent(httpContext) deletes the cookie, for example on a "change cookie settings" endpoint.
app.UseOsirionCookieConsent() adds middleware that puts the parsed data in HttpContext.Items["CookieConsent"].
Gating analytics
The analytics module can render trackers only after the visitor accepted the analytics category. Turn the gate on
in code:
using Osirion.Blazor.Analytics.Extensions;
using Osirion.Blazor.Extensions;
builder.Services.AddOsirion(osirion => osirion
.UseAnalytics(analytics => analytics
.AddClarity(clarity => clarity.SiteId = "your-clarity-id")
.RequireConsent()));
or in configuration:
{
"Osirion": {
"Analytics": {
"Consent": { "RequireConsent": true }
}
}
}
Without consent no tracker script is rendered at all; with GA4, Google Consent Mode starts with its defaults set to
denied. RequireConsent(options => options.Category = "statistics") uses another category ID. See
Analytics.
Styling
The form has osirion-cookie-consent-form; the banner has osirion-cookie-consent and
osirion-cookie-consent-bottom or osirion-cookie-consent-top, plus osirion-cookie-consent-customizing while the
panel is open. Inner parts include osirion-cookie-consent-title, osirion-cookie-consent-description,
osirion-cookie-consent-link, osirion-cookie-consent-actions, osirion-cookie-consent-customize and
osirion-cookie-consent-category. Colors come from the theme tokens (--osirion-text-primary,
--osirion-border-color, --osirion-action-primary and others), and the buttons use the active CSS framework's
classes.
Related
Related items
