Cookies — Secure Cookie Management
Why a cookie module?
Section titled “Why a cookie module?”Granit.Http.Cookies enforces a strict cookie registry: every cookie must be declared at
startup with a consent category. Writing an undeclared cookie throws
UnregisteredCookieException. Consent is resolved per-category via a pluggable
IConsentResolver.
Package structure
Section titled “Package structure”| Package | Role | Depends on |
|---|---|---|
Granit.Http.Cookies | Cookie registry, consent enforcement, GPC signal | Granit |
Granit.Http.Cookies.Klaro | Klaro CMP consent resolver | Granit.Http.Cookies |
Granit.Http.Cookies.Endpoints | Cookie configuration API endpoint | Granit.Http.Cookies |
Granit.Privacy.Regulations.Cookies | Regulation-aware consent model bridge | Granit.Http.Cookies, Granit.Privacy.Regulations |
[DependsOn(typeof(GranitHttpCookiesModule))]public class AppModule : GranitModule{ public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddGranitCookies(cookies => { cookies.RegisterCookie(new CookieDefinition( "session_id", CookieCategory.StrictlyNecessary, 1, true, "Session identification"));
cookies.RegisterCookie(new CookieDefinition( "analytics_consent", CookieCategory.Analytics, 365, false, "Analytics tracking preference"));
cookies.UseKlaro(); }); }}Module auto-registration
Section titled “Module auto-registration”Granit modules that introduce cookies auto-declare them via ICookieDefinitionContributor.
The cookie registry collects all contributors at first resolution — no manual declaration
needed for framework cookies.
| Module | Cookies auto-registered | Contributor |
|---|---|---|
Granit.Http.Cookies | __Host-xsrf / .xsrf (dev) | AntiforgeryCookieDefinitionContributor |
Granit.OpenIddict.EntityFrameworkCore | __Host-id / .id (dev), __Host-id-2fa / .id-2fa, __Host-id-ext / .id-ext | IdentityCookieDefinitionContributor |
Granit.Http.Cookies.Klaro | klaro (configurable) | KlaroCookieDefinitionContributor |
Granit.Bff.Endpoints | __Host-bff-{name} / .bff-{name} (dev) | Runtime registration in MapGranitBff() |
Granit.Privacy.Endpoints | _optout_id | Runtime registration in MapGranitPrivacy() |
Implementing a contributor
Section titled “Implementing a contributor”internal sealed class MyCookieContributor : ICookieDefinitionContributor{ public IEnumerable<CookieDefinition> GetCookieDefinitions() { yield return new CookieDefinition( "my_cookie", CookieCategory.StrictlyNecessary, 1, true, "Purpose description") { IsEssential = true }; }}Register it in your module’s ConfigureServices:
context.Services.AddSingleton<ICookieDefinitionContributor, MyCookieContributor>();Application-level cookies
Section titled “Application-level cookies”The antiforgery cookie (__Host-xsrf) is auto-registered by GranitHttpCookiesModule.
The session cookie is opt-in because AddSession() is not always used. Call
RegisterSessionCookie() in hosts that enable session middleware:
context.Services.AddGranitCookies(cookies =>{ cookies.RegisterSessionCookie();});Cookie categories
Section titled “Cookie categories”| Category | Consent required | Description |
|---|---|---|
StrictlyNecessary | No | Session, CSRF, authentication, opt-out tracking |
Preferences | Yes | Language, theme, layout |
Analytics | Yes | Usage tracking (first-party) |
Marketing | Yes | Advertising, retargeting |
SaleOrSharing | Yes | CCPA “Do Not Sell or Share” — third-party data sharing |
Managed cookie operations
Section titled “Managed cookie operations”Always use IGranitCookieManager instead of IResponseCookies:
public class SessionService(IGranitCookieManager cookieManager){ public async Task SetSessionCookieAsync( HttpContext httpContext, string sessionId) { // Checks registry, verifies consent, applies security defaults await cookieManager.SetCookieAsync( httpContext, "session_id", sessionId) .ConfigureAwait(false); }}Security defaults applied automatically:
Secure = true(HTTPS only)SameSite = Lax(CSRF protection, configurable per cookie)MaxAgecalculated fromRetentionDaysHttpOnlyper cookie definition
Configuration reference
Section titled “Configuration reference”{ "Cookies": { "ThrowOnUnregistered": true, "DefaultRetentionDays": 365, "ThirdPartyServices": [ { "Name": "Google Analytics", "Category": "Analytics", "CookiePatterns": ["_ga*", "_gid"] } ] }}Public API summary
Section titled “Public API summary”| Category | Key types | Package |
|---|---|---|
| Modules | GranitHttpCookiesModule, GranitHttpCookiesKlaroModule | — |
| Registry | ICookieRegistry, CookieDefinition, CookieCategory, GranitCookiesBuilder | Granit.Http.Cookies |
| Contributors | ICookieDefinitionContributor | Granit.Http.Cookies |
| Manager | IGranitCookieManager, IConsentResolver | Granit.Http.Cookies |
| GPC | IGlobalPrivacyControlSignal, ICookieConsentModelProvider, ConsentModelInfo | Granit.Http.Cookies |
| Klaro | KlaroConsentResolver, KlaroOptions | Granit.Http.Cookies.Klaro |
See also
Section titled “See also”- Consent & GPC — Consent models, Global Privacy Control
- Klaro CMP — Klaro integration
- Regulation Bridge — Privacy.Regulations bridge
- Privacy module — Data export, erasure, legal agreements