dotnet/aspnetcore · error · InvalidOperationException

The provided identity of type '{0}' is marked {1} = {2} but

Error message

The provided identity of type '{0}' is marked {1} = {2} but does not have a value for {3}. By default, the antiforgery system requires that all authenticated identities have a unique {3}. If it is not possible to provide a unique {3} for this identity, consider extending {4} by overriding the {5} or a custom type that can provide some form of unique identifier for the current user.

What it means

Thrown by GenerateRequestToken (DefaultAntiforgeryTokenGenerator.cs:80-94) when the current user is authenticated but the system cannot derive ANY unique identifier for them — no username (IIdentity.Name is empty), no extractable ClaimUid, and no AdditionalData. The antiforgery system requires every authenticated token to be bound to a unique user identifier to prevent token theft across users; if none is available, it throws InvalidOperationException.

Source

Thrown at src/Antiforgery/src/Internal/DefaultAntiforgeryTokenGenerator.cs:86

            if (requestToken.ClaimUid == null)
            {
                requestToken.Username = authenticatedIdentity.Name;
            }
        }

        // populate AdditionalData
        if (_additionalDataProvider != null)
        {
            requestToken.AdditionalData = _additionalDataProvider.GetAdditionalData(httpContext);
        }

        if (isIdentityAuthenticated
            && string.IsNullOrEmpty(requestToken.Username)
            && requestToken.ClaimUid == null
            && string.IsNullOrEmpty(requestToken.AdditionalData))
        {
            // Application says user is authenticated, but we have no identifier for the user.
            throw new InvalidOperationException(
                Resources.FormatAntiforgeryTokenValidator_AuthenticatedUserWithoutUsername(
                    authenticatedIdentity?.GetType() ?? typeof(ClaimsIdentity),
                    nameof(IIdentity.IsAuthenticated),
                    "true",
                    nameof(IIdentity.Name),
                    nameof(IAntiforgeryAdditionalDataProvider),
                    nameof(DefaultAntiforgeryAdditionalDataProvider)));
        }

        return requestToken;
    }

    /// <inheritdoc />
    public bool IsCookieTokenValid(AntiforgeryToken? cookieToken)
    {
        return cookieToken != null && cookieToken.IsCookieToken;
    }

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Set the NameClaimType in authentication options so IIdentity.Name resolves (e.g., TokenValidationParameters.NameClaimType = ClaimTypes.Name or a unique claim).
  2. Add a unique claim (sub, nameidentifier, etc.) to the identity so ClaimUidExtractor can derive a ClaimUid.
  3. Implement IAntiforgeryAdditionalDataProvider.GetAdditionalData to return a unique identifier (e.g., session ID, user ID) when standard claims aren't available.

Example fix

// before — authenticated identity with no name claim
var identity = new ClaimsIdentity(claims, "MyScheme"); // no NameClaimType

// after — set NameClaimType to a unique claim
var identity = new ClaimsIdentity(claims, "MyScheme",
    nameType: ClaimTypes.Name, roleType: ClaimTypes.Role);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the identity has a usable name before generating tokens
if (httpContext.User?.Identity?.IsAuthenticated == true)
{
    if (string.IsNullOrEmpty(httpContext.User.Identity.Name)
        && !httpContext.User.Claims.Any(c => c.Type == ClaimTypes.NameIdentifier))
    {
        throw new InvalidOperationException(
            "Authenticated identity has no Name or NameIdentifier claim for antiforgery.");
    }
}

Type guard

static bool IdentitySupportsAntiforgery(ClaimsIdentity identity)
    => identity.IsAuthenticated
       && (!string.IsNullOrEmpty(identity.Name)
           || identity.HasClaim(c => c.Type == ClaimTypes.NameIdentifier));

Prevention

When it happens

Trigger: At line 80-84: isIdentityAuthenticated is true, but requestToken.Username is empty, requestToken.ClaimUid is null, and AdditionalData is empty. This happens with authentication schemes that set IsAuthenticated=true but don't populate Name or any claims the ClaimUidExtractor can hash.

Common situations: A custom ClaimsIdentity with IsAuthenticated=true but no NameClaimType claim set; authentication middleware that authenticates via a token/header without populating standard claims; an anonymous-converted identity that retains IsAuthenticated; missing NameClaimType configuration in JwtBearer/Cookie auth options.

Understand the failure class

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/015fc69e41b7cb32. Report an issue: GitHub.