从 ASP.NET MVC 客户端应用程序和 .NET 5 openiddict 服务器注销。注销后重定向 URL 无效

Posted

技术标签:

【中文标题】从 ASP.NET MVC 客户端应用程序和 .NET 5 openiddict 服务器注销。注销后重定向 URL 无效【英文标题】:Logout from ASP.NET MVC client app and a .NET 5 openiddict server. Post logout redirect url invalid 【发布时间】:2021-10-02 20:41:04 【问题描述】:

我将 OWIN 4.2 与 .NET Framework 4.7.2 一起用于我的 ASP.NET MVC 客户端应用程序。 登录完全正常,但注销会失败。

在我客户的 startup.cs 上

app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            
                ClientId = "MVC",
                ClientSecret = "MVC-Secret",

                Authority = "https://localhost:44305/",
                RedirectUri = "https://localhost:44347/",
                CallbackPath = new PathString("/"),
                
                Scope = "openid api",

                SignInAsAuthenticationType = "cookie",
                RequireHttpsMetadata = false,
                UseTokenLifetime = false,

                RedeemCode = true,
                SaveTokens = true,

                ResponseType = OpenIdConnectResponseType.Code,
                ResponseMode = OpenIdConnectResponseMode.Query,

                // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to the OnAuthenticationFailed method
                Notifications = new OpenIdConnectAuthenticationNotifications
                
                    AuthenticationFailed = OnAuthenticationFailed,

                    RedirectToIdentityProvider = n =>
                    
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        
                            // generate code verifier and code challenge
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);
                            
                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge = Base64Url.Encode(challengeBytes);
                            

                            // set code_challenge parameter on authorization request
                            n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
                            n.ProtocolMessage.SetParameter("code_challenge_method", "S256");

                            // remember code verifier in cookie (adapted from OWIN nonce cookie)
                            // see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L85
                            RememberCodeVerifier(n, codeVerifier);
                        

                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;

                            if (idTokenHint != null)
                            
                                n.ProtocolMessage.IdTokenHint = idTokenHint;
                            
                        

                        return Task.CompletedTask;
                    ,

                    AuthorizationCodeReceived = n =>
                    
                        // get code verifier from cookie
                        // see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L102
                        var codeVerifier = RetrieveCodeVerifier(n);

                        // attach code_verifier on token request
                        n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);

                        return Task.CompletedTask;
                    ,

                    SecurityTokenValidated = n =>
                    
                        var id = n.AuthenticationTicket.Identity;

                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        n.AuthenticationTicket = new AuthenticationTicket(
                               id,
                               n.AuthenticationTicket.Properties);
                        return Task.FromResult(0);
                    ,

                
            
        );

我也试过

...
                Authority = "https://localhost:44305/",
                RedirectUri = "https://localhost:44347/",
                PostLogoutRedirectUri = "https://localhost:44347/signout-callback-oidc",
...

还有

...
                Authority = "https://localhost:44305/",
                RedirectUri = "https://localhost:44347/",
                PostLogoutRedirectUri = "https://localhost:44347/",
...

但是,所有这些都会导致响应

错误:invalid_request error_description:指定的“post_logout_redirect_uri”无效。 error_uri:https://documentation.openiddict.com/errors/ID2052

在我的服务器上,配置如下

await manager.CreateAsync(new OpenIddictApplicationDescriptor
            
                ClientId = clientId,
                ClientSecret = clientSecret,
                DisplayName = displayName,
                RedirectUris =
                
                    new Uri("https://localhost:44347/")
                ,
                Permissions =
                
                    ...
                ,
                PostLogoutRedirectUris =
                
                    new Uri("https://localhost:44347/")
                

            , cancellationToken);
        

我也尝试将服务器配置更改为

PostLogoutRedirectUris =
                
                    new Uri("https://localhost:44347/signout-callback-oidc")
                

【问题讨论】:

您能否检查数据库中的条目是否与您设置的相符?配置存储在数据库中的 OpenIddictApplications 中 我已经检查了数据库,可以确认这些值已更新且正确。 你能分享你的服务器和客户端完整的startup's 吗?我必须做同样的一堆,但在 ASP.NET MVC 网站上无法弄清楚。顺便说一句,答案有帮助吗? 【参考方案1】:

我遇到了同样的问题,为我解决的方法是在应用程序中添加注销权限 - OpenIddictConstants.Permissions.Endpoints.Logout

await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor

    ClientId = "mvc",
    ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
    DisplayName = "MVC client application",
    PostLogoutRedirectUris =  new Uri("http://localhost:53507/signout-callback-oidc") ,
    RedirectUris =  new Uri("http://localhost:53507/signin-oidc") ,
    Permissions =
    
        OpenIddictConstants.Permissions.Endpoints.Authorization,
        OpenIddictConstants.Permissions.Endpoints.Logout,
        OpenIddictConstants.Permissions.Endpoints.Token,
        OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
    
);

【讨论】:

【参考方案2】:

正如应用程序在此处https://***.com/a/69671657/6477254 所回答的那样,我可以确认您必须允许注销端点的权限,使用常量值OpenIddictConstants.Permissions.Endpoints.Logout,在创建 OpenIddict 数据时,该值包含 "ept:logout" 字符串值。

【讨论】:

以上是关于从 ASP.NET MVC 客户端应用程序和 .NET 5 openiddict 服务器注销。注销后重定向 URL 无效的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ASP.net MVC 程序中获取纯 c# 程序中的 JSON 数据?

ASP.NET Core 2.1 MVC - 无法设置从 Web api 响应接收到的 cookie

传统ASP.NET开发和MVC的设计思想

在 .NET 中开发新的 RESTful Web 服务——我应该从哪里开始? ASP.NET-MVC,WCF?

asp.net mvc 生命周期

1.ASP.net MVC入门基础