0

i am using Microsoft.Owin.Security.OpenIdConnect v3.1.0.0 and implemented samesite=strict to one of the cookie but getting below exception

IDX10311: RequireNonce is 'true' (default) but validationContext.Nonce is null. A nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator

after making the samesite=none or removing the samesite is working fine. I have below code

cookiemanager.cs

public static void SetCookies(HttpContextBase context)
    {
        var request = context.Request;
        var response = context.Response;

        var holder = CookieManagerModule.AddCurrentValuesToContext(context, false);
        if (holder == null)
        {
            return;
        }

        var names = holder.AllKeys;
        var values = new string[names.Length];
        holder.CopyTo(values, 0);

        var allData = CookieManagerModule.Encode(SystemServices.ArrayEncode(new string[] { SystemServices.ArrayEncode(names), SystemServices.ArrayEncode(values) }));

        for (var i = 0; i < CookieManagerModule.MaxCookieSpan; i++)
        {
            var name = CookieManagerModule.NamePrefix + i.ToString();

            if ((i * CookieManagerModule.MaxDataLength) < allData.Length)
            {
                var data = allData.Substring(
                    (i * CookieManagerModule.MaxDataLength),
                    Math.Min((i + 1) * CookieManagerModule.MaxDataLength, allData.Length) - (i * CookieManagerModule.MaxDataLength)
                    );

                response.Cookies.Remove(name);
                string currentUserAgent = HttpContext.Current.Request.UserAgent;
                

                var cookie = new HttpCookie(name, data)
                {
                    Path = "/",
                    HttpOnly = true,
                    SameSite = SameSiteMode.Strict,
                    Secure = true
                };
                response.Cookies.Add(cookie);
            }
            else if (Array.IndexOf(request.Cookies.AllKeys, name) >= 0)
            {
                response.Cookies.Remove(name);

                // add an expired cookie
                var cookie = new HttpCookie(name, String.Empty)
                {
                    Path = "/",
                    HttpOnly = true,
                    SameSite = SameSiteMode.Strict,
                    Secure = true,
                    Expires = CookieManagerModule.CookieExpiration                      
                };
                response.Cookies.Add(cookie);
            }
        }

and in my startup.cs

private void ConfigureOpenIdConnect(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(OpenIdConnectAuthenticationContext.AuthenticationType);

        string applicationBaseUrl = PortalApplication.SSOConfiguration.ApplicationBaseUrl;

        if (!applicationBaseUrl.EndsWith("/"))
        {
            applicationBaseUrl = applicationBaseUrl + "/";
        }

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            ClientId = PortalApplication.SSOConfiguration.OpenIdSettings.OidcClientId,
            ClientSecret = PortalApplication.SSOConfiguration.OpenIdSettings.OidcClientSecret,
            RedirectUri = applicationBaseUrl + SSOResponse.Path,
            MetadataAddress = PortalApplication.SSOConfiguration.OpenIdSettings.OidcMetadataAddressUrl,
            CookieManager = new PortalCookieManager(),
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
            PostLogoutRedirectUri = applicationBaseUrl + "./SSOLogoutComplete.aspx",
            
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = true,
                ValidateIssuer = true
            },

            Notifications = new OpenIdConnectAuthenticationNotifications
            {                   
                SecurityTokenValidated = async (notification) =>
                {
                    IOwinContext context = notification.OwinContext;
                    ClaimsIdentity claimsIdentity = notification.AuthenticationTicket.Identity;
                    Claim identityClaim = claimsIdentity.FindFirst(PortalApplication.SSOConfiguration.NameClaimType);

                    SSOCredential credential = SSOCredential.CreateFromAuthenticatedIdentity(identityClaim != null ? identityClaim.Value : claimsIdentity.Name, claimsIdentity.IsAuthenticated);
                    var identity = new ExternalIdentity(PortalHttpApplication.Host, credential);

                    if (identity != null)
                    {
                        AuthenticationException ex;

                        string oidcToken = notification.ProtocolMessage.IdToken;

                        if (Authentication.TryAuthenticate(identity, out ex))
                        {
                            PortalHttpApplication.WriteTrace(
                                this,
                                PortalTraces.Authentication,
                                DiagnosticSeverityLevel.Informational,
                                APISoftware.Culture.Customer.FormatString("SignIn (SSO) {0}", identity.Name));

                            DateTimeOffset? expiry = notification.AuthenticationTicket.Properties.ExpiresUtc;

                            if (PortalApplication.SSOConfiguration.TimeoutOverride.HasValue)
                            {
                                expiry = DateTime.UtcNow.AddMinutes(PortalApplication.SSOConfiguration
                                    .TimeoutOverride.Value.TotalMinutes);
                            }

                            if (expiry != null)
                            {
                                var configuration = notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled).Result;
                                string domainHint = null;
                                notification.AuthenticationTicket.Properties.Dictionary.TryGetValue(OpenIdConnectAuthenticationContext.DomainHintKey, out domainHint);

                                var authenticationContext = new OpenIdConnectAuthenticationContext(
                                    configuration.TokenEndpoint,
                                    notification.Options.ClientId,
                                    notification.Options.ClientSecret,
                                    notification.Options.RedirectUri,
                                    domainHint,
                                    notification.ProtocolMessage.IdToken);

                                await authenticationContext.GetRefreshTokenAsync(notification.ProtocolMessage.Code);
                                Authentication.SetUser(identity, expiry.Value.UtcDateTime, authenticationContext.SerializeToToken());

                                ISystemPrincipal systemPrincipal = new SystemPrincipal(identity);
                                HttpContext.Current.User = systemPrincipal;
                                Thread.CurrentPrincipal = systemPrincipal;

                                return;
                            }
                        }

                        PortalHttpApplication.WriteAlert(this, new Exception(APISoftware.Culture.Customer.FormatString("Failed attempt to Sign-In (SSO) {0}", identity.Name), ex));

                        if (!String.IsNullOrWhiteSpace(oidcToken))
                        {
                            OpenIdConnectAuthenticationContext.Logout(notification.ProtocolMessage.IdToken, "SSOError.aspx?errorCode=403", context);
                        }
                    }
                },
                AuthenticationFailed = (notification) =>
                {
                    PortalHttpApplication.WriteAlert(
                        this,
                        new Exception("Failed attempt to SignIn (SSO)", notification.Exception));

                    Authentication.SignOut();
                    notification.Response.Redirect(SSOError.Path + "?errorCode=401");
                    return Task.FromResult(0);
                },

                RedirectToIdentityProvider = (notification) =>
                {
                    if (notification.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
                    {
                        string idTokenHint = String.Empty;

                        notification.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary.TryGetValue(
                            OpenIdConnectAuthenticationContext.IdTokenHintKey,
                            out idTokenHint);

                        if (idTokenHint != null)
                        {
                            notification.ProtocolMessage.IdTokenHint = idTokenHint;
                        }
                    }

                    IDictionary<string, string> propertiesDictionary = null;

                    if (notification.OwinContext.Authentication.AuthenticationResponseChallenge != null
                        && notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties != null)
                    {
                        propertiesDictionary = notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary;
                    }
                    else if (notification.OwinContext.Authentication.AuthenticationResponseRevoke != null
                        && notification.OwinContext.Authentication.AuthenticationResponseRevoke.Properties != null)
                    {
                        propertiesDictionary = notification.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary;
                    }

                    if (propertiesDictionary != null && propertiesDictionary.ContainsKey(OpenIdConnectAuthenticationContext.DomainHintKey))
                    {
                        notification.ProtocolMessage.DomainHint = propertiesDictionary[OpenIdConnectAuthenticationContext.DomainHintKey];
                    }

                    return Task.FromResult(0);
                },
            },
        });
    }

i have been asked to implement the samesite=strict with oidc sso login but not getting success to make it work.

James Z
  • 12,209
  • 10
  • 24
  • 44
Manish Gupta
  • 61
  • 3
  • 14

0 Answers0