<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nagasudhir Pulla</title>
    <description>The latest articles on Forem by Nagasudhir Pulla (@nagasudhirpulla).</description>
    <link>https://forem.com/nagasudhirpulla</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3922938%2F97d9278e-2133-47e2-a02f-a1d1475f43ca.jpg</url>
      <title>Forem: Nagasudhir Pulla</title>
      <link>https://forem.com/nagasudhirpulla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nagasudhirpulla"/>
    <language>en</language>
    <item>
      <title>Cookie based authentication &amp; authorization in ASP.NET Core explained</title>
      <dc:creator>Nagasudhir Pulla</dc:creator>
      <pubDate>Sun, 10 May 2026 07:10:08 +0000</pubDate>
      <link>https://forem.com/nagasudhirpulla/cookie-based-authentication-authorization-in-aspnet-core-explained-1k8l</link>
      <guid>https://forem.com/nagasudhirpulla/cookie-based-authentication-authorization-in-aspnet-core-explained-1k8l</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ivfai9w8kkyuownacid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ivfai9w8kkyuownacid.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Video - &lt;a href="https://youtu.be/GhZLi8pBJow?si=mnIVpCke9OJBMFoJ" rel="noopener noreferrer"&gt;https://youtu.be/GhZLi8pBJow?si=mnIVpCke9OJBMFoJ&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Services for Authentication and Authorization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maintains multiple authentication schemes&lt;/li&gt;
&lt;li&gt;Uses Cookie handler to Build ClaimsPrincipal from cookie, set up request redirection for login, logout, access denial &lt;/li&gt;
&lt;li&gt;Add cookie authentication service in DI container using the following
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add Cookie Authentication service&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAuthentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CookieAuthenticationDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationScheme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoginPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/Account/Login"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Specify the path to the login page&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccessDeniedPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/Account/AccessDenied"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Specify the path for access denied&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExpireTimeSpan&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set the cookie expiration time&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SlidingExpiration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Enable sliding expiration&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;AddAuthentication&lt;/code&gt; adds the authentication service to DI container. It also specifies the default authentication scheme (Cookies) for authentication. &lt;/li&gt;
&lt;li&gt;  &lt;code&gt;AddCookie&lt;/code&gt; provides a cookie authentication handler for the Cookies authentication scheme.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authorization Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Evaluates ClaimsPrincipal's claims against authorization policies to determine if the request is authorized&lt;/li&gt;
&lt;li&gt;Add authorization service in DI container using the following
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAuthorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Define a rule named "AdminOnly"&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AdminOnly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RequireRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Admin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RequireClaim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EmployeeId"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The above code adds a policy named &lt;code&gt;AdminOnly&lt;/code&gt; along with default available authorization service policies &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Request's Journey for cookie-based Authentication and Authorization in dotnet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wgr1yx4pj4d7e3scfiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wgr1yx4pj4d7e3scfiv.png" alt="auth middleware arch" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1 - Authentication middleware (for Identification)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Authentication middleware identifies the visitor by extracting the ClaimsPrincipal from cookie and attaches it to HttpContext
&lt;/li&gt;
&lt;li&gt;Authenticaiton middleware is added to the request pipeline using the following
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthentication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Steps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Middleware asks the Authentication Service (configured via AddAuthentication) for a ClaimsPrincipal (user).&lt;/li&gt;
&lt;li&gt;Authentication Service calls the Cookie Handler. It decrypts the cookie (using Data Protection Provider) and creates a ClaimsPrincipal&lt;/li&gt;
&lt;li&gt;The created ClaimsPrincipal is attached to HttpContext.User. The request moves to the next middleware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 2: Authorization middleware (for Permissions check)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Authorization middleware evaluates the identified ClaimsPrincipal's claims and redirects the request to login or denies the request if claims don't meet the authorization requirements &lt;/li&gt;
&lt;li&gt;Authorization middleware is added to the request pipeline using the following
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Steps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Authorization middleware checks the endpoint for attributes like [Authorize] or a specific policy (e.g., [Authorize(Policy = "AdminOnly")]).&lt;/li&gt;
&lt;li&gt;Authorization middleware asks the Authorization Service (registered via AddAuthorization) to evaluate the ClaimsPrincipal's claims against those rules.&lt;/li&gt;
&lt;li&gt;Based on that evaluation, the system executes one of three paths:&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Path A: User is Not Logged In (Challenge the request)
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Condition: The authorization policy requires a user, but HttpContext.User is anonymous.&lt;/li&gt;
&lt;li&gt;Action: The Authorization middleware triggers a Challenge by calling the ChallengeAsync method on the Authentication service.&lt;/li&gt;
&lt;li&gt;Execution: Authentication service delegates the Challenge execution to Cookie Handler, which modifies HttpContext.Response for a 302 Redirect to LoginPath. The pipeline short-circuits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Path B: User has Wrong Permissions (Forbid the request)
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Condition: ClaimPrincipal is present, but the claims fail the requirements of authorization policies.&lt;/li&gt;
&lt;li&gt;Action: The Authorization middleware triggers a Forbid by calling the ForbidAsync method on the Authentication service.&lt;/li&gt;
&lt;li&gt;Execution: Authentication service delegates the Forbid execution to Cookie Handler, which modifies HttpContext.Response for a 302 Redirect to AccessDeniedPath. The pipeline short-circuits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Path C: Access Granted
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Condition: The user's claims satisfy all requirements in the Authorization Service.&lt;/li&gt;
&lt;li&gt;Execution: The middleware calls next(), allowing the request to reach next middleware (like controllers).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting logged in user in the cookie
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwwixwzcl7u0qpfx5aj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwwixwzcl7u0qpfx5aj4.png" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; The user will submit credentials in the login page&lt;/li&gt;
&lt;li&gt; The user credentials will be verified from a database and ClaimsPrincipal will be created to represent the logged in user&lt;/li&gt;
&lt;li&gt; &lt;code&gt;HttpContext.SignInAsync&lt;/code&gt; uses Authentication service's Cookie Handler to set the logged in user details (a ClaimsPrincipal) in the response cookie
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;HttpContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SignInAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;CookieAuthenticationDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationScheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ClaimsPrincipal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;claimsIdentity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;authProperties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Signout logged in user
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;HttpContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SignOutAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CookieAuthenticationDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationScheme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;HttpContext.SignOutAsync&lt;/code&gt; uses Authentication service's Cookie Handler to expire the cookie that contains the logged in user details (a ClaimsPrincipal) and makes the &lt;code&gt;HttpContext.User&lt;/code&gt; as anonymous&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Access the ClaimsPrincipal (logged in user)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  After the authentication middleware derives a valid ClaimsPrincipal from the cookie, it sets the user details (ClaimsPrincipal) in the &lt;code&gt;HttpContext.User&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;  Hence

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;HttpContext.User?.Identity?.IsAuthenticated&lt;/code&gt; can be used to determine if a request is authenticated&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;HttpContext.User.Identity.Name&lt;/code&gt; can be used to determine the logged in user name&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
