Search code examples
javascriptserver-sent-events

EventSource with bearer token


I am currently trying to setup a realtime list using SSE. Everything is working as expected except when it comes to querying data that needs authentication. I am using JWTs and have an axios interceptor for all my other requests sitewide that works great.

Here is my observable

return new Observable<Api.MyType>((subscriber) => {
    const eventSource = new EventSource(url)

    const eventListener = (event: MessageEvent<string>) => {
        try {
            const item: Api.MyType = JSON.parse(event.data)

            subscriber.next(item)
        } catch (error) {
            subscriber.error(error as Error)
        }
    }

    eventSource.addEventListener('event-name', eventListener)

    eventSource.onerror = (_: Event) => {
        subscriber.error(new Error('EventSource failed'))

        eventSource.close()
    }

    return () => {
        eventSource.removeEventListener('event-name', eventListener)
        eventSource.close()
    }
})

I tried using event-source-polyfill but could not get it working with my event listener - also in the repos readme (despite having 500k weekly downloads) in russian it says "dont use this crap library".

Long story short, I need a way to pass my token with my request in order to successfully connect to my stream

const eventSource = new EventSource(url, {
    headers: {
        authorization: `Bearer ${token from cookies}`
    }
})

Update I have used fetch api with promises however after two events from the stream it collapses. I have identified why yet.

As per websockets I have successfully implemented a websockets solution however I only need unidirectional flow so in order to simplify I would like to get SSE working. Also I believe that websockets would increase my concurrent connections.


Solution

  • The EventSource constructor does not accept a headers option, you cannot use the EventSource API if you need a custom authorization header. All it supports is regular cookie authentication - maybe change your backend to accept those if you're storing the token in a cookie anyway?

    As an alternative, you can use the fetch API which gives you the necessary control over request headers, and allows parsing the response yourself by reading it as a stream.

    However, you may want to consider switching to web sockets anyway as JWTs have an expiry time. If you need to refresh your access token while the event stream connection is open, you need to be able to send the new token via some method that is not a header.