Server returns 500 after token refresh

[Problem/Question]
We have a chat in a react app which uses and as described in your examples.

The provider uses a custom SessionHandler to provide the ability to refresh the token, but after some time (can’t really say how many minutes) when the sessionHandler.onSessionTokenRequired is called and generates a new token which is than resolve(newToken) then we’re seeing server 500 errors from the sdk to the sendbird server:

https://api-e91a7eaa-412b-43eb-a504-b2b621c6986e.sendbird.com/v3/users/MY_USER_ID/session_key
// Obviously MY_USER_ID is a real user ID.



In addition, the Uncaught (in promise) SendbirdError: This session token is invalid. seems to be coming from within the sendbird package and i couldn’t find how to catch this error…

Here’s how the provider looks like:


function ChatProvider({ children }) {
  const dispatch = useDispatch();
  const [token, setToken] = useState();
  const state = useSelector((state) => state.toJS());
  const userId = state.global?.portalUser;
  const [channels, setChannels] = useState();

  const authService = useMemo(() => {
    return AuthService.getInstance()
  }, []);

  const issueSessionToken = async () => {
    if (!authService?.hasValidToken()) {
      return new Error('No Valid Token');
    }

    return new RequestHelper()
      .sendRequest('GET', '/v2/chat/accessToken')
      .then((res) => {
        if (res.status === 'success' && res.data?.accessToken !== '') {
          const token = res.data;
          setToken(token);
          return token;
        } else {
          console.error(
            'something went wrong trying to get chat access token',
            res
          );
        }
      })
      .catch((err) => {
        console.error('Error trying to get chat access token', err);
        return err;
      });
  };

  useEffect(() => {
    issueSessionToken();
  }, []);

  useEffect(() => {
    if (!token || !authService?.hasValidToken() || channels) {
      return;
    }

    function getChannels() {
      new RequestHelper()
        .sendRequest('GET', '/v2/chat/channels')
        .then((res) => {
          setChannels(res.data.channels)
          dispatch({
            type: CHAT_SET_CHANNELS,
            payload: res.data.channels ?? [],
          });
        })
        .catch((err) => {
          console.error('Error trying to get channels for coach', err);
        });
    }
    getChannels();
  }, [token]);

  const configureSession = () => {
    const sessionHandler = new SessionHandler();
    sessionHandler.onSessionTokenRequired = async (resolve, reject) => {
      const newToken = await issueSessionToken();
      if(newToken instanceof Error){
        reject('Invalid token');
      } else if (newToken) {
        resolve(newToken);
      } else {
        reject('Invalid token');
      }
    };
    return sessionHandler;
  };

  const isValidSession = useMemo(() => {
    return token && userId && authService?.hasValidToken();
  }, [token, userId]);


  return isValidSession ? (
    <SendbirdProvider
      appId={config.sendbirdAppId}
      userId={userId}
      accessToken={token.accessToken}
      configureSession={configureSession}
      isVoiceMessageEnabled={true}
      isMessageReceiptStatusEnabledOnChannelList={true}
      isTypingIndicatorEnabledOnChannelList={true}
      colorSet={{
        '--sendbird-light-primary-500': '#286345',
        '--sendbird-light-primary-400': '#286345',
        '--sendbird-light-primary-300': '#286345',
        '--sendbird-light-primary-200': '#286345',
        '--sendbird-light-primary-100': '#286345',
      }}
      config={{
        logLevel:
          process.env.REACT_APP_ENV === 'production'
            ? ['error']
            : ['warning', 'error'],
      }}
    >
      {children}
      <SendbirdListener />
    </SendbirdProvider>
  ) : (
    <div className="chat-info-pane">
      <Spinner />
    </div>
  );
}

The Listener component looks like this:


const SendbirdListener = ({onReconnectionFailed}) => {
  const dispatch = useDispatch();
  const sendbirdGlobalStore = useSendbirdStateContext();
  const sdkInstance = sendbirdSelectors.getSdk(sendbirdGlobalStore);

  const updateUnreadCount = (channel) => {
    const { url, unreadMessageCount } = channel;
    dispatch({
      type: CHAT_UPDATE_CHANNELS_UNREAD_COUNT,
      payload: { channelId: url, unreadMessageCount },
    });
  };

  useEffect(() => {
    const id = generateUid();
    let channelHandlerConstructor, connectionHandler;

    if (sdkInstance?.groupChannel?.addGroupChannelHandler) {
      channelHandlerConstructor = {
        onChannelChanged: (channel) => {
          updateUnreadCount(channel);
        },
      };

      const channelHandler = new GroupChannelHandler(channelHandlerConstructor);
      sdkInstance.groupChannel.addGroupChannelHandler(id, channelHandler);
    }

    return () => {
      if (sdkInstance?.groupChannel?.removeChannelHandler) {
        sdkInstance.groupChannel.removeChannelHandler(id);
      }
    };
  }, [sdkInstance]);

  return <></>;
};

export default SendbirdListener;

The chat itself looks like this:

function Chat(){
  return <SBConversation
    channelUrl={currentChannelUrl}
    disableMarkAsRead={true}
    showSearchIcon={false}
    animatedMessage={true}
    renderChannelHeader={() => <div />}
    reconnectOnIdle={false}
  />
}

// If problem, please fill out the below. If question, please delete.
[UIKit Version]
@sendbird/chat”: “^4.9.6”,
@sendbird/uikit-react”: “^3.6.5”,

[Reproduction Steps]
// Please provide reproduction steps and, if possible, code snippets.

[Frequency]
every time

[Current impact]
high impact, expired sessions are crashing the app

Hey @amit,

Can you submit this to our Support team via the Dashboard? We’ll take a look at what’s going on.

Thanks,
Tyler

Hey @Tyler, thanks for the prompt reply!

I think i found the cause for the 500 error, i sent the wrong payload onSessionTokenRequired() so that’s on me and sorry…
However, we’re still getting the expired token error when we send the new one in, I checked our server and we get the token using /v3/users/USER_ID.

I’ve submitted a support request as well, thanks again!