{"id":3463,"date":"2016-07-25T00:47:17","date_gmt":"2016-07-25T07:47:17","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=3463"},"modified":"2016-09-11T23:54:26","modified_gmt":"2016-09-12T06:54:26","slug":"controlling-a-web-apps-session-duration-2","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2016\/07\/25\/controlling-a-web-apps-session-duration-2\/","title":{"rendered":"Controlling a Web App&rsquo;s session duration"},"content":{"rendered":"<p>When you use the OpenId Connect (OIDC) or the WS-Federation middleware (MW) in an ASP.NET app, a successful authentication (eg, a transaction resulting in your app receiving a valid user token) results in the production of a session cookie \u2013 courtesy of the cookie middleware. As long as the session cookie sticks around and is valid, the app considers the user authenticated.<\/p>\n<p>By default, in ASP.NET 4.6 the amount of time for which this session is matches the validity timeframe of the token that prompted the generation of the session in the first place. Say that you are using the OIDC MW with Azure AD: the id_token received by the app during the user authentication transaction will last one hour, hence the session cookie for your app will also last 1 hour. Somewhat counter-intuitively, this behavior will be enforced regardless of session-modifying settings (such as a specific duration) you add to the cookie MW options. However, it is safe to say that you will often want your app to have sessions that last more that one hour, or whatever duration the original token carries. True, by default the cookie MW provides sliding sessions\u2026 but users don\u2019t necessarily stay active all the time. Certain web apps stay quiet in a tab all day, and are used only at sparse times \u2013 but with inactivity, the session times out so every tab switch becomes a new auth gesture. Not fun.<\/p>\n<p>There are at least a couple of ways you can extend the duration of your session. One is quick and somewhat dirty; the other is more\u2026 thoughtful, and safer: but it also requires a bit more code. Let\u2019s take a look.<\/p>\n<h3>Decouple the session duration from the token validity<\/h3>\n<p>The easiest way out of this is to decouple the session duration from the expiration times carried by the original token. That is super easy: you just tell the OIDC MW to stop controlling this aspect in the cookie MW, by passing the following option:<\/p>\n<div id=\"codeSnippetWrapper\" style=\"font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4\">\n<div id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\">\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum1\" style=\"color: #606060\">   1:<\/span> app.UseOpenIdConnectAuthentication(<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum2\" style=\"color: #606060\">   2:<\/span>     <span style=\"color: #0000ff\">new<\/span> OpenIdConnectAuthenticationOptions {<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum3\" style=\"color: #606060\">   3:<\/span>      ... <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum4\" style=\"color: #606060\">   4:<\/span>     UseTokenLifetime = <span style=\"color: #0000ff\">false<\/span>, <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum5\" style=\"color: #606060\">   5:<\/span>     }<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum6\" style=\"color: #606060\">   6:<\/span> ); <\/pre>\n<p><!--CRLF--><\/div>\n<\/div>\n<p>As simple as that. With <span style=\"font-family: 'Courier New'\">UseTokenLifetime<\/span> set to <span style=\"font-family: 'Courier New'\">false<\/span>, the cookie MW will now honor whatever settings you add in the cookie MW options.<\/p>\n<p>The challenge with that approach is that now the app session is entirely decoupled from the session the user has with Azure AD (or whatever IdP you are working with). That\u2019s dangerous: your app session might outlive the IdP session, which might have been terminated for good reasons (admins find out the user was compromised; lost device scenarios; and so on).<\/p>\n<h3>Set up session renewing logic<\/h3>\n<p>The ideal would be to ensure that our app\u2019s session lasts as long as the IdP session, or at least approximate it. Note: the duration of the IdP session is NOT the duration of the id_token obtained when the user authenticated to your app. When your user was bounced to the Azure AD pages, he\/she went through an authentication ceremony which ended up with two artifacts:the id_token your app requested AND a session cookie bound to the Azure AD domain. That cookie is what makes possible for the user to avoid entering credentials if he\/she ends up needing in short order another token from Azure AD. The validity timeframe of that cookie is the validity timeframe of the IdP session. How can we latch to that session and ensure that our own web app\u2019 session follows it?<\/p>\n<p>If you ever worked with <a href=\"https:\/\/www.cloudidentity.com\/blog\/2015\/02\/19\/introducing-adal-js-v1\/\">ADAL JS<\/a>, you know that it uses a neat trick (explained <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/10\/28\/adal-javascript-and-angularjs-deep-dive\/\">here<\/a>) to renew the tokens it needs for the JS frontend to access its API backend. The idea is that ADAL JS injects in the web app a hidden iframe, and uses that iframe to silently request new tokens to Azure AD. Given that the hidden frame points to the Azure AD domain, as long as there is a valid cookie for Azure AD maintaining a user session, requests for new tokens will not require the user to reenter credentials \u2013 and will obtain new tokens silently.<\/p>\n<p>That works for the SPA application architecture, where the web app \u201csession\u201d is really carried by the tokens attached to every web API call. In the case of apps protected by OIDC and cookie MWs, the session is really the cookie issued by the web app itself. Could we tweak the trick we use in ADAL JS to keep getting fresh session cookies from the web app as long as the Azure AD session is valid? Yes we can! Here there\u2019s a way to do it:<\/p>\n<p>1. add to the web app a route that will <em>always<\/em> result in a new authorization request, regardless of whether the user is already signed in or not<\/p>\n<p>2. add a hidden iframe in the web app, which hits the new \u201cforced\u201d sign in route at regular time intervals<\/p>\n<p>\u2026and that\u2019s all there is to it.<\/p>\n<p>The point #1 is only necessary because I am assuming you are using the ASP.NET project templates or our github samples for OIDC web apps &#8211; in the regular app templates and samples the <span style=\"font-family: 'Courier New'\">SignIn<\/span> route only triggers the <span style=\"font-family: 'Courier New'\">Challenge<\/span> if the user isn\u2019t signed in yet. In fact, all you need to do is to go in the <span style=\"font-family: 'Courier New'\">Account<\/span> controller, duplicate the <span style=\"font-family: 'Courier New'\">SignIn<\/span> method, rename it <span style=\"font-family: 'Courier New'\">ForcedSignIn<\/span> or equivalent, and get rid of the if:<\/p>\n<div id=\"codeSnippetWrapper\" style=\"font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4\">\n<div id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\">\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum1\" style=\"color: #606060\">   1:<\/span> <span style=\"color: #0000ff\">public<\/span> <span style=\"color: #0000ff\">void<\/span> ForcedSignIn() <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum2\" style=\"color: #606060\">   2:<\/span> {<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum3\" style=\"color: #606060\">   3:<\/span>    <span style=\"color: #008000\">\/\/ Send an OpenID Connect sign-in request. <\/span><\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum4\" style=\"color: #606060\">   4:<\/span>    HttpContext.GetOwinContext().Authentication.Challenge(<span style=\"color: #0000ff\">new<\/span> AuthenticationProperties { RedirectUri = <span style=\"color: #006080\">\"\/\"<\/span> }, <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum5\" style=\"color: #606060\">   5:<\/span>                                                        OpenIdConnectAuthenticationDefaults.AuthenticationType); <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum6\" style=\"color: #606060\">   6:<\/span> }<\/pre>\n<p><!--CRLF--><\/div>\n<\/div>\n<p>That done, all you need to do is to inject an iframe in the app pages that will periodically hit the new route. For example, you can add the below right in \u2013Layout.cshtml, in the body (right after all the &lt;div&gt;s).<\/p>\n<div id=\"codeSnippetWrapper\" style=\"font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4\">\n<div id=\"codeSnippet\" style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\">\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum1\" style=\"color: #606060\">   1:<\/span> &lt;iframe id=<span style=\"color: #006080\">\"renewSession\"<\/span> hidden&gt;&lt;\/iframe&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum2\" style=\"color: #606060\">   2:<\/span> &lt;script&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum3\" style=\"color: #606060\">   3:<\/span>     setInterval( <span style=\"color: #0000ff\">function<\/span> () <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum4\" style=\"color: #606060\">   4:<\/span>         { <span style=\"color: #cc6633\">@if<\/span> (Request.IsAuthenticated) {<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum5\" style=\"color: #606060\">   5:<\/span>                 &lt;text&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum6\" style=\"color: #606060\">   6:<\/span>                 <span style=\"color: #0000ff\">var<\/span> renewUrl = <span style=\"color: #006080\">\"\/Account\/ForcedSignIn\"<\/span>; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum7\" style=\"color: #606060\">   7:<\/span>                 <span style=\"color: #0000ff\">var<\/span> element = document.getElementById(<span style=\"color: #006080\">\"renewSession\"<\/span>); <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum8\" style=\"color: #606060\">   8:<\/span>                 console.log(<span style=\"color: #006080\">\"sending request to: \"<\/span> + renewUrl); <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum9\" style=\"color: #606060\">   9:<\/span>                 element.src = renewUrl; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum10\" style=\"color: #606060\">  10:<\/span>                 &lt;\/text&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum11\" style=\"color: #606060\">  11:<\/span>             } <span style=\"color: #0000ff\">else<\/span> { <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum12\" style=\"color: #606060\">  12:<\/span>                 &lt;text&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum13\" style=\"color: #606060\">  13:<\/span>                 console.log(<span style=\"color: #006080\">\"No renewal attempt without a valid session\"<\/span>); <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum14\" style=\"color: #606060\">  14:<\/span>                 &lt;\/text&gt; <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum15\" style=\"color: #606060\">  15:<\/span>                     } <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum16\" style=\"color: #606060\">  16:<\/span>         }, <\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum17\" style=\"color: #606060\">  17:<\/span>         1000*60*45<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4\"><span id=\"lnum18\" style=\"color: #606060\">  18:<\/span>     );<\/pre>\n<p><!--CRLF--><\/p>\n<pre style=\"border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white\"><span id=\"lnum19\" style=\"color: #606060\">  19:<\/span> &lt;\/script&gt;<\/pre>\n<p><!--CRLF--><\/div>\n<\/div>\n<p>It\u2019s that simple! With that JS in place, the app will trigger a new sign in, completely transparently, every 45 minutes. Note that this will happen only if the current web app session is still valid. If there is a valid Azure AD session, the app will successfully drive a new authentication dance that will result in a new cookie; otherwise \u2013 no harm done.<\/p>\n<p>I made a little test just to be sure. I created two apps, one with the session refresh trick and one without. I deployed both to their own azure websites. I opened Chrome and signed in in both apps, from 2 different tabs, at 10:12pm. Then I selected the tab with the app without session trick, and started watching Mockingjay part II (don\u2019t judge me. Also, meh).<br \/>At 23:20 I went back to Chrome, selected the tab with the app with the session trick, and clicked on About. I got access right away \u2013 sign that the session was still valid.<br \/>I switched to the tab with the app with no session trick. I clicked about, and sure enough I got redirected to Azure AD before gaining access \u2013 sign that the session expired as usual. Fiddler:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2016\/07\/clip_image002.jpg\"><img loading=\"lazy\" decoding=\"async\" title=\"clip_image002\" style=\"border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px\" border=\"0\" alt=\"clip_image002\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2016\/07\/clip_image002_thumb.jpg\" width=\"1442\" height=\"322\"><\/a><\/p>\n<p>This is all pretty neat, isn\u2019t it. I already know that some of you like to sprinkle just a bit of AJAX in their MVC apps, and this trick allows you to also secure web API with the OIDC and cookie MW instead of switching to the more appropriate OAuth2 bearer. Not that I approve \u2013 tokens are better than cookies \u2013 but I understand that for apps that are mostly MVC adding a whole JS subsystem might be impractical.<\/p>\n<p>The approach isn\u2019t completely issues-free, though. For example: the Azure AD session is <em>itself <\/em>a sliding session. Which means that this trick will generate traffic and keep the Azure AD session alive where user inactivity could have eventually lead to that session expiring. But, as long as you know what you are doing, it\u2019s an extra trick in your bag <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2016\/07\/wlEmoticon-smile.png\"><\/p>\n<p>Happy coding!<\/p>\n<p>V.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you use the OpenId Connect (OIDC) or the WS-Federation middleware (MW) in an ASP.NET app, a successful authentication (eg, a transaction resulting in your app receiving a valid user token) results in the production of a session cookie \u2013 courtesy of the cookie middleware. As long as the session cookie sticks around&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3463","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3463","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=3463"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3463\/revisions"}],"predecessor-version":[{"id":3469,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3463\/revisions\/3469"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/3459"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=3463"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=3463"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=3463"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}