okta / samples-js-vue

samples-js-vue
https://github.com/okta/samples-js-vue
Other
57 stars 63 forks source link

Okta Widget navigate to login page after being idle for long time #58

Closed sonphnt closed 3 years ago

sonphnt commented 4 years ago

Hi I just realized a bug like this. Using Okta widget samples, I can login successfully with my custom login and navigate to my Dashboard, then I stay there for many hours until my token get expired, then I select another route like "/myprofile" and the app automatically redirect me to Okta server login, not my custom login.

Is this a bug or I am missing something? Thanks

swiftone commented 4 years ago

@sonphnt - Thanks for the report. I'm able to recreate, so it does look like a bug. Investigating.

sonphnt commented 4 years ago

@swiftone I guess it is because of this line in router.beforeEach. if Vue.prototype.$auth.isAuthenticated(). And inside that isAuthenticated method, for some reason, this line will trigger and redirect to okta server login. But I am not sure. !!(await this.getAccessToken()) || !!(await this.getIdToken())

swiftone commented 4 years ago

Internal ref: OKTA-295146

sonphnt commented 4 years ago

Do we have any fixes for this?

swiftone commented 4 years ago

@sonphnt - No news to report as of yet, I have an item on my backlog to review what happens during long idle times.

vkmasters commented 4 years ago

Hi @swiftone ,

Please take this into consideration because same thing is also happened in my case.. I implemented your custom login page and what I see that after expiry of okta access token or with long idle time, it will automatically redirect to okta server login page instead of our custom login page and that shouldn't happen. Could you please have a look and provide a fix asap.

vkmasters commented 4 years ago

@swiftone, @vijetmahabaleshwar-okta any update on the progress ?

swiftone commented 4 years ago

TL;DR: A better solution is coming along, but isn't yet here.

Here's some background that might help you create a workaround, ending with some tips on how to create a workaround.

While these changes are tested and confirmed, workarounds can be made by using the 'onSessionExpired()` handler, where you can replace the default reaction to a token. being expired. This will still happen passively (i.e. the user has to take an action, which may be well after both the token and the SSO session have expired) but you can bounce the user to the location you require rather than relying on the default renew behavior. You might consider sending the user to /logout on the issuer, and configure the post_redirect_uri on Okta to be your apps /login page.

https://github.com/okta/okta-vue#configuration-options

MikeSpencer42 commented 4 years ago

@swiftone I'm also having this problem. Can you show an example of your recommended solution?

swiftone commented 4 years ago

I'll see if I can scrape together an example @MikeSpencer42 - it might not be today as I have a few other cases queued up, but I will take a stab at it.

MikeSpencer42 commented 4 years ago

@swiftone I added some code last night and left my app open. I think the following change worked, but I didn't have any logging or breakpoints in place 🤦. Here's what I've got:

router/index.js

import Auth from "@okta/okta-vue";

Vue.use(Auth, { ...authService.authConfig });

authService.js

import router from "@/router";

const authConfig = {
    \\ ... standard config properties omitted
    onSessionExpired: function() {
        router.push("/login");
    }
};

Do you know if there's a way to force a session expiration so I don't have to wait hours to test this again?

MikeSpencer42 commented 4 years ago

@swiftone It does appear that the workaround that I've posted is working. My only remaining concern at this point is whether the solution you proposed will be implemented before onSessionExpired is removed from the library (as it is already deprecated).

aarongranick-okta commented 4 years ago

@MikeSpencer42 onSessionExpired is being removed, but you can achieve the same effect by adding a subscriber to the "error" event from the TokenManager.

const tokenManager = Vue.prototype.$auth.getTokenManager();
tokenManager.on('error', err => {
  // handle token error
});

We strongly recommend against performing any asynchronous logic within event handlers. Also be aware that if tokens are set to expire at the same time, there may be more than one "error" event occurring in close succession, so you may want to throttle/debounce your logic. More details here: https://github.com/okta/okta-auth-js#tokenmanageronevent-callback-context

swiftone commented 4 years ago

@MikeSpencer42 -

Do you know if there's a way to force a session expiration so I don't have to wait hours to test this again?

(okta-vue instantiates and uses okta-auth-js internally)

You can combine these steps if you want to test the behavior that happens when a token expires and cannot be auto-renewed (really, auto-replaced) without waiting a long time.

MikeSpencer42 commented 4 years ago

@aarongranick-okta Thanks for the feedback. Where would you put the suggested code in the sample project? I tried stuffing it into the onAuthRequired function in the router. The code hit when I tried changing the route after my session expired, but the login page still redirected to the hosted version.

aarongranick-okta commented 4 years ago

@MikeSpencer42 We believe this issue has been fixed on our end. Can you try updating to the latest version of okta-vue ? Also if you have any code set for onSessionExpired, please remove it. We have deprecated this function and do not recommend using it.

MikeSpencer42 commented 4 years ago

@aarongranick-okta I just forced a session expiration (in a separate tab) and then tried navigating to another route. This resulted in a redirect to the login page, which is exactly what I want to happen. Thank you!

One last question: is there any way to detect this behavior so I can display a message to the user?

aarongranick-okta commented 3 years ago

@MikeSpencer42 I'm very happy that your issue was resolved.

As for your question about detecting when a user signs out, current versions of @okta/okta-auth-js support cross tab token synchronization. If you are using localStorage for token storage (the default), then the values will be synchronized between tabs. That means if an instance of your app in one tab signs out, another app instance can detect that the tokens have been removed by subscribing to the "removed" event on the token manager. https://github.com/okta/okta-auth-js#tokenmanageronevent-callback-context