<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Teguh Murdianto's Blog]]></title><description><![CDATA[Teguh Murdianto's Blog]]></description><link>https://blog.tmurdianto.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 14:27:24 GMT</lastBuildDate><atom:link href="https://blog.tmurdianto.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[🧠 Comprehensive Guide: ClaimsPrincipal, HttpContext, and HttpContextAccessor in .NET Core]]></title><description><![CDATA[🧠 Comprehensive Guide: ClaimsPrincipal, HttpContext, and HttpContextAccessor in .NET Core

Based on Internet Research Best Practices (10x Iterations)Date: November 2025


📘 Executive Summary
In ASP.NET Core, three key classes form the backbone of u...]]></description><link>https://blog.tmurdianto.com/comprehensive-guide-claimsprincipal-httpcontext-and-httpcontextaccessor-in-net-core</link><guid isPermaLink="true">https://blog.tmurdianto.com/comprehensive-guide-claimsprincipal-httpcontext-and-httpcontextaccessor-in-net-core</guid><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Teguh Murdianto]]></dc:creator><pubDate>Tue, 11 Nov 2025 14:21:52 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-comprehensive-guide-claimsprincipal-httpcontext-and-httpcontextaccessor-in-net-core">🧠 Comprehensive Guide: <code>ClaimsPrincipal</code>, <code>HttpContext</code>, and <code>HttpContextAccessor</code> in .NET Core</h1>
<blockquote>
<p>Based on Internet Research Best Practices (10x Iterations)<br /><strong>Date:</strong> November 2025</p>
</blockquote>
<hr />
<h2 id="heading-executive-summary">📘 Executive Summary</h2>
<p>In ASP.NET Core, three key classes form the backbone of user identity and request handling:</p>
<ul>
<li><p><code>HttpContext</code> – Holds all HTTP-specific information about the current request (headers, cookies, identity, etc.)</p>
</li>
<li><p><code>ClaimsPrincipal</code> – Represents the current user and all their claims (e.g., roles, email, ID)</p>
</li>
<li><p><code>IHttpContextAccessor</code> – Safely provides access to <code>HttpContext</code> outside controllers or middleware</p>
</li>
</ul>
<h3 id="heading-why-they-matter">🧩 Why They Matter</h3>
<p>Before .NET Core, developers relied on <code>HttpContext.Current</code>, which was <strong>not thread-safe</strong> and tightly coupled business logic to the web layer.<br />.NET Core’s new design solves these issues by enabling:</p>
<p>✅ Thread-safe access to request context<br />✅ Clean dependency injection (DI)<br />✅ A flexible, claims-based identity model<br />✅ Decoupled architecture</p>
<hr />
<h2 id="heading-core-concepts">🧱 Core Concepts</h2>
<h3 id="heading-1-claims-based-authentication">1. Claims-Based Authentication</h3>
<p><strong>Claims</strong> describe facts about a subject (user, app, or service) in key-value pairs:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">new</span> Claim(ClaimTypes.Email, <span class="hljs-string">"john@company.com"</span>);
<span class="hljs-keyword">new</span> Claim(<span class="hljs-string">"sub"</span>, <span class="hljs-string">"12345"</span>);
<span class="hljs-keyword">new</span> Claim(<span class="hljs-string">"department"</span>, <span class="hljs-string">"Engineering"</span>);
</code></pre>
<p><strong>ClaimsIdentity</strong> represents a set of claims from one authentication type (e.g., “Bearer”, “Cookies”).<br /><strong>ClaimsPrincipal</strong> aggregates one or more identities — like combining your passport and driver’s license.</p>
<blockquote>
<p>🔍 A <code>ClaimsPrincipal</code> inherits all claims from all its identities.</p>
</blockquote>
<hr />
<h3 id="heading-2-httpcontext-the-request-container">2. <code>HttpContext</code>: The Request Container</h3>
<p><code>HttpContext</code> encapsulates everything about an HTTP request/response:</p>
<ul>
<li><p><code>Request</code>: Headers, cookies, form data</p>
</li>
<li><p><code>Response</code>: Status code, headers</p>
</li>
<li><p><code>User</code>: The <code>ClaimsPrincipal</code> for the authenticated user</p>
</li>
<li><p><code>Items</code>: Request-scoped storage</p>
</li>
<li><p><code>RequestServices</code>: Dependency-injected services</p>
</li>
</ul>
<p>It’s created at request start and disposed at the end — one per request.</p>
<hr />
<h3 id="heading-3-httpcontextaccessor-accessing-context-anywhere">3. <code>HttpContextAccessor</code>: Accessing Context Anywhere</h3>
<p><code>HttpContext</code> is directly available in controllers, but not in service classes.<br />That’s where <code>IHttpContextAccessor</code> comes in.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IHttpContextAccessor _httpContextAccessor;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserService</span>(<span class="hljs-params">IHttpContextAccessor httpContextAccessor</span>)</span>
    {
        _httpContextAccessor = httpContextAccessor;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetCurrentUserId</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _httpContextAccessor.HttpContext?.User
            .FindFirst(<span class="hljs-string">"sub"</span>)?.Value ?? <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedAccessException();
    }
}
</code></pre>
<p>Thread-safe and testable — no more static <code>HttpContext.Current</code>!</p>
<hr />
<h2 id="heading-problem-statement-amp-solutions">⚙️ Problem Statement &amp; Solutions</h2>
<h3 id="heading-tight-coupling-pre-net-core">❌ Tight Coupling (Pre-.NET Core)</h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> userId = HttpContext.Current.User.Identity.Name; <span class="hljs-comment">// Not testable</span>
</code></pre>
<h3 id="heading-dependency-injection-modern-net">✅ Dependency Injection (Modern .NET)</h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> userId = _contextAccessor.HttpContext?.User.FindFirst(<span class="hljs-string">"sub"</span>)?.Value;
</code></pre>
<ul>
<li><p>Thread-safe (<code>AsyncLocal&lt;T&gt;</code>)</p>
</li>
<li><p>Easily mockable for unit tests</p>
</li>
</ul>
<hr />
<h2 id="heading-architecture-amp-design">🏗️ Architecture &amp; Design</h2>
<h3 id="heading-request-pipeline-overview">Request Pipeline Overview</h3>
<pre><code class="lang-plaintext">Incoming Request
   ↓
HttpContext Created
   ↓
Authentication Middleware → Builds ClaimsPrincipal
   ↓
Authorization Middleware → Validates Policies
   ↓
Controller → Access User
   ↓
Service Layer → Inject IHttpContextAccessor
   ↓
Response Returned → HttpContext Disposed
</code></pre>
<h3 id="heading-dependency-injection-setup">Dependency Injection Setup</h3>
<pre><code class="lang-csharp">services.AddHttpContextAccessor(); <span class="hljs-comment">// Singleton registration</span>
</code></pre>
<blockquote>
<p><code>IHttpContextAccessor</code> is stateless — safe as a singleton.<br />Only access <code>HttpContext</code> inside method scope, never store it in fields.</p>
</blockquote>
<hr />
<h2 id="heading-implementation-best-practices">🧩 Implementation Best Practices</h2>
<h3 id="heading-1-register-everything-in-programcs">✅ 1. Register Everything in <code>Program.cs</code></h3>
<pre><code class="lang-csharp">builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped&lt;IUserService, UserService&gt;();
</code></pre>
<h3 id="heading-2-access-user-in-controllers">✅ 2. Access User in Controllers</h3>
<pre><code class="lang-csharp">[<span class="hljs-meta">Authorize</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetOrders</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> userId = User.FindFirst(<span class="hljs-string">"sub"</span>)?.Value;
    <span class="hljs-keyword">return</span> Ok(_orderService.GetUserOrders(userId));
}
</code></pre>
<p>Or, if you need it in the constructor, inject <code>IHttpContextAccessor</code>.</p>
<hr />
<h3 id="heading-3-access-user-in-services">✅ 3. Access User in Services</h3>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetCurrentUserId</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> user = _httpContextAccessor.HttpContext?.User;
    <span class="hljs-keyword">if</span> (user?.Identity?.IsAuthenticated != <span class="hljs-literal">true</span>)
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedAccessException();

    <span class="hljs-keyword">return</span> user.FindFirst(<span class="hljs-string">"sub"</span>)?.Value ?? <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidOperationException(<span class="hljs-string">"User ID not found"</span>);
}
</code></pre>
<hr />
<h3 id="heading-4-add-extension-methods-for-clean-code">✅ 4. Add Extension Methods for Clean Code</h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ClaimsPrincipalExtensions</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">GetUserId</span>(<span class="hljs-params"><span class="hljs-keyword">this</span> ClaimsPrincipal principal</span>)</span> =&gt;
        principal?.FindFirst(<span class="hljs-string">"sub"</span>)?.Value ??
        principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
</code></pre>
<hr />
<h3 id="heading-5-avoid-nullreferenceexceptions">✅ 5. Avoid NullReferenceExceptions</h3>
<p>Use null-conditional (<code>?.</code>) operators and null checks everywhere.</p>
<hr />
<h3 id="heading-6-never-store-httpcontext-in-fields">✅ 6. Never Store <code>HttpContext</code> in Fields</h3>
<p>Bad:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> HttpContext _context;
</code></pre>
<p>Good:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> context = _accessor.HttpContext; <span class="hljs-comment">// Access on-demand</span>
</code></pre>
<hr />
<h2 id="heading-thread-safety-amp-performance">🧵 Thread Safety &amp; Performance</h2>
<ul>
<li><p><code>HttpContext</code> is <strong>not thread-safe</strong></p>
</li>
<li><p>Use <strong>AsyncLocal</strong> (via <code>IHttpContextAccessor</code>)</p>
</li>
<li><p>Extract user data before background/parallel tasks</p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> userId = User.FindFirst(<span class="hljs-string">"sub"</span>)?.Value;
_ = Task.Run(() =&gt; ProcessInBackground(userId)); <span class="hljs-comment">// Safe</span>
</code></pre>
<p>Performance overhead? <strong>Negligible (&lt;1µs per access).</strong></p>
<hr />
<h2 id="heading-common-pitfalls-amp-solutions">⚡ Common Pitfalls &amp; Solutions</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Problem</td><td>Root Cause</td><td>Solution</td></tr>
</thead>
<tbody>
<tr>
<td><code>IsAuthenticated = false</code></td><td><code>AuthenticationType</code> not set</td><td>Provide authentication type</td></tr>
<tr>
<td><code>Name</code> is null</td><td>Non-standard claim key</td><td>Use <code>ClaimTypes.Name</code> or map via constructor</td></tr>
<tr>
<td><code>IsInRole()</code> false</td><td>Custom “role” claim key</td><td>Configure <code>RoleClaimType</code> in JWT</td></tr>
<tr>
<td><code>HttpContext</code> null in constructor</td><td>Not initialized yet</td><td>Use <code>IHttpContextAccessor</code></td></tr>
<tr>
<td>Claims missing after token refresh</td><td>Stale claims</td><td>Implement <code>IClaimsTransformation</code></td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-real-world-example-health-insurance-claims">💼 Real-World Example: Health Insurance Claims</h2>
<p>Controller extracts user ID and passes it to service for auditing:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> userId = _httpContextAccessor.HttpContext?.User.FindFirst(<span class="hljs-string">"sub"</span>)?.Value;
<span class="hljs-keyword">await</span> _claimServices.InsertClaimTransBenefit(response.Id, request.BenefitDetail, userId, ct);
</code></pre>
<p>Audit trail includes:</p>
<ul>
<li><p><code>UserId</code></p>
</li>
<li><p><code>UserName</code></p>
</li>
<li><p><code>UserEmail</code></p>
</li>
<li><p><code>IP Address</code></p>
</li>
</ul>
<hr />
<h2 id="heading-decision-guide-when-to-use-what">🧭 Decision Guide: When to Use What</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Scenario</td><td>Use</td><td>Example</td></tr>
</thead>
<tbody>
<tr>
<td>Controller / Middleware</td><td><code>User</code> or <code>HttpContext</code> directly</td><td><code>User.FindFirst("sub")</code></td></tr>
<tr>
<td>Service / Repository</td><td><code>IHttpContextAccessor</code></td><td><code>_accessor.HttpContext?.User</code></td></tr>
<tr>
<td>Background Job</td><td>No HttpContext</td><td>Pass user data as parameters</td></tr>
</tbody>
</table>
</div><h3 id="heading-quick-flow">Quick Flow:</h3>
<pre><code class="lang-markdown">Need user info?
│
├─ Controller → Use User
├─ Service → Use IHttpContextAccessor
└─ Background/Job → Pass data manually
</code></pre>
<hr />
<h2 id="heading-key-takeaways">🧠 Key Takeaways</h2>
<ul>
<li><p><code>ClaimsPrincipal</code> defines <strong>who</strong> the user is</p>
</li>
<li><p><code>HttpContext</code> describes <strong>what</strong> the request is</p>
</li>
<li><p><code>IHttpContextAccessor</code> enables <strong>safe cross-layer access</strong></p>
</li>
<li><p>Always access context on-demand and avoid storing it</p>
</li>
<li><p>Be mindful of <strong>thread safety</strong> and <strong>lifetime scopes</strong></p>
</li>
</ul>
<hr />
<h3 id="heading-references">📚 References</h3>
<ul>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor">Microsoft Docs – IHttpContextAccessor</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/standard/security/claims">Microsoft Docs – Claims-Based Identity in .NET</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-8.0">ASP.NET Core Authentication and Authorization</a></p>
</li>
<li><p><a target="_blank" href="https://andrewlock.net/introduction-to-authentication-with-asp-net-core/">Introduction to Authentication with ASP.NET Core (Andrew Lock)</a></p>
</li>
<li><p><a target="_blank" href="https://code-maze.com/aspnetcore-get-current-user-claims/">Get Current User With Claims in ASP.NET Core (Code Maze)</a></p>
</li>
<li><p><a target="_blank" href="https://thecodebuzz.com/httpcontext-best-practices-in-net-csharp-thread-safe/">HttpContext Best Practices in .NET (TheCodeBuzz)</a></p>
</li>
<li><p><a target="_blank" href="https://eddieabbondanz.io/post/aspnet/claims-based-authentication-claims-identities-principals/">Claims Based Authentication: Claims vs Identities vs Principals (Eddie Abbondanzio)</a></p>
</li>
<li><p><a target="_blank" href="https://www.benday.com/blog/3-common-problems-with-claimsidentity-and-claimsprincipal-in-asp-net-cor">3 Common Problems with ClaimsIdentity and ClaimsPrincipal (Benjamin Day)</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[From Mathematics to Tech Leadership: My Journey in Software Engineering]]></title><description><![CDATA[From Mathematics to Tech Leadership: My Journey in Software Engineering 🚀
Hey there! 👋 Ever heard of a mathematician who ended up leading tech teams? Well, that's me! My path into software engineering has been anything but ordinary. Let me tell you...]]></description><link>https://blog.tmurdianto.com/from-mathematics-to-tech-leadership-my-journey-in-software-engineering</link><guid isPermaLink="true">https://blog.tmurdianto.com/from-mathematics-to-tech-leadership-my-journey-in-software-engineering</guid><category><![CDATA[Career]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[leadership]]></category><category><![CDATA[techlead]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Mathematics]]></category><category><![CDATA[careerchange]]></category><category><![CDATA[Career Change]]></category><category><![CDATA[technology]]></category><dc:creator><![CDATA[Teguh Murdianto]]></dc:creator><pubDate>Tue, 05 Nov 2024 09:15:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730797585473/379dc686-3b10-40e7-9532-d7ba665704c0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-from-mathematics-to-tech-leadership-my-journey-in-software-engineering">From Mathematics to Tech Leadership: My Journey in Software Engineering 🚀</h1>
<p>Hey there! 👋 Ever heard of a mathematician who ended up leading tech teams? Well, that's me! My path into software engineering has been anything but ordinary. Let me tell you how I went from solving abstract mathematical problems to architecting software solutions and leading development teams.</p>
<h2 id="heading-starting-with-x-y">Starting with X + Y = ? 📚</h2>
<p>Back in 2007-2012, you'd find me buried in mathematics textbooks at Institut Teknologi Sepuluh Nopember Surabaya. Plot twist - I wasn't dreaming about becoming a software engineer back then! But here's something cool: my thesis on "Application of Expert System to support determining the strategy of security problem in Indonesia borders area" turned out to be my first step into the tech world. Talk about a happy accident! 😄</p>
<h2 id="heading-first-steps-into-tech-the-rookie-days">First Steps into Tech: The Rookie Days 👶</h2>
<p>Remember that feeling of your first day at a new job? Mine was in tech support and maintenance, staring at enterprise systems like they were written in hieroglyphics! But here's a funny thing about having a math background - I started seeing patterns everywhere.</p>
<p>Picture this: I had to fix this data integration process that was slower than a snail in molasses. Instead of panicking, I put on my math hat and broke it down like an equation. End result? Cut the processing time by 70%! My math professors would've been proud (or confused, not sure which 😅).</p>
<h2 id="heading-leveling-up-the-leadership-adventure">Leveling Up: The Leadership Adventure 🎮</h2>
<p>Talk about a plot twist - one day I'm coding away happily, the next I'm leading development teams across Android, iOS, and Backend. It's like being promoted from player to coach mid-game!</p>
<p>Here's a story that still makes me chuckle: My first team presentation as a lead was a technical masterpiece (in my head, at least). Reality check? Half my team was lost in the first five minutes. Lesson learned - being a tech lead is less about showing how smart you are and more about helping others be awesome.</p>
<h2 id="heading-the-boss-battle-that-changed-everything">The Boss Battle That Changed Everything 🎯</h2>
<p>Ever had one of those projects that felt like fighting a final boss in a video game? I hit one of those - tight deadlines, low team morale, stakeholders breathing down our necks. Instead of pushing everyone harder (my first instinct), I did something crazy: I took a step back.</p>
<p>We reorganized the team based on what people loved doing (turns out forcing your best backend dev to do frontend work isn't always smart 😅), started daily "how's it going?" chats, and boom! Two months later, we turned that project from a potential disaster into a success story.</p>
<h2 id="heading-where-im-at-now-the-current-chapter">Where I'm At Now: The Current Chapter 🎯</h2>
<p>These days, I'm living my best life as a System Analyst and Technical Leader. The cool part? I get to use BOTH my math brain and tech skills. Recently, we had this complex data analysis project, and guess who was grinning like a kid in a candy store? Yep, the math nerd in me was finally having its moment! 🤓</p>
<h2 id="heading-life-lessons-not-the-boring-kind">Life Lessons (Not the Boring Kind) 💡</h2>
<ol>
<li><p><strong>Your "Weird" Background Might Be Your Superpower</strong>: Being the "math guy" in tech turned out to be pretty awesome. Different perspectives make tech better!</p>
</li>
<li><p><strong>It's OK to Say "I Have No Clue"</strong>: Seriously, it's liberating. Plus, people trust you more when you're honest about what you don't know.</p>
</li>
<li><p><strong>Most "Technical Debt" is Actually "We Should Have Talked More" Debt</strong>: Trust me on this one - clear communication beats perfect code any day.</p>
</li>
<li><p><strong>Growth is Messy</strong>: Some of my best learning came from my biggest facepalm moments. Embrace the chaos!</p>
</li>
<li><p><strong>Everyone's a Teacher</strong>: That junior dev who just joined? They might teach you something amazing about new tech you've never heard of.</p>
</li>
</ol>
<h2 id="heading-whats-next-in-this-adventure">What's Next in This Adventure? 🎯</h2>
<p>I'm currently geeking out over combining mathematical modeling with machine learning - imagine explaining that to my old math professors! Through this blog, I'll be sharing:</p>
<ul>
<li><p>Real stories from the trenches (the good, the bad, and the "what was I thinking?")</p>
</li>
<li><p>How to survive and thrive in tech (especially if you're coming from a different background)</p>
</li>
<li><p>Leadership stuff that actually works in real life</p>
</li>
<li><p>Cool tech experiments (some successful, some... let's call them "learning experiences" 😉)</p>
</li>
<li><p>The fun side of mixing math and coding</p>
</li>
</ul>
<p>Whether you're a fellow mathematician thinking about jumping into tech, a developer looking to level up to leadership, or just someone who enjoys a good career-change story, I hope my experiences can help make your journey a bit easier (or at least more entertaining!).</p>
<p>Let's learn together, laugh at our mistakes, and build some awesome stuff along the way! Drop a comment below - I'd love to hear your story too! 🎉</p>
<p>#career #softwareengineering #leadership #techlead #programming #mathematics #careerchange #technology</p>
]]></content:encoded></item></channel></rss>