OpenIddict — Выход с idToken на предъявителе невозможен

#c# #openiddict

Вопрос:

Я довольно новичок в OpenIddict, и я изо всех сил пытаюсь получить соответствующий принципал в функции выхода из системы authorizationController, когда функция вызывается из Postman. Вход в систему отлично работает от почтальона, и вход выход из MVC-клиента также работает нормально.

Я не понимаю, почему IDTokenHint, установленный клиентом MVC, сопоставляется OpenIddict с правильным участником, но IdTokenHint, установленный в обработчике ValidateLogoutRequestContext, — нет. Кто-нибудь может мне помочь, пожалуйста?

Вот что я пытался:

Startup.cs:

 public void ConfigureServices(IServiceCollection services)
{
                services.AddOpenIddict()
               .AddServer(options =>
               {
                   options.RegisterScopes(OpenIddictConstants.Scopes.OpenId,
                                   OpenIddictConstants.Scopes.Profile);
                   options.AddDevelopmentEncryptionCertificate()
                          .AddDevelopmentSigningCertificate();
                   options.AllowClientCredentialsFlow().AllowAuthorizationCodeFlow().AllowHybridFlow();
                   options.SetAuthorizationEndpointUris("/connect/authorize")
                          .SetTokenEndpointUris("/connect/token").SetLogoutEndpointUris("/connect/logout");
    
                    options
                       .AddEphemeralEncryptionKey()
                       .AddEphemeralSigningKey()
                       .DisableAccessTokenEncryption();
                   options.EnableDegradedMode();
                   options.UseAspNetCore().EnableTokenEndpointPassthrough().
                   EnableAuthorizationEndpointPassthrough().EnableLogoutEndpointPassthrough();
    
                         options.AddEventHandler<OpenIddict.Server.OpenIddictServerEvents.ValidateLogoutRequestContext>(builder =>
                     builder.UseInlineHandler(context =>
                     {
                         var x = context.PostLogoutRedirectUri;
                         var authHeader = context.Transaction.GetHttpRequest()?.Headers["Authorization"];
                         if (!string.IsNullOrEmpty(authHeader))
                         {
                             var auth = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(authHeader);
                             if (auth.Scheme == "Bearer")
                             {
                                 context.Request.IdTokenHint = auth.Parameter;
                             }
                         }
      
                         return defau<
                     }));
 

authorizationController.cs

 [HttpGet("~/connect/logout")]
[HttpPost("~/connect/logout")]
public async Task LogoutAsync()
{
    var request = HttpContext.GetOpenIddictServerRequest();
    var clientId = request.ClientId;
     var principal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme))?.Principal;
  
    if (principal != null) {
        var name = principal.Identity.Name;
        if (string.IsNullOrEmpty(name) amp;amp; principal.HasClaim(System.Security.Claims.ClaimTypes.Name)) 
            name = principal.GetClaim(System.Security.Claims.ClaimTypes.Name);
        if (string.IsNullOrEmpty(name) amp;amp; principal.HasClaim(OpenIddictConstants.Claims.Subject))
            name = principal.GetClaim(OpenIddictConstants.Claims.Subject);
        var claims = new List<Claim>
        {
            new Claim(System.Security.Claims.ClaimTypes.Name, name),
        };

        if (principal.HasClaim(System.Security.Claims.ClaimTypes.Sid)) claims.Add(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Sid, principal.GetClaim(System.Security.Claims.ClaimTypes.Sid)));
        if (principal.HasClaim(System.Security.Claims.ClaimTypes.Email)) claims.Add(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, principal.GetClaim(System.Security.Claims.ClaimTypes.Email)));
        if (principal.HasClaim(OpenIddictConstants.Claims.AuthorizedParty)) clientId = principal.GetClaim(OpenIddictConstants.Claims.AuthorizedParty);
        var claimsIdentity = new System.Security.Claims.ClaimsIdentity(claims, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme);
        var claimsPrincipal = new System.Security.Claims.ClaimsPrincipal(claimsIdentity);
        await HttpContext.SignInAsync(claimsPrincipal);
        //perform some custom logout tasks
        await Helpers.Func.LogoutAsync(claimsPrincipal, settings, HttpContext, clientId);
    }
    await HttpContext.SignOutAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

}
 

И это то, что делает MVC-клиент, где работает выход из системы:

AccountController.cs (MVC-Клиент)

 [HttpGet(), HttpPost()]
        [Route("/logout")]
        public async Task<IActionResult> LogOut()
        {
            await HttpContext.SignOutAsync(Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectDefaults.AuthenticationScheme);
            return SignOut(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme);
        }
 

Startup.cs (MVC-Клиент, IdTokenHint устанавливается с помощью контекста.Протокольное сообщение)

  services.AddAuthentication(options =>
            {
                options.DefaultScheme = "smart"; 
            })
            .AddPolicyScheme("smart", "Bearer or Cookie", options =>
                {
                    options.ForwardDefaultSelector = context =>
                    {
                        var bearerAuth = context.Request.Headers["Authorization"].FirstOrDefault()?.StartsWith("Bearer ") ?? false;

                        if (bearerAuth)
                            return Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;
                        else
                            return Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme;
                    };
                })
            .AddCookie(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath = "/login";
                options.AccessDeniedPath = "/login";
                options.LogoutPath = "/logout";
                options.ExpireTimeSpan = TimeSpan.FromMinutes(50);
                options.SlidingExpiration = false;
            })
            .AddOpenIdConnect(options =>
            {
        
                options.ClientId = "xyapi";
               
                options.SignInScheme = Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme;
                options.RequireHttpsMetadata = false;
                options.GetClaimsFromUserInfoEndpoint = false;
                options.SaveTokens = true;

                // Use the authorization code flow.
                options.ResponseType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.CodeIdTokenToken;
                options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;

                // Note: setting the Authority allows the OIDC client middleware to automatically
                // retrieve the identity provider's configuration and spare you from setting
                // the different endpoints URIs or the token validation parameters explicitly.
                options.Authority = "https://localhost:44362/";
                options.SignedOutRedirectUri = "/signedout";
                //options.SignedOutCallbackPath = "/signout-oidc";
                options.CallbackPath = "/signin-oidc";
                
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                //options.Scope.Add("roles");

                options.SecurityTokenValidator = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler
                {
                    // Disable the built-in JWT claims mapping feature.
                    InboundClaimTypeMap = new Dictionary<string, string>()
                };
                options.ClaimActions.MapJsonKey(System.Security.Claims.ClaimTypes.Sid, "sid");
                options.TokenValidationParameters.NameClaimType = System.Security.Claims.ClaimTypes.Name;
            options.TokenValidationParameters.RoleClaimType = "role";
            var events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProviderForSignOut =  context =>
               {
                    var idToken = context.HttpContext.User.FindFirst("id_token");
                  

                   if (idToken != null)
                   {
                       context.ProtocolMessage.IdTokenHint = idToken.Value;
                   } else
                   {
                       var bearerAuth = context.Request.Headers["Authorization"].FirstOrDefault()?.StartsWith("Bearer ") ?? false;
                       if (bearerAuth)
                       {
                           context.ProtocolMessage.IdTokenHint = context.Request.Headers["Authorization"].FirstOrDefault().Substring(7);
                       }
                   }
                   return Task.CompletedTask;
               }
                };
                options.Events = events;
            })
 

Комментарии:

1. Пожалуйста, проясните вашу конкретную проблему или предоставьте дополнительные сведения, чтобы точно указать, что вам нужно. Поскольку это написано в настоящее время, трудно точно сказать, о чем вы просите.