refresh Directline token after it got expired

929 views Asked by At

I'm applying a token based authentication to bot webchat along with the chat being persisted but facing an issue after the token got expired. Unable to connect to bot.

At first I'm generating a token and refreshing for 15 mins and every thing working fine till then. But, when user went offline with no internet connectivity, suppose for around 6-7 hours, due to offline the refresh token post call don't happen and there will be an expired token in the session storage. later than he wanted to chat with the same conversation he did before. but was going to FailedToConnect or ExpiredToken issue. As the token got expired due to inactivity unable to connect to bot again.

My main intention is how to connect user with the previous converstion.

Thanks in advance.

 (async function() {
    'use strict';
    const {
            hooks: { usePostActivity },
            hooks: { useDirection },
            ReactWebChat
    } = window.WebChat;
    
     let { token, conversation_Id } = sessionStorage;
    if ( !token ) {
                    const res = await fetch( 'https:/localhost/api/generateToken', { method: 'POST' } );
                    const { token: directLineToken, conversationId: conversationId } = await res.json();
                    sessionStorage[ 'token' ] = directLineToken;
                    sessionStorage[ 'conversation_Id' ] = conversationId;
                    token = directLineToken;
                    conversation_Id = conversationId;
                    }
                    
    if (token) {
        await setInterval(async () => {
        var myHeaders = new Headers();
        myHeaders.append("Authorization","Bearer "+ sessionStorage[ 'token' ]);
        let res = await fetch( 'https://directline.botframework.com/v3/directline/tokens/refresh', {
                                method: 'POST', 
                                headers: myHeaders,
                                });
        const { token: directLineToken, conversationId } = await res.json();
            sessionStorage[ 'token' ] = directLineToken;
            sessionStorage[ 'conversation_Id' ] = conversationId;
            token = directLineToken;
            conversation_Id = conversationId;
        }, 1000*60*15)}
        
                        
    
    
    const  store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
    if(action.payload && action.payload.directLine) {
        const subscription = action.payload.directLine.connectionStatus$.subscribe({
                error: error => console.log( error ),
                next: value => {
                        if ( value === 0 ) {console.log('Uninitialized')} 
                        else if ( value === 1 ) {console.log('Connecting')} 
                        else if ( value === 2 ) {console.log('Online')}
                        else if  ( value === 3 ) {console.log('Expire Token')}
                        else if ( value === 4 ) {console.log('FailedToConnect')}
                        else if ( value === 5 ) {console.log('Ended')}
                }
            });
        }
     if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
        dispatch({
                type: 'WEB_CHAT/SEND_EVENT',
                payload: {
                    name: 'Welcome',
                    value: { language: window.navigator.language }
                    }
                });
            }
            
    
    if (action.type === 'DIRECT_LINE/POST_ACTIVITY') {
                action = window.simpleUpdateIn(action, ['payload', 'activity', 'channelData', 'CustomChannel'], () =>"webchat");
                }
    
        return next(action);
    });
    
    
   const  botconnection = createDirectLine( {token,webSockets: true,watermark: "0" });
    
    window.ReactDOM.render(
    <ReactWebChat directLine={botconnection}
                  store={store}
        />,
        document.getElementById('webchat'));
        document.querySelector('#webchat > *').focus();
        })().catch(err => console.error(err));
1

There are 1 answers

0
Steven Kanberg On

Unfortunately, once a token is expired there is no way to obtain a refreshed token in order to continue a conversation. The original token must still be valid when requesting a refreshed token.


Regarding maintaining a connection, there's no great option, but here is an idea that may be worth trying:

  • Create a service that, when a token is generated, it is sent to this service along with the user's online status.
  • The service would manage the token refreshes and would return the refreshed token to the original client to be consumed.
  • If a user goes offline, the call to return the refreshed token would fail, the service updates the user's online status, and follows some condition on when to stop refreshing (e.g. after 4 hours).
  • If a user comes back online, state is again updated, the refreshed token is consumed, and the conversation continues.

Hope of help!