Authentication with MVC Client 4.7.1 and IdentityServer4

I am trying to integrate user authentication between an MVC 4.7.1 client and an ASP.NET Core 3.1 IdentityServer4 & ASP.NET Identity service.

I have been following this tutorial for cookie issued authentication: Refreshing your Legacy ASP.NET IdentityServer Client Applications (with PKCE)

So far, the MVC client is able to redirect to the Login page. Upon logging in, I have a null error in the following function:

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;
}

Apparently the codeVerifierCookie is null.

The rest of the configuration is as follows.

 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;
                    }
                }
            });

And on IdentityServer4 ConfigureServices:
 services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = 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>();

Finally, Client.cs configuration on IdentityServer4 side:
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 and the rest is pretty much the basic IdentityServer4.Template, specifically is4aspid.
  1. Anyone tried the same and knows what fails?
  2. Is there a way to do it with JWT instead of Cookies? And, what are the drawbacks?

Edit: Apparently, this configuration works with Firefox, and I am suspecting this is a problem with Chrome’s Same-Site cookie policy, hence the null in GetRequestCookie. The thing is, IdentityServer4 is running on HTTPS (otherwise, there are others) while the MVC client app is running on HTTP (note: both on localhost). I have tried using SameSite policy None, Lax, Strict and vise-versa with no success. I am not sure what else to try.

Best,
mkanakis.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Cookies that assert SameSite=None must also be marked as Secure, this means you need to use https

Read more here


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x