1 comment

  • Yael Schwartz

    In case someone comes across this post, I'll share what approaches we tried and which one actually worked for us:

    Refresh on invalid token authorization error

    The idea: Use the `responseInterceptor` to identify a failing request with the appropriate header, issue a refresh token call and retry the previous request. 

    We quickly learned that this appraoch doesn't work both because the parameter passed into the interceptor function is only the error object without the response header that indicates that the token expired but more importantly because the components don't have the notion of retry, so once we refresh the token we must rerender the components and lose the state the user was in

    Check expiratoin and refresh before issuing requests

    The idea: sand the `expires_in` field we get when generating a token to the client, and in the client compute annd save the expiration time. Now, since the `token` prop of the Box components can recieve a token generation function (see here), we can send a function that checks if the expiration time passed, if it did, call the api to get a new token and return the fresh one to the component.

    This solution worked will for the ContentPicker component but showed bad performance in the ContentExplorer. The reason was that on each row selection, the ContentExplorer generates a thumbnail url for all files rendered currently on the screen, and each of these thumbnails are calling the token generation function in parallel. This made the component issue ~15 calls in parallel to our server and caused a buggy behavior in the UI.

    Refresh the token before expiration independent of user actions

    Finally, we decided we don't want to give the box components control on when to call our server to refresh the token. So instead of refreshing upon user action that requires the token, we set a timer that triggers when the token is about to expire and at that point, refresh the token. Something like this:

    const timer = userRef(null);

    useEffect(() =>
    const timeToRefreshToken = expirationDate - - REFRESH_TOKEN_BUFFER;

    if (timeToRefreshToken <= 0) {
    // server call to update app state with new token and new expirationDate
    } else {
    timer.current = setTimeout(() => {
    timer.current = null;
    }, timeToRefreshToken);

    // clear the timeout and the timer ref on unmount
    return clearTimer;
    }, [expirationDate]);

    Note that you probably also want to listen to the document visibilitychange event so you stop issuing requests if you app's tab is not in use.

    Comment actions Permalink

Please sign in to leave a comment.