Skip to content

Instantly share code, notes, and snippets.

@wcabus
Created February 6, 2026 13:24
Show Gist options
  • Select an option

  • Save wcabus/8572d45f0235a9dda14f3811960fe01e to your computer and use it in GitHub Desktop.

Select an option

Save wcabus/8572d45f0235a9dda14f3811960fe01e to your computer and use it in GitHub Desktop.
C#14 extensions for the ClaimsPrincipal, ClaimsIdentity and AuthenticationProperties types, adding both static methods and useful properties.
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
namespace Duende.Extensions;
internal static class SecurityExtensions
{
private static readonly ClaimsPrincipal Anonymous = new(new ClaimsIdentity());
extension(ClaimsPrincipal)
{
/// <summary>
/// Gets an anonymous <see cref="ClaimsPrincipal"/> instance with an empty <see cref="ClaimsIdentity"/>.
/// </summary>
/// <remarks>
/// This can be used as a placeholder for unauthenticated users or in scenarios where you want to represent an
/// anonymous user without any claims or authentication information.
/// </remarks>
public static ClaimsPrincipal Anonymous => Anonymous;
/// <summary>
/// Creates a new authenticated <see cref="ClaimsPrincipal"/> with the specified authentication type and claims.
/// </summary>
/// <param name="authenticationType">The type of authentication used.</param>
/// <param name="claims">The claims with which to populate the inner <see cref="ClaimsIdentity"/>.</param>
public static ClaimsPrincipal CreateAuthenticatedPrincipal(string authenticationType, params Claim[] claims)
{
return new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType));
}
/// <summary>
/// Creates a new authenticated <see cref="ClaimsPrincipal"/> with the specified authentication type, claims,
/// name claim type and role claim type.
/// </summary>
/// <param name="authenticationType">The type of authentication used.</param>
/// <param name="nameClaimType">The claim type to use for the user's name (e.g., "name", "preferred_username", etc.).</param>
/// <param name="roleClaimType">The claim type to use for the user's roles (e.g., "role", "roles", etc.).</param>
/// <param name="claims">The claims with which to populate the inner <see cref="ClaimsIdentity"/>.</param>
public static ClaimsPrincipal CreateAuthenticatedPrincipal(string authenticationType, string nameClaimType, string roleClaimType, params Claim[] claims)
{
return new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType, nameClaimType, roleClaimType));
}
}
internal const string SubjectClaimType = "sub";
internal const string NameClaimType = "name";
internal const string GivenNameClaimType = "given_name";
internal const string FamilyNameClaimType = "family_name";
internal const string UsernameClaimType = "preferred_username";
internal const string EmailClaimType = "email";
internal const string RoleClaimType = "role";
extension(ClaimsPrincipal user)
{
/// <summary>
/// Returns <c>true</c> if the user is authenticated; otherwise, <c>false</c>.
/// </summary>
/// <remarks>
/// This checks the <see cref="ClaimsPrincipal.Identity"/> property and its <see cref="ClaimsIdentity.IsAuthenticated"/> property.
/// </remarks>
public bool IsAuthenticated => user.Identity?.IsAuthenticated ?? false;
/// <summary>
/// Returns the value of the "sub" claim, which is commonly used to represent the user's unique identifier (subject ID) in authentication systems.
/// </summary>
public string SubjectId => user.FindFirst(SubjectClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "name" claim, which is commonly used to represent the user's full name or display name in authentication systems.
/// </summary>
public string Name => user.FindFirst(NameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "given_name" claim, which is commonly used to represent the user's first name in authentication systems.
/// </summary>
public string GivenName => user.FindFirst(GivenNameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "family_name" claim, which is commonly used to represent the user's last name or surname in authentication systems.
/// </summary>
public string FamilyName => user.FindFirst(FamilyNameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "preferred_username" claim, which is commonly used to represent the user's username or login name in authentication systems.
/// </summary>
public string UserName => user.FindFirst(UsernameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "email" claim, which is commonly used to represent the user's email address in authentication systems.
/// </summary>
public string Email => user.FindFirst(EmailClaimType)?.Value ?? "";
/// <summary>
/// Returns an enumeration of role claim values for the user, based on claims of the "role" claim type.
/// </summary>
public IEnumerable<string> Roles => user.Claims.Where(c => c.Type == RoleClaimType && !string.IsNullOrEmpty(c.Value)).Select(c => c.Value);
}
extension(ClaimsIdentity identity)
{
/// <summary>
/// Returns the value of the "sub" claim, which is commonly used to represent the user's unique identifier (subject ID) in authentication systems.
/// </summary>
public string SubjectId => identity.FindFirst(SubjectClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "name" claim, which is commonly used to represent the user's full name or display name in authentication systems.
/// </summary>
public string Name => identity.FindFirst(NameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "given_name" claim, which is commonly used to represent the user's first name in authentication systems.
/// </summary>
public string GivenName => identity.FindFirst(GivenNameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "family_name" claim, which is commonly used to represent the user's last name or surname in authentication systems.
/// </summary>
public string FamilyName => identity.FindFirst(FamilyNameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "preferred_username" claim, which is commonly used to represent the user's username or login name in authentication systems.
/// </summary>
public string UserName => identity.FindFirst(UsernameClaimType)?.Value ?? "";
/// <summary>
/// Returns the value of the "email" claim, which is commonly used to represent the user's email address in authentication systems.
/// </summary>
public string Email => identity.FindFirst(EmailClaimType)?.Value ?? "";
/// <summary>
/// Returns an enumeration of role claim values for the user, based on claims of the "role" claim type.
/// </summary>
public IEnumerable<string> Roles => identity.Claims.Where(c => c.Type == RoleClaimType && !string.IsNullOrEmpty(c.Value)).Select(c => c.Value);
}
internal const string SessionIdKey = "session_id";
extension(AuthenticationProperties properties)
{
/// <summary>
/// Gets or sets the user's session identifier, stored using the "session_id" key in <see cref="AuthenticationProperties.Items"/>.
/// </summary>
public string? SessionId
{
get => properties.Items.TryGetValue(SessionIdKey, out var value) == true ? value : null;
// Example of a setter. Careful with this, as it will overwrite any existing value for the "session_id" key in the Items dictionary!
set => properties.Items[SessionIdKey] = value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment