Open fetters5 opened 4 years ago
Bumping this as we are seeing the same issue and are on 4.1.0, we did not see this issue on version 3.0.1. Any help would be appreciated
Catching up on this issue (thanks for the bump) -
@fetters5 -
can I have an access token with a lifetime of say 2 hours, that can be refreshed for up to say 7 days with the pkce method or does it rely on the lifetime of the okta session
It relies on the lifetime of the okta session to do renewals. Okta has just released one-time refresh tokens for SPAs, which will allow you to do renewals without relying on the okta session, speak to our support team (developers@okta.com) if you are interested in trying that feature in our Early Access program. ( https://help.okta.com/en/prod/Content/Topics/ReleaseNotes/early-access.htm ).
PKCE has no connection to the lifetime of a renewal, it is simply used to ensure that the recipient of the token is the same application that requested them.
@fetters5 and @Salinn -
A full page redirect should not be required to renew tokens, particularly in recent versions of our libraries. I'm happy to work to figure out what is going wrong, but the only code sample above is for a previous major version of the library. Can someone share a simple reproduction case?
@swiftone tried reproducing this in a simple CRA and think it might actually be due to a useEffect that we were dependent on. Will respond back to this thread if the useEffect is not the problem.
@swiftone after getting some more time to investigate I have figured out what is causing the issue for our team, it was due to us passing the component the function that returned a component to the component prop instead of the render prop. Once I switched that it worked as expected. Added an example in case anyone runs into this same issue.
TLDR: passing a function to the component to render on the secure route is what is causing the issue.
function App() {
const { userDispatch } = useUserState();
useGetUser({ types, dispatch: userDispatch });
return (
<Switch>
<SecureRoute
path="/"
exact
component={() => ComponentWithHeaderFooter(Home)}
/>
<Route path="/implicit/callback" component={LoginCallback} />
</Switch>
);
}
const ComponentWithHeaderFooter = (Component) => {
return (
<UserAuthenticationCheck>
<Header />
<main role="main" className="container">
<Component />
</main>
<Footer />
</UserAuthenticationCheck>
);
};
function App() {
const { userDispatch } = useUserState();
useGetUser({ types, dispatch: userDispatch });
return (
<Switch>
<SecureRoute
path="/"
exact
render={() => ComponentWithHeaderFooter(Home)}
/>
<Route path="/implicit/callback" component={LoginCallback} />
</Switch>
);
}
@Salinn - thanks for reporting back! Glad you're working.
That's interesting - <SecureRoute>
is just a thin layer around <Route>
, so it accepts render/component/children, but we may want to do some checking/reporting if it turns out using component
(or not using render
) is always a bad idea.
@swiftone please report back if you did that as I would be interested in those results. I found an easy way to reproduce and check this was with adding a counter that incremented on the home page for each render and watched it keep resetting to 0 with the componet={()=>....} and worked perfectly with children or render
I am currently using @okta/okta-react v4.0.1
and found a similar behavior where the auto-renew token, refreshes the whole page.
Though, this behavior is only observed while using private browsing or incognito mode in browser. In normal mode, the token refresh happens silently.
Does anyone else faced similar issue?
@Salinn I tried your above approach and still no luck. Im using okta-react:3.0.0 & okta-signin-widget:3.9.0. Any help/suggestion?
const HasAccessToRouter = (securityConfig) => {
const history = useHistory(); // example from react-router
const [localSecurityConfig] = useState(securityConfig.securityConfig.config);
const customAuthHandler = () => {
history.push('/login');
};
return (
<Security
{...localSecurityConfig}
onAuthRequired={customAuthHandler}>
<div className="container-full-bg">
<SecureRoute path="/" exact component={Home} />
<Route path='/implicit/callback' component={LoginCallback} />
{/* <Route path="/login" component={LoginPage} /> */}
<Route path='/login' render={(props) => (<LoginPage {...props} oktaConfig={securityConfig.securityConfig.config} />)}/>
</div>
</Security>
);
};
const App = (config) => {
return(
<div>
<Router>
<HasAccessToRouter securityConfig={config} />
</Router>
</div>);
};
@swiftone any thoughts on the above observation?
@amit70 - I'm no longer at Okta, so I can't give any insights from the SDK team there anymore, but per the suggestion above, have you tried replacing
<SecureRoute path="/" exact component={Home} />
with
<SecureRoute path="/" exact render={ () => <Home/> } />
?
@swiftone Thanks for your response. I tried and still no luck. Also I have updated the okta plugins to latest.
"@okta/okta-react": "^5.1.2" "@okta/okta-signin-widget": "^5.6.3"
Any OKTA SDK team member can provide help/suggestion?
I am currently using
@okta/okta-react v4.0.1
and found a similar behavior where the auto-renew token, refreshes the whole page. Though, this behavior is only observed while using private browsing or incognito mode in browser. In normal mode, the token refresh happens silently. Does anyone else faced similar issue?
I tried upgrading the okta to v4.0.1 and okta-auth-js to v4.0.0, still facing the issue. Any lead?
@ey52fpv ,what I observed was- in case of incognito mode, if you allow third-party cookies (in Chrome, there is an "eye" on right side of address bar), the thing is solved. It Seems by allowing that, okta-sdk can use previous set cookies and does not treat it as a fresh session.
@rohit-khanna Thank you for your response. Right now Im facing the issue in the normal browser session. As a workaround, I degraded to okta-react: 3.0.0 and okta-sign-widget: 3.9.0 and the app seems not to refresh when it tries to get a token.
I had the same issue. I found out two different issues that caused this. As mentioned above by @Salinn one should not write
component={() => <Component />}
but instead:
render={() => <Component />}
This is actually mentioned in the docs for react-router, here:
When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below). see react-router docs here
I am not sure but I can not see any upsides in using the component prop instead of the render prop if the intention is to use a function within, so just changing to render
should be fine.
The above solves the issue when parts of the SPA is re-rendering. There are also cases when the complete page is reloaded. The cause of this is that third party cookies are disallowed in the browser. I got around this issue by enabling these cookies on the site (for firefox see here) but that is not a real end user solution to the problem.
Is there any solution to make it work with third party cookies disabled as well?
@alfredvaa I recommend upgrading to the latest @okta/okta-auth-js
and @okta/react
, the versions listed in this thread are out-of-date.
Routing samples: https://github.com/okta/okta-react/tree/master/samples/routing
Third Party Cookie Guidance: https://support.okta.com/help/s/article/FAQ-How-Blocking-Third-Party-Cookies-Can-Potentially-Impact-Your-Okta-Environment?language=en_US
For the life of me I dont know how to change it so that the octa react package can switch to using iframes when renewing tokens. The current way the tokens are renewed it redirects to the okta server and then back causing a full page reload, is there a way to override this? Currently I pass the following service to the Security component AuthService
App.tsx
Also I am a little unsure can I have an access token with a lifetime of say 2 hours, that can be refreshed for up to say 7 days with the pkce method or does it rely on the lifetime of the okta session?