Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
MFA: TOTP, Recovery Codes, Step-up Authentication and the Weakness of SMS
ASP.NET Core Identity's default authenticator provider accepts a TOTP code within ±2 time steps (five codes) and again and again, while NIST requires a code to be accepted once. We compute TOTP ourselves against the RFC 6238 test vector and show setup, lockout, a replay-protected provider, recovery codes, a step-up policy with the amr claim and the risks of SMS and 'remember this device' with real outputs.
The Account Lifecycle with ASP.NET Core Identity: Registration, Email Confirmation, Password Reset, External Login and Account Deletion
Identity's reset token is never marked as used; it carries the security stamp, so it dies when the password changes, and its default lifetime is one day. We build registration, e-mail confirmation, a password reset provider with its own lifetime, dropping other sessions, e-mail change, the risk of automatic linking in Google external login, and personal data export and account deletion for KVKK/GDPR, with an Angular screen.
The Architecture of ASP.NET Core Identity: UserManager, SignInManager, Stores and Customization
ASP.NET Core Identity is not a single login system; UserManager runs user rules, SignInManager the HTTP session and store interfaces the data access, in separate layers. We build our own user entity with Guid keys and table names, and examine schema versions, the four registration methods and MapIdentityApi's non-JWT token and reusable refresh token with real outputs.
ASP.NET Core Cookie Authentication in Depth: Session Lifetime, Sliding Expiration, Server-Side Sessions and Revocation
Sliding expiration alone can keep a session alive forever; you have to add an absolute timeout yourself with OnValidatePrincipal, and revocation needs state on the server (ITicketStore or a version stamp). We show the cookie ticket's contents, the 14-day default, renewal at half the window, chunking, server-side sessions in Redis and signing out of all devices with real outputs.
Mapping Authentication and Authorization: Credentials, Sessions, Tokens, Claims and ASP.NET Core's Authentication Handler Model
Authentication finds out who you are, authorization decides what you may do; in ASP.NET Core the first fills HttpContext.User through named schemes and handlers, the second checks policies and calls challenge (401) or forbid (403). We name credentials, sessions, tokens and claims, combine cookies and JWT with a policy scheme, and show why an endpoint returning Results.Ok still answers 302 on .NET 10.
ASP.NET Core Security in .NET 11: Automatic CSRF Protection with Fetch Metadata, Device Bound Session Credentials and TLS Channel Binding
.NET 11 adds CSRF protection, on by default for apps built with WebApplication.CreateBuilder, that checks the Sec-Fetch-Site and Origin headers; yet only form-reading endpoints enforce the verdict and DisableAntiforgery turns it off too. We cover the decision table, origins trusted through CORS, a middleware applying the same rules on .NET 10, experimental DBSC, TLS channel binding, unified authorization metadata and a migration checklist.
Observing Security Events in ASP.NET Core: Authentication, Authorization and Identity Metrics, Audit Trails and Alerts
.NET 10's authentication, authorization and Identity metrics count 401s, 403s and account lockouts but deliberately carry no user or policy name; who did what and when is the audit trail's job. We collect the metrics with OpenTelemetry and Prometheus, verify the real labels with a test, write alert rules and build a hash-chained audit trail that detects tampering.
Kestrel and Request Limits: Body Size, Header Timeout, Request Timeouts and Settings Against Slow Clients
By default Kestrel allows a 28.6 MB body, 30 seconds for headers and unlimited request duration, and a request timeout stops nothing unless the CancellationToken is carried. We read the real defaults from code and, with measurements, cover body, header, form and JSON limits, RequestHeadersTimeout and MinRequestBodyDataRate against slow clients, the request timeouts middleware and the split of work between Kestrel and the reverse proxy.
Antiforgery in Depth: CSRF Protection with Cookie Authentication, SPAs and Minimal APIs
ASP.NET Core's antiforgery middleware does not reject requests; it writes the result to a feature, and in minimal APIs only form binding enforces it, so cookie-authenticated JSON endpoints accept token-less requests with 200. With real output we cover the token pair internals, Angular's XSRF-TOKEN pattern, an endpoint filter that enforces validation, refreshing the token after login and deliberate use of DisableAntiforgery.
Emitting Security Headers and Nonce-Based CSP from ASP.NET Core: HSTS Preload, COOP/COEP/CORP, Permissions-Policy and a Reporting Endpoint
A nonce-based CSP changes on every request and depends on the response type, so it belongs in the app rather than Nginx, and the HTML must not be cached at any layer. We build one ASP.NET Core middleware with separate API and HTML header sets, nonce injection into Angular's index.html, Report-Only with a size- and rate-limited reporting endpoint, the HSTS preload risk and COOP/COEP/CORP, with real header output.
Rate Limiting in Depth: Algorithms, Partition Keys, Chained Limiters and Multiple Instances
ASP.NET Core rate limiters live in process memory: two instances double the limit, and behind a proxy without the real IP everyone lands in one partition. We compare fixed window, sliding window and token bucket under the same traffic, then show queue order, partition keys, CreateChained, 429 instead of the default 503 with Retry-After, the shared-policy trap and a per-user-name login limit with real output.
Data Protection in Depth: The Key Ring, Rotation, Key Storage, Encrypting Keys and Multiple Instances
Random logouts and empty-bodied 400s in a multi-instance ASP.NET Core app usually come from a separate Data Protection key ring per instance. Using real logs, we cover the key ring lifetime, rotation and revocation, the purpose hierarchy, file, Redis and database stores, encrypting keys with a certificate and the role of SetApplicationName.