I am using Microsoft OWIN library with the Webform App and my app faces timeout and redirects to ADFS around almost an hour. I already tried extending the app session through web.config
<SessionState timeout = 90 />
I also tried extending the owin session with SlidingExpiration set to true.
app.UseCookieAuthentication sets to SlidingExpiration=true but it wont extend. Now after trying multiple approaches i wrote my own CookieProvider class and want to confirm with the devs if its right. My startup file looks like this
public void ConfigureAuth(IAppBuilder app)
{
try
{
Util.Logger.Info("SSO additional logs: Entering the ActiveDirectory Startup file. \n");
OAuth2Service.Instance = new OAuth2ServiceImplementation();
GetSsoConfigValues();
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,
LoginPath = new PathString("/Pages/Login.aspx"),
CookieManager = new SystemWebChunkingCookieManager(),
CookieSameSite = Microsoft.Owin.SameSiteMode.None,
CookieName = "AspNet.Cookies." + Guid.NewGuid(),
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = context =>
{
context.Properties.AllowRefresh = true;
},
OnValidateIdentity = CustomOwinCookieProvider.OwinCookieCustomSlideExpiration
}
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = _clientId,
ClientSecret = _clientSecret,
//Authority = _authority,
MetadataAddress = _metaDataAddress,
RedirectUri = _redirectUri,
PostLogoutRedirectUri = _redirectUri,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Scope = OpenIdConnectScope.OpenIdProfile,
TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" },
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
string userName = n.AuthenticationTicket.Identity.Claims.ToList()?.FirstOrDefault(x => x.Type.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", StringComparison.OrdinalIgnoreCase))?.Value;
Util.Logger.Info("SSO additional logs: AuthorizationCodeReceived for the username: " + userName + "\n");
IEnumerable<Claim> claimsTobeProcessed = n.AuthenticationTicket.Identity.Claims;
Util.Logger.Info("SSO additional logs: Exiting AuthorizationCodeReceived event");
OAuth2Service.Instance.ProcessSso(userName, claimsTobeProcessed, n.JwtSecurityToken);
},
AuthenticationFailed = async n =>
{
Util.Logger.Info("SSO additional logs: Entering in AuthenticationFailed event");
Util.HandleException(new Exception(message: n.Exception.Message, n.Exception), Framework.General.Severity.SsoError);
// Specific sporadic error which requires cache clean up
if (n.Exception.Message.Contains("IDX21323"))
{
OAuth2Service.Instance.LogoutPageRedirect(SingleSignOnAuthenticationState.CacheIssue,null);
}
else
{
OAuth2Service.Instance.LogoutPageRedirect(SingleSignOnAuthenticationState.SsoSystemFailure, null);
}
await Task.FromResult(true);
}
},
});
}
catch(Exception ex)
{
if (ex is ThreadAbortException)
{
return;
}
Util.HandleException(ex, Framework.General.Severity.SsoError);
OAuth2Service.Instance.LogoutPageRedirect(Framework.Plugins.SingleSignOn.SingleSignOnAuthenticationState.SsoSystemFailure, null);
}
}
public static class CustomOwinCookieProvider
{
public static Task OwinCookieCustomSlideExpiration(CookieValidateIdentityContext ctx)
{
Util.Logger.Debug("********START OwinCookieCustomSlideExpiration********");
try
{
var expireUtc = ctx.Properties.ExpiresUtc.Value;
var issuedUtc = ctx.Properties.IssuedUtc.Value;
var diff = expireUtc-issuedUtc;
var halfTimeInMins = diff.TotalMinutes / 2;
Util.Logger.Debug("maxOwinCookieTimeinMins: " + diff.TotalMinutes.ToString());
var issuedTime = issuedUtc;
long halftimeTicks = issuedTime.AddMinutes(halfTimeInMins).Ticks;
long currentUtcTicks = DateTimeOffset.UtcNow.Ticks;
var timeElapsedSinceTokenIssued = DateTimeOffset.UtcNow.Subtract(issuedTime);
if(timeElapsedSinceTokenIssued.TotalMinutes >= 0)
{
Util.Logger.Debug("timeElapsedSinceCookieIssuedinMins: " + timeElapsedSinceTokenIssued.TotalMinutes.ToString() + "\n");
}
if (currentUtcTicks > expireUtc.Ticks)
{
Util.Logger.Debug("OwinCookie is expired. Redirecting to IDP... \n");
ctx.OwinContext.Authentication.SignOut(ctx.Options.AuthenticationType);
ctx.RejectIdentity();
return Task.FromResult(0);
}
var timeLeftBeforeCookieRenewal = halfTimeInMins - timeElapsedSinceTokenIssued.TotalMinutes;
if(timeLeftBeforeCookieRenewal >= 0)
{
Util.Logger.Debug("timeLeftBeforeCookieRenewalinMins: " + timeLeftBeforeCookieRenewal.ToString() + "\n");
}
if (currentUtcTicks >= halftimeTicks)
{
Util.Logger.Debug("OwinCookie passed the halftime mark. Extendng the cookie expiry for " + diff.TotalMinutes.ToString() + " mins.\n");
var identity = ctx.Identity;
var authTicket = new AuthenticationProperties() { //IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMinutes(diff.TotalMinutes),
IssuedUtc = DateTime.UtcNow };
HttpContext.Current.GetOwinContext().Authentication.SignIn(authTicket, identity);
}
}
catch(Exception ex)
{
var exception = new Exception("Error occurred in CustomOwinCookieProvider.OwinCookieCustomSlideExpiration ", ex);
Util.HandleException(exception, Framework.General.Severity.SsoError);
}
Util.Logger.Debug("********END OwinCookieCustomSlideExpiration********");
return Task.FromResult(0);
}
}
I am expecting devs to verify my ValidateIdentity on cookie approach and let me know if it is right thing to do with the Microsoft OWIN.