1

I'm testing both server and client on my machine and I'm experiencing the following: I log in to the client fine, do some work, close the browser without logging out. Then I open the client again and I am still logged in (expected) but then a minute later I am auto logged out (NOT-expected).

I am using the oidc-client.js configured like this:

var mgr = new Oidc.UserManager({
    userStore: new Oidc.WebStorageStateStore({ store: window.localStorage }),
    authority: 'http://localhost:5000',
    client_id: 'TST_PORTAL',
    redirect_uri: window.location.origin + '/static/callback.html',
    response_type: 'code id_token token',
    scope: 'api47 openid profile read write offline_access active_dir email',
    post_logout_redirect_uri: window.location.origin + '/',
    silent_redirect_uri: window.location.origin + '/static/silent-renew.html',
    accessTokenExpiringNotificationTime: 10,
    automaticSilentRenew: true,
    filterProtocolClaims: true,
    loadUserInfo: true
})

After further investigation I see the client is calling /connect/checksession (returns status 200) to support single sign-out and then calls /connect/authorize?client_id... which fails (302 redirects to /home/error). The identity server logs say "no user present in authorize request" and "invalid grant type for client: implicit. I have hybrid and client_credentials configured. I read something here so I added this code to my IdentityServer startup:

services.ConfigureApplicationCookie(options =>
{
   options.Cookie.SameSite = SameSiteMode.None;
});

But this did not seem to help.

Thinking out loud, could this be a cross domain issue since these run on different ports or I don't have CORs correctly setup? I don't see cors errors. Also should the checksession GET request have parameters? I've been reading the spec and it talks about iframes but not the network traffic so I'm not sure what this traffic should look like.

Update:

The first page of my app is an anonymous auth landing page which checks if they are logged in. If so, it redirects them to the home page. The code for checking is this:

// Get signed in status without prompting to log in
getIsSignedIn() {
    console.log('Checking if signed in');
    return new Promise((resolve, reject) => {
        mgr.getUser().then(function (user) {
            if (user == null) {
                console.log('Not Signed In');
                return resolve(false)
            } else {
                if (user.expired) {
                   console.log('User expired');
                   return resolve(false)
                } else {
                    console.log('Signed In');
                    return resolve(true)
                }
            }
        }).catch(function (err) {
            console.log('Error when checking if signed in');
            return reject(false)
        });
    })
}

This seems to be returning true even when I open a fresh browser. I even changed the Oidc.WebStorageStateStore to use the default rather than localStorage.

CSharper
  • 53
  • 1
  • 9

1 Answers1

5

There are a lot of things, that could cause this behavior.

1) Single-signout (monitorSession: true) What does this do? -- After you login into your application (post redirect from IDP server, OIDC-Client JS will include the CheckSession endpoint in an iframe and OIDC library internally pings this iframe every 2 seconds (default) to verify that the idsrv.session cookie value matches with the value inside the applications id token, If they do not match, OIDC will raise user signed out event addUserSignedOut. It is up to your application, how you want to handle when this even get raised from OIDC. Just because you enable single sign out, unless application handles, it will not take the user back to login page.

2) Silent-Renew (automaticSilentRenew: true) When you have this flag enabled to true, you don't have control on when the silent renew is supposed to happen, by default, it happens before 1 min of access token expiration time. So if silentrenew fails, will raise silentrenew event addSilentRenewError. It is up to your application, how you want to handle when this even get raised from OIDC.

3) From what you are saying if you close the entire browser, and go to url application URL, Identity server cookies should be deleted, as they are session cookies. So, if you had handled single signout event, then OIDC will raise the signout event within 2 seconds after the application gets loaded. Since you are not seeing the login page, I assume that you might not have handled this event in your application.

4) When the silent renew happens (before 1 min of token exp time), This time your app will communicate to IDP server, but you'll not have session cookies as you closed the browser and you will get silentrenew error (probably this time, you might have seen the error you described) and You must have handled silentrenew error in this case and that is why you are seeing login screen. (Just a wild assumption based on ur input).

Hope this helps !!

hashbytes
  • 769
  • 1
  • 8
  • 26
  • Great ideas. Yes, we want #1 & 2 to happen. I will follow up on 3 & 4 and let you know – CSharper Feb 08 '19 at 13:46
  • Regarding #4 I am only logging to the console in the SilentRenewError event handler (and I don't see that message). Regarding #3 I updated my question. If my getIsSignedIn check is correct, then it should return false if I open the browser fresh, correct? Because if the session cookies were destroyed it should return false. – CSharper Feb 08 '19 at 15:09
  • 1
    The assumption about #3 is wrong, `getUser()` only looks for the values in the local storage and local storage won't be cleared automatically. When you close and re-open the browser, cookies will be deleted but local storage access token time will still be valid. Since these are session cookies, JS can't read those cookies. IMO, There is no way you can find out if the IDP session is valid or not, without enabling single sign out or redirecting the user to idp every time they load the app. – hashbytes Feb 08 '19 at 15:24
  • without seeing your auth service implementation, it is very hard for me to give you a solution and help you explain why this behavior is happening for your application. – hashbytes Feb 08 '19 at 15:30
  • My implementation is exactly like this one except for my added getIsSignedIn function in my update above: https://github.com/joaojosefilho/vuejsOidcClient/blob/master/src/services/SecurityService.js. I do have single sign-out enabled. – CSharper Feb 08 '19 at 15:38
  • Maybe my anonymous landing page needs to be on a different host html page than the authenticated SPA app then so I won't have to make this check. – CSharper Feb 08 '19 at 16:00