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.