Skip to content

Cookies

Granit.Cookies enforces a strict cookie registry: every cookie must be declared at startup with a GDPR category. Writing an undeclared cookie throws UnregisteredCookieException. Consent is resolved per-category via a pluggable IConsentResolver. Granit.Cookies.Klaro integrates with the EU-sovereign Klaro consent management platform.

PackageRoleDepends on
Granit.CookiesCookie registry, consent enforcementGranit.Timing
Granit.Cookies.KlaroKlaro CMP consent resolverGranit.Cookies
[DependsOn(typeof(GranitCookiesModule))]
public class AppModule : GranitModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddGranitCookies(cookies =>
{
cookies.RegisterCookie(new CookieDefinition(
Name: "session_id",
Category: CookieCategory.StrictlyNecessary,
RetentionDays: 1,
IsHttpOnly: true,
Purpose: "Session identification"));
cookies.RegisterCookie(new CookieDefinition(
Name: "analytics_consent",
Category: CookieCategory.Analytics,
RetentionDays: 365,
IsHttpOnly: false,
Purpose: "Analytics tracking preference"));
cookies.UseConsentResolver<KlaroConsentResolver>();
});
}
}
CategoryConsent requiredDescription
StrictlyNecessaryNoSession, CSRF, authentication
FunctionalityYesPreferences, language
AnalyticsYesUsage tracking
MarketingYesAdvertising, retargeting
OtherYesUncategorized

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);
}
public async Task RevokeAnalyticsAsync(HttpContext httpContext)
{
// Deletes all cookies in the Analytics category
await cookieManager.RevokeCategoryAsync(
httpContext, CookieCategory.Analytics)
.ConfigureAwait(false);
}
}

Security defaults applied automatically:

  • Secure = true (HTTPS only)
  • SameSite = Lax (CSRF protection)
  • Expires calculated via IClock.Now + RetentionDays
  • HttpOnly per cookie definition

The consent resolver determines if a user has consented to a cookie category:

public interface IConsentResolver
{
Task<bool> ResolveAsync(HttpContext httpContext, CookieCategory category);
}

StrictlyNecessary cookies always return true — no consent check needed.

Klaro is a self-hosted, EU-sovereign consent management platform.

[DependsOn(typeof(GranitCookiesKlaroModule))]
public class AppModule : GranitModule { }
{
"Klaro": {
"CookieName": "klaro"
}
}

KlaroConsentResolver reads the Klaro consent cookie and maps service consent to Granit cookie categories.

{
"Cookies": {
"ThrowOnUnregistered": true,
"DefaultRetentionDays": 365,
"ThirdPartyServices": [
{
"Name": "Google Analytics",
"Category": "Analytics",
"CookiePatterns": ["_ga*", "_gid"]
}
]
}
}
PropertyDefaultDescription
ThrowOnUnregisteredtrueThrow when writing an undeclared cookie
DefaultRetentionDays365Default cookie lifetime
ThirdPartyServices[]Third-party service declarations
CategoryKey typesPackage
ModulesGranitCookiesModule, GranitCookiesKlaroModule
RegistryICookieRegistry, CookieDefinition, CookieCategory, GranitCookiesBuilderGranit.Cookies
ManagerIGranitCookieManager, IConsentResolverGranit.Cookies
KlaroKlaroConsentResolver, KlaroOptionsGranit.Cookies.Klaro
ExtensionsAddGranitCookies(), AddGranitCookiesKlaro()