Authentication using Uppy and Tus

Hi there. I’m attempting to integrate Uppy, with the Tus plugin into a next-react app with authentication, and I’ve run into some undesirable behavior.

Firstly, everytime my authorization token expires, I am refreshing it using a refresh function, which is run in the onAfterResponse method for the Tus plugin. As you would expect, this runs for every request encountering a 401, meaning if I upload 5 items, I will be refreshing 5 times. I however only want to refresh on the 1st 401 encountered. I’ve attempted solutions with useRef, and 0 concurrent uploads (limit : 0 in the Tus plugin settings), but was unsuccessful.

Secondly, I’m struggling to figure out how I can update an uppy plugin with new settings while it’s still uploading. For instance, I would like to share authentication credentials to uppy using the react context api. These credentials change on refresh, so I want to update uppy with the new token.

Thank you to anyone that takes the time to read this.

Here is an example of what I am doing in my code:

function useUppy(onCreateOrChange: (uppyInstance: Uppy) => Uppy, deps: any[]) {
    const [uppy, setUppy] = useState(() => {
        const uppy = new Uppy()
        return onCreateOrChange(uppy)
    });

    useEffect(() => {
        setUppy(onCreateOrChange(uppy))
    }, deps);

    return uppy;
}

 const uppy = useUppy(() => {
        const uppy = new Uppy({
           id: id            
           meta: meta,
        })
            .use(Tus, { 
                endpoint: TUS_ENDPOINT,
                async onBeforeRequest(req) {
                    let token = "sometoken"
                    req.setHeader('Authorization', `Bearer ${token}`)
                },
                async onShouldRetry(err, retryAttempt, options, next) {
                    const status = err?.originalResponse?.getStatus()
                    if (status === 401) {
                        return true
                    }
                    return next(err)
                },
                async onAfterResponse(req, res) {
                    if (res.getStatus() === 401) {
                        await refresh()
                    }
                },
            }) 
           return uppy
    }, [deps])

Hi, you should keep Uppy outside of the render loop at all costs.

I made an example which dynamically changes the onBeforeRequest function to change the token being set but doesn’t put Uppy inside React. Note that this is only needed if you can only get the token from the state inside a component. You should definitely try to not get the token from React state inside a component, but outside of React. Then you can create a getToken() function which is used inside onBeforeRequest and have no useEffect for this.

Hope this helps