|
|
|
@ -9,6 +9,7 @@ using System.Security.Claims; |
|
|
|
using Microsoft.Extensions.DependencyInjection; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using Microsoft.IdentityModel.Tokens; |
|
|
|
using OpenIddict.Extensions; |
|
|
|
|
|
|
|
namespace OpenIddict.Client; |
|
|
|
|
|
|
|
@ -399,7 +400,7 @@ public class OpenIddictClientService |
|
|
|
|
|
|
|
// Create a composite principal containing claims resolved from the
|
|
|
|
// backchannel identity token and the userinfo token, if available.
|
|
|
|
return (context.TokenResponse, CreatePrincipal( |
|
|
|
return (context.TokenResponse, OpenIddictHelpers.CreateMergedPrincipal( |
|
|
|
context.BackchannelIdentityTokenPrincipal, |
|
|
|
context.UserinfoTokenPrincipal)); |
|
|
|
} |
|
|
|
@ -491,7 +492,7 @@ public class OpenIddictClientService |
|
|
|
|
|
|
|
// Create a composite principal containing claims resolved from the
|
|
|
|
// backchannel identity token and the userinfo token, if available.
|
|
|
|
return (context.TokenResponse, CreatePrincipal( |
|
|
|
return (context.TokenResponse, OpenIddictHelpers.CreateMergedPrincipal( |
|
|
|
context.BackchannelIdentityTokenPrincipal, |
|
|
|
context.UserinfoTokenPrincipal)); |
|
|
|
} |
|
|
|
@ -576,7 +577,7 @@ public class OpenIddictClientService |
|
|
|
|
|
|
|
// Create a composite principal containing claims resolved from the
|
|
|
|
// backchannel identity token and the userinfo token, if available.
|
|
|
|
return (context.TokenResponse, CreatePrincipal( |
|
|
|
return (context.TokenResponse, OpenIddictHelpers.CreateMergedPrincipal( |
|
|
|
context.BackchannelIdentityTokenPrincipal, |
|
|
|
context.UserinfoTokenPrincipal)); |
|
|
|
} |
|
|
|
@ -937,43 +938,4 @@ public class OpenIddictClientService |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static ClaimsPrincipal CreatePrincipal(params ClaimsPrincipal?[] principals) |
|
|
|
{ |
|
|
|
// Note: the OpenIddict client handler can be used as a pure OAuth 2.0-only stack for
|
|
|
|
// delegation scenarios where the identity of the user is not needed. In this case,
|
|
|
|
// since no principal can be resolved from a token or a userinfo response to construct
|
|
|
|
// a user identity, a fake one containing an "unauthenticated" identity (i.e with its
|
|
|
|
// AuthenticationType property deliberately left to null) is used to allow ASP.NET Core
|
|
|
|
// to return a "successful" authentication result for these delegation-only scenarios.
|
|
|
|
if (!principals.Any(principal => principal?.Identity is ClaimsIdentity { IsAuthenticated: true })) |
|
|
|
{ |
|
|
|
return new ClaimsPrincipal(new ClaimsIdentity()); |
|
|
|
} |
|
|
|
|
|
|
|
// Create a new composite identity containing the claims of all the principals.
|
|
|
|
var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType); |
|
|
|
|
|
|
|
foreach (var principal in principals) |
|
|
|
{ |
|
|
|
// Note: the principal may be null if no value was extracted from the corresponding token.
|
|
|
|
if (principal is null) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var claim in principal.Claims) |
|
|
|
{ |
|
|
|
// If a claim with the same type and the same value already exist, skip it.
|
|
|
|
if (identity.HasClaim(claim.Type, claim.Value)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
identity.AddClaim(claim); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return new ClaimsPrincipal(identity); |
|
|
|
} |
|
|
|
} |
|
|
|
|