使用MVC Client 4.7.1和IdentityServer4进行身份验证

问题描述

我正在尝试在MVC 4.7.1客户端与ASP.NET Core 3.1 IdentityServer4和ASP.NET Identity服务之间集成用户身份验证。

我一直在按照本教程进行Cookie颁发的身份验证:Refreshing your Legacy ASP.NET IdentityServer Client Applications (with PKCE)

到目前为止,MVC客户端能够重定向到“登录页面登录后,以下功能出现空错误

private string RetrieveCodeVerifier(AuthorizationCodeReceivednotification n)
{
        string key = GetCodeVerifierKey(n.ProtocolMessage.State);

        string codeVerifierCookie = n.Options.CookieManager.GetRequestCookie(n.OwinContext,key);
        if (codeVerifierCookie != null)
        {
            var cookieOptions = new CookieOptions
            {
                SameSite = SameSiteMode.None,HttpOnly = true,Secure = n.Request.IsSecure
            };

            n.Options.CookieManager.DeleteCookie(n.OwinContext,key,cookieOptions);
        }

        string codeVerifier;
        var cookieProperties = n.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
        cookieProperties.Dictionary.TryGetValue("cv",out codeVerifier);

        return codeVerifier;
}

显然,codeVerifierCookie为空。

其余配置如下。

 app.UseCookieAuthentication(new CookieAuthenticationoptions
            {
                AuthenticationType = "cookie"
            });

            app.USEOpenIdConnectAuthentication(new OpenIdConnectAuthenticationoptions
            {
                ClientId = "mvc.owin",Authority = "https://localhost:44355",RedirectUri = "http://localhost:5001/Auth/",Scope = "openid profile scope1",SignInAsAuthenticationType = "cookie",RequireHttpsMetadata = false,UsetokenLifetime = false,RedeemCode = true,Savetokens = true,ClientSecret = "secret",ResponseType = "code",ResponseMode = "query",Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {
                            // set PKCE parameters
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);

                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            {
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge = Base64Url.Encode(challengeBytes);
                            }

                            n.ProtocolMessage.SetParameter("code_challenge",codeChallenge);
                            n.ProtocolMessage.SetParameter("code_challenge_method","S256");

                            // remember code_verifier (adapted from OWIN nonce cookie)
                            RememberCodeVerifier(n,codeVerifier);
                        }

                        return Task.CompletedTask;
                    },AuthorizationCodeReceived = n =>
                    {
                        // get code_verifier
                        var codeVerifier = RetrieveCodeVerifier(n);

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

                        return Task.CompletedTask;
                    }
                }
            });

在IdentityServer4 ConfigureServices上

 services.AddIdentity<ApplicationUser,IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.raiseerrorEvents = true;
                options.Events.Raise@R_433_4045@ionEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;

                // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
                options.EmitStaticAudienceClaim = true;
            })
                .AddInMemoryIdentityResources(Config.IdentityResources)
                .AddInMemoryApiScopes(Config.ApiScopes)
                .AddInMemoryClients(Config.Clients)
                .AddAspNetIdentity<ApplicationUser>();

最后,在IdentityServer4端配置Client.cs:

new Client
{
            ClientId = "mvc.owin",ClientName = "MVC Client",AllowedGrantTypes = GrantTypes.Code,ClientSecrets = {new Secret("secret".Sha256())},RedirectUris = {"http://localhost:5001/Auth/"},AllowedScopes = {"openid","profile","scope1"},AllowPlainTextPkce = false,RequirePkce = true,RequireConsent = false,// Token lifetimes
            AuthorizationCodeLifetime = 60,AccesstokenLifetime = 60,IdentityTokenLifetime = 60
}

AccountController,其余的几乎是基本的IdentityServer4.Template,特别是 is4aspid

  1. 有人尝试过同样的方法,知道失败了吗?
  2. 有没有办法用JWT代替Cookies?而且,缺点是什么?

编辑:显然,此配置适用于Firefox,并且我怀疑这与Chrome的Same-Site Cookie策略有关,因此在GetRequestCookie中为 null 。事实是,IdentityServer4在HTTPS上运行(否则,还有其他),而MVC客户端应用程序在HTTP上运行(注意:两者都在localhost上)。我尝试使用SameSite策略“无”,“宽松”,“严格”和“反之亦然”,但均未成功。我不确定还有什么尝试。

最好, mkanakis。

解决方法

断言SameSite=None的cookie也必须标记为“安全”,这意味着您需要使用https

了解更多here