{"record":{"id":"18f89eb4fa1a48e1","repo":"OrchardCMS/OrchardCore","slug":"no-suitable-user-name-can-be-found-in-the-principal","errorCode":null,"errorMessage":"No suitable user name can be found in the principal.","messagePattern":"No suitable user name can be found in the principal\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.OpenId/OpenIdExtensions.cs","lineNumber":23,"sourceCode":"\ninternal static class OpenIdExtensions\n{\n    internal static string GetUserIdentifier(this ClaimsIdentity identity)\n        => identity.FindFirst(Claims.Subject)?.Value ??\n           identity.FindFirst(ClaimTypes.NameIdentifier)?.Value ??\n           identity.FindFirst(ClaimTypes.Upn)?.Value ??\n           throw new InvalidOperationException(\"No suitable user identifier can be found in the identity.\");\n\n    internal static string GetUserIdentifier(this ClaimsPrincipal principal)\n        => principal.FindFirst(Claims.Subject)?.Value ??\n           principal.FindFirst(ClaimTypes.NameIdentifier)?.Value ??\n           principal.FindFirst(ClaimTypes.Upn)?.Value ??\n           throw new InvalidOperationException(\"No suitable user identifier can be found in the principal.\");\n\n    internal static string GetUserName(this ClaimsPrincipal principal)\n        => principal.FindFirst(Claims.Name)?.Value ??\n           principal.FindFirst(ClaimTypes.Name)?.Value ??\n           throw new InvalidOperationException(\"No suitable user name can be found in the principal.\");\n\n    internal static string[] GetRoles(this ClaimsPrincipal principal)\n        => principal.FindAll(c => c.Type is Claims.Role or ClaimTypes.Role)\n        .Select(x => x.Value)\n        .Distinct()\n        .ToArray();\n\n    internal static async Task<bool> AnyAsync<T>(this IAsyncEnumerable<T> source)\n    {\n        ArgumentNullException.ThrowIfNull(source);\n\n        await using var enumerator = source.GetAsyncEnumerator();\n        return await enumerator.MoveNextAsync();\n    }\n\n    internal static Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source)\n    {\n        ArgumentNullException.ThrowIfNull(source);","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.OpenId/OpenIdExtensions.cs#L5-L41","documentation":"OpenIdExtensions.GetUserName extracts a user name from a ClaimsPrincipal, checking OpenID Connect 'name' (Claims.Name) first, then ClaimTypes.Name. If neither claim exists on the principal it throws InvalidOperationException because downstream code (e.g. mapping external logins to a local user) requires a displayable name.","triggerScenarios":"Calling GetUserName on a principal whose identity token contains no 'name' or 'nameidentifier'-style Name claim — e.g. an OpenID Connect provider that only sends 'sub', or a token missing the 'profile'/'email' scopes that populate name claims.","commonSituations":"Configuring an external OIDP (Keycloak, Auth0, Azure AD) without requesting the profile scope; a misconfigured claim-type mapping so the provider's name claim isn't mapped to ClaimTypes.Name; custom tokens issued without standard claims.","solutions":["Request the 'profile' (and 'openid') scopes on the OpenIdConnect client options so the name claim is issued","Configure ClaimActions/claim-type mappings so the provider's display-name claim maps to ClaimTypes.Name","Use GetUserName on principals known to carry name claims, or fall back to the 'sub'/NameIdentifier claim for user lookup","Wrap in try-catch and handle missing-name principals explicitly (e.g. prompt user for a username)"],"exampleFix":"// before\nvar name = principal.GetUserName();\n// after\nvar name = principal.FindFirst(Claims.Name)?.Value\n    ?? principal.FindFirst(ClaimTypes.Name)?.Value\n    ?? principal.FindFirst(ClaimTypes.NameIdentifier)?.Value\n    ?? throw new InvalidOperationException(\"No suitable user name can be found in the principal.\");","handlingStrategy":"validation","validationCode":"if (principal?.Identity?.IsAuthenticated != true ||\n    (principal.FindFirst(ClaimTypes.Name) is null && principal.FindFirst(\"name\") is null)) {\n    throw new InvalidOperationException(\"Principal has no name claim; request 'profile' scope or map claims first.\");\n}","typeGuard":null,"tryCatchPattern":"try { name = principal.GetUserName(); } catch (InvalidOperationException ex) { logger.LogWarning(ex, \"Principal missing name claim\"); /* fallback to subject claim */ }","preventionTips":["Always request openid and profile scopes from the OIDP","Verify claim-type mappings (ClaimActions) in the OIDC options during integration testing","Log principal claims when debugging external logins"],"tags":["openid","claims","authentication"],"backgroundTag":"null-argument","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}