Skip to content

Clarify session migration from framework to core #35684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
51cd5ba
Initial fx-to-core session rewrite
twsouthwick Jun 30, 2025
46e0529
update
twsouthwick Jun 30, 2025
7213d94
Include built-in asp.net session migration
twsouthwick Jun 30, 2025
2866ad6
clarify decision tree for session
twsouthwick Jun 30, 2025
13264b0
clarify introduction
twsouthwick Jun 30, 2025
59c8f3d
fix cross reference
twsouthwick Jun 30, 2025
9d55732
add serialization details
twsouthwick Jun 30, 2025
85abdda
move samples
twsouthwick Jun 30, 2025
78e5524
move session images
twsouthwick Jun 30, 2025
ef2f0e3
fix cross reference
twsouthwick Jun 30, 2025
0b14eab
clean up remote-app setup
twsouthwick Jun 30, 2025
2deb4b1
some links
twsouthwick Jun 30, 2025
d4e6443
rework authentication
twsouthwick Jun 30, 2025
e09a90e
fix cross references
twsouthwick Jun 30, 2025
9144675
expand starting
twsouthwick Jun 30, 2025
efacc90
combine unit testing into systemweb-adapters
twsouthwick Jun 30, 2025
ec497b8
update httpcontext docs
twsouthwick Jun 30, 2025
0bebf0c
list again
twsouthwick Jun 30, 2025
aa224b0
spread out usage_guidance
twsouthwick Jun 30, 2025
e5c5fa9
clean up errors
twsouthwick Jun 30, 2025
9bed760
update
twsouthwick Jun 30, 2025
6f48d2b
toc
twsouthwick Jun 30, 2025
45bf6b1
toc
twsouthwick Jun 30, 2025
7f812ff
claimsprincipal
twsouthwick Jun 30, 2025
9cefae4
xref
twsouthwick Jun 30, 2025
587ec61
update title
twsouthwick Jun 30, 2025
6e330bf
remove
twsouthwick Jun 30, 2025
606c2bd
update remote app setup
twsouthwick Jun 30, 2025
82b445b
add ?displayProperty=nameWithType
twsouthwick Jun 30, 2025
bb03021
add type
twsouthwick Jun 30, 2025
b000cec
response patterns
twsouthwick Jun 30, 2025
fa557b3
add proxy guidance
twsouthwick Jun 30, 2025
7dd4df0
add missing back ticks
twsouthwick Jun 30, 2025
da1b8cf
fix link
twsouthwick Jun 30, 2025
afeb122
clean up overview
twsouthwick Jun 30, 2025
b4e0a12
remove advanced auth - not needed
twsouthwick Jul 1, 2025
fe3a210
add aspire pivots
twsouthwick Jul 1, 2025
fb9ed92
add windows requirement
twsouthwick Jul 1, 2025
41f9304
warnings
twsouthwick Jul 1, 2025
fb33eba
Revert aspire stuff
twsouthwick Jul 1, 2025
37b6d46
Add documentation for using incremental setup with Aspire
twsouthwick Jul 1, 2025
fb16904
move enable session
twsouthwick Jul 1, 2025
3b576a4
fix whitespace
twsouthwick Jul 1, 2025
c1f9415
update sesison
twsouthwick Jul 1, 2025
5597f87
fix up sample
twsouthwick Jul 1, 2025
6cb428c
more session
twsouthwick Jul 1, 2025
dfd2c39
move to includes
twsouthwick Jul 1, 2025
907bbc7
remove path
twsouthwick Jul 1, 2025
d368de0
reword
twsouthwick Jul 1, 2025
4a0fab0
move
twsouthwick Jul 1, 2025
fbfb55f
better headers
twsouthwick Jul 1, 2025
fcbb991
better manual steps
twsouthwick Jul 1, 2025
f95e303
add incremental pivot
twsouthwick Jul 1, 2025
ce354a8
Revert "add incremental pivot"
twsouthwick Jul 1, 2025
31a847e
add version
twsouthwick Jul 1, 2025
33166b4
fix ordering
twsouthwick Jul 1, 2025
8e7f078
version
twsouthwick Jul 1, 2025
f1b134b
updates per feedback
twsouthwick Jul 14, 2025
e92b221
consolidate
twsouthwick Jul 14, 2025
d7380c5
warn
twsouthwick Jul 14, 2025
869d011
index
twsouthwick Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 36 additions & 6 deletions .openpublishing.redirection.json
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,16 @@
"redirect_url": "/aspnet/core/migration/fx-to-core/systemweb-adapters",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/inc/unit-testing.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/systemweb-adapters",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/fx-to-core/inc/unit-testing.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/systemweb-adapters",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/inc/blazor.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/blazor",
Expand All @@ -1022,7 +1032,7 @@
},
{
"source_path": "aspnetcore/migration/inc/overview.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/overview",
"redirect_url": "/aspnet/core/migration/fx-to-core/index",
"redirect_document_id": false
},
{
Expand All @@ -1047,24 +1057,44 @@
},
{
"source_path": "aspnetcore/migration/inc/start.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/start",
"redirect_url": "/aspnet/core/migration/fx-to-core/start",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/inc/unit-testing.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/unit-testing",
"source_path": "aspnetcore/migration/inc/usage_guidance.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/inc/usage_guidance.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/usage_guidance",
"source_path": "aspnetcore/migration/fx-to-core/inc/usage_guidance.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/inc/wrapped.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/inc/wrapped",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/fx-to-core/inc/remote-session.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/areas/session#remote-app-session-state",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/fx-to-core/inc/remote-authentication.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/areas/authentication#remote-authentication",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/fx-to-core/inc/session.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/areas/session",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/migration/fx-to-core/inc/wrapped.md",
"redirect_url": "/aspnet/core/migration/fx-to-core/areas/session#wrapped-aspnet-core-session-state",
"redirect_document_id": false
},
{
"source_path": "aspnetcore/security/blazor/server-side.md",
"redirect_url": "/aspnet/core/blazor/security/server/",
Expand Down
374 changes: 374 additions & 0 deletions aspnetcore/migration/fx-to-core/areas/authentication.md

Large diffs are not rendered by default.

205 changes: 188 additions & 17 deletions aspnetcore/migration/fx-to-core/areas/claimsprincipal-current.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,202 @@
---
title: Migrate from ClaimsPrincipal.Current
title: Migrate from static ClaimsPrincipal access
author: mjrousos
description: Learn how to migrate away from ClaimsPrincipal.Current to retrieve the current authenticated user's identity and claims in ASP.NET Core.
description: Learn how to migrate away from static ClaimsPrincipal access to retrieve the current authenticated user's identity and claims in ASP.NET Core.
ms.author: wpickett
ms.custom: mvc
ms.date: 03/26/2019
ms.date: 06/30/2025
uid: migration/fx-to-core/areas/claimsprincipal-current
---
# Migrate from ClaimsPrincipal.Current
# Migrate from static ClaimsPrincipal access

In ASP.NET 4.x projects, it was common to use <xref:System.Security.Claims.ClaimsPrincipal.Current%2A?displayProperty=nameWithType> to retrieve the current authenticated user's identity and claims. In ASP.NET Core, this property is no longer set. Code that was depending on it needs to be updated to get the current authenticated user's identity through a different means.
The current ClaimsPrincipal is a fundamental component of authenticated web applications, providing access to the current user's identity and claims. When migrating from ASP.NET Framework to ASP.NET Core, accessing this presents unique challenges because the two frameworks have different approaches to user context management.

## Context-specific state instead of static state
## Why static ClaimsPrincipal migration is complex

When using ASP.NET Core, the values of both `ClaimsPrincipal.Current` and `Thread.CurrentPrincipal` aren't set. These properties both represent static state, which ASP.NET Core generally avoids. Instead, ASP.NET Core uses [dependency injection](xref:fundamentals/dependency-injection) (DI) to provide dependencies such as the current user's identity. Getting the current user's identity from DI is more testable, too, since test identities can be easily injected.
ASP.NET Framework and ASP.NET Core have fundamentally different approaches to accessing the current user:

## Retrieve the current user in an ASP.NET Core app
* **ASP.NET Framework** uses static properties like <xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType> and <xref:System.Threading.Thread.CurrentPrincipal?displayProperty=nameWithType> with automatic context management. These properties are interchangeable and both provide access to the current user's identity.
* **ASP.NET Core** stores the current user in <xref:Microsoft.AspNetCore.Http.HttpContext.User?displayProperty=nameWithType> and avoids static state.

There are several options for retrieving the current authenticated user's `ClaimsPrincipal` in ASP.NET Core in place of `ClaimsPrincipal.Current`:
These differences mean you can't simply continue using static principal properties (<xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType> or <xref:System.Threading.Thread.CurrentPrincipal?displayProperty=nameWithType>) in ASP.NET Core without changes. By default, the static properties aren't set, and code depending on them needs to be updated to get the current authenticated user's identity through different means.

* **ControllerBase.User**. MVC controllers can access the current authenticated user with their <xref:Microsoft.AspNetCore.Mvc.ControllerBase.User%2A> property.
* **HttpContext.User**. Components with access to the current `HttpContext` (middleware, for example) can get the current user's `ClaimsPrincipal` from <xref:Microsoft.AspNetCore.Http.HttpContext.User%2A?displayProperty=nameWithType>.
* **Passed in from caller**. Libraries without access to the current `HttpContext` are often called from controllers or middleware components and can have the current user's identity passed as an argument.
* **IHttpContextAccessor**. The project being migrated to ASP.NET Core may be too large to easily pass the current user's identity to all necessary locations. In such cases, <xref:Microsoft.AspNetCore.Http.IHttpContextAccessor> can be used as a workaround. `IHttpContextAccessor` is able to access the current `HttpContext` (if one exists). If DI is being used, see <xref:fundamentals/httpcontext>. A short-term solution to getting the current user's identity in code that hasn't yet been updated to work with ASP.NET Core's DI-driven architecture would be:
## Migration strategies overview

* Make `IHttpContextAccessor` available in the DI container by calling [AddHttpContextAccessor](https://github.com/aspnet/Hosting/issues/793) in `Startup.ConfigureServices`.
* Get an instance of `IHttpContextAccessor` during startup and store it in a static variable. The instance is made available to code that was previously retrieving the current user from a static property.
* Retrieve the current user's `ClaimsPrincipal` using `HttpContextAccessor.HttpContext?.User`. If this code is used outside of the context of an HTTP request, the `HttpContext` is null.
You have two main approaches for handling static principal access during migration:

The final option, using an `IHttpContextAccessor` instance stored in a static variable, is contrary to the ASP.NET Core principle of preferring injected dependencies to static dependencies. Plan to eventually retrieve `IHttpContextAccessor` instances from DI instead. A static helper can be a useful bridge, though, when migrating large existing ASP.NET apps that use `ClaimsPrincipal.Current`.
1. **Complete rewrite** - Rewrite all static principal access code to use ASP.NET Core's native patterns
2. **System.Web adapters** - Use adapters to enable static access patterns during incremental migration

For most applications, migrating to ASP.NET Core's native ClaimsPrincipal access provides the best performance and maintainability. However, larger applications or those with extensive static principal usage may benefit from using System.Web adapters during incremental migration.

## Choose your migration approach

You have two main options for migrating static principal access from ASP.NET Framework to ASP.NET Core. Your choice depends on your migration timeline, whether you need to run both applications simultaneously, and how much code you're willing to rewrite.

### Quick decision guide

**Answer these questions to choose your approach:**

1. **Are you doing a complete rewrite or incremental migration?**
* Complete rewrite → [Complete rewrite to ASP.NET Core patterns](#complete-rewrite-to-aspnet-core-patterns)
* Incremental migration → Continue to question 2

2. **Do you have extensive static principal usage (<xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType> or <xref:System.Threading.Thread.CurrentPrincipal?displayProperty=nameWithType>) across shared libraries?**
* Yes, lots of shared code → [System.Web adapters](#systemweb-adapters)
* No, isolated static principal usage → [Complete rewrite to ASP.NET Core patterns](#complete-rewrite-to-aspnet-core-patterns)

### Migration approaches comparison

| Approach | Code Changes | Performance | Shared Libraries | When to Use |
|----------|-------------|-------------|------------------|-------------|
| **[Complete rewrite](#complete-rewrite-to-aspnet-core-patterns)** | High - Rewrite all static principal access | Best | Requires updates | Complete rewrites, performance-critical apps |
| **[System.Web adapters](#systemweb-adapters)** | Low - Keep existing patterns | Good | Works with existing code | Incremental migrations, extensive static access |

## Complete rewrite to ASP.NET Core patterns

Choose this approach when you're performing a complete migration or want the best performance and maintainability.

ASP.NET Core provides several options for retrieving the current authenticated user's <xref:System.Security.Claims.ClaimsPrincipal> without relying on static properties. This approach requires rewriting static principal access code but offers the most benefits in the long term.

### Complete rewrite pros and cons

| Pros | Cons |
|------|------|
| Best performance | Requires rewriting all static principal access code |
| More testable (dependency injection) | No automatic migration path |
| No static dependencies | Learning curve for new patterns |
| Native ASP.NET Core implementation | Breaking change from Framework patterns |
| Thread-safe by design | Potential refactoring across shared libraries |

### ASP.NET Core ClaimsPrincipal access patterns

There are several options for retrieving the current authenticated user's <xref:System.Security.Claims.ClaimsPrincipal> in ASP.NET Core in place of <xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType>:

* **<xref:Microsoft.AspNetCore.Mvc.ControllerBase.User?displayProperty=nameWithType>**
* **<xref:Microsoft.AspNetCore.Http.HttpContext.User?displayProperty=nameWithType>**
* **Passed in from caller**. Libraries without access to the current <xref:Microsoft.AspNetCore.Http.HttpContext> are often called from controllers or middleware components and can have the current user's identity passed as an argument.
* **<xref:Microsoft.AspNetCore.Http.IHttpContextAccessor>**. The project being migrated to ASP.NET Core may be too large to easily pass the current user's identity to all necessary locations. In such cases, <xref:Microsoft.AspNetCore.Http.IHttpContextAccessor> can be used as a workaround. This is not ideal as it uses a static accessor behind the scenes. Prefer a more direct option if possible.

### Code examples

Here are examples of migrating common static principal usage patterns:

**ASP.NET Framework (before):**
```csharp
public class UserService
{
public string GetCurrentUserId()
{
// Both ClaimsPrincipal.Current and Thread.CurrentPrincipal work interchangeably
return ClaimsPrincipal.Current?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
// or: return Thread.CurrentPrincipal?.Identity?.Name;
}
}
```

**ASP.NET Core (after) - Pass ClaimsPrincipal as parameter:**
```csharp
public class UserService
{
public string GetCurrentUserId(ClaimsPrincipal user)
{
return user?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
}

// Usage in controller
public class HomeController : Controller
{
private readonly UserService _userService;

public HomeController(UserService userService)
{
_userService = userService;
}

public IActionResult Index()
{
var userId = _userService.GetCurrentUserId(User);
return View();
}
}
```

**ASP.NET Core (after) - Dependency Injection:**
```csharp
public class UserService
{
private readonly IHttpContextAccessor _httpContextAccessor;

public UserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}

public string GetCurrentUserId()
{
return _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
}
```

### When to choose this approach

* You can afford to rewrite static principal access code
* Performance is a top priority (in this case, prefer passing the identity as a parameter over DI)
* You want to eliminate static dependencies
* You're not sharing code with legacy applications
* You want the most testable and maintainable solution

## System.Web adapters

[!INCLUDE[](~/migration/fx-to-core/includes/uses-systemweb-adapters.md)]

Choose this approach when you need to maintain existing static principal usage patterns during incremental migration, or when you have extensive shared libraries that would be difficult to update.

The System.Web adapters can enable both <xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType> and <xref:System.Threading.Thread.CurrentPrincipal?displayProperty=nameWithType> support in ASP.NET Core, allowing you to keep existing code patterns while migrating incrementally. Both properties work interchangeably once adapters are configured.

### System.Web adapters pros and cons

| Pros | Cons |
|------|------|
| Minimal code changes required | Performance overhead |
| Works with existing shared libraries | Not thread-safe in all scenarios |
| Enables incremental migration | Requires System.Web adapters dependency |
| Maintains familiar patterns | Should be temporary solution |
| Good for large codebases | Less testable than DI patterns |

### Setting up static principal support

To enable static principal support (<xref:System.Security.Claims.ClaimsPrincipal.Current?displayProperty=nameWithType> and <xref:System.Threading.Thread.CurrentPrincipal?displayProperty=nameWithType>) with System.Web adapters, endpoints must be annotated with the `SetThreadCurrentPrincipalAttribute` metadata:

```csharp
// Add to controller or action
[SetThreadCurrentPrincipal]
public class HomeController : Controller
{
public IActionResult Index()
{
// Both ClaimsPrincipal.Current and Thread.CurrentPrincipal are now available
var user1 = ClaimsPrincipal.Current;
var user2 = Thread.CurrentPrincipal;
return View();
}
}
```

### When to use System.Web adapters

* You have extensive static principal usage across shared libraries
* You're doing an incremental migration
* You can't afford to rewrite all static principal access code immediately
* You need to maintain compatibility with existing ASP.NET Framework code
* You understand the performance and threading implications

## Migration considerations

### Performance implications

* **Native ASP.NET Core patterns** provide the best performance with no overhead
* **System.Web adapters** introduce some performance overhead but enable gradual migration
* **Static variables** should be avoided as they can cause memory leaks and threading issues
Loading