Explain Codes LogoExplain Codes Logo

Http Authorization Header in EventSource (Server Sent Events)

javascript
event-source
sse
polyfills
Nikita BarsukovbyNikita Barsukov·Feb 23, 2025
TLDR

Presenting you the David Blaine of Javascript, the EventSource API. Well, it's almost magical, with one slight hitch, no built-in support for custom headers.

Yet, we have a workaround: the query string technique for a lightning-fast solution:

// Just like David Blaine, our token disappears (into the URL) const eventSource = new EventSource(`https://example.com/events?token=${encodeURIComponent('YOUR_TOKEN')}`);

For something a little more cunning, go the cookie route. Here's how you make it work:

// Like Santa, our token sneaks in through the cookie. Shh! document.cookie = `token=${encodeURIComponent('YOUR_TOKEN')}`; const eventSource = new EventSource('https://example.com/events');

This approach keeps the token safely hidden from the URL, eluding possible exposure and keeps the cookie jar just for the essentials.

How to: Secure EventSource using short-lived tokens and PHP validation

How about a safety helmet for your SSE setup? Make it bulletproof using short-lived tokens that PHP can verify with ease, filtering out all unsolicited requests.

Making SSE connections resilient with token-driven reestablishment

On the client-side, modify the EventSource initialization to spring back into action post disconnections, using the recent event ID (lastEventId), doubling as your short-lived token:

// When life disconnects you, lastEventId helps you reconnect const eventSource = new EventSource(`https://example.com/events?lastEventId=${encodeURIComponent('LAST_KNOWN_EVENT_ID')}`);

On the server-side, pair each event with a unique ID, ideally linked to the authenticated session or user. This not only ensures security but manages a smooth, uninterrupted event stream.

Passing tokens using lastEventId

Capitalizing on the lastEventId property, you can pass authentication tokens. No fuss!

// lastEventId isn't just any mid-life crisis, it's a new identity - a token if (eventSource.readyState === EventSource.OPEN) { eventSource.lastEventId = 'YOUR_SHORT_LIVED_TOKEN'; }

Code diversification: Incorporating polyfills for header support

When native capacity lets you down, polyfills step in. Go for the "Yaffle/EventSource" library, a reliable solution to enable custom headers:

// A spoonful of polyfill helps the header medicine go down const eventSource = new EventSourcePolyfill('https://example.com/events', { headers: { 'Authorization': `Bearer ${yourToken}` } });

With an AngularJS complimented polyfill library, you get enhanced functionality and simplicity for interceptor-based setups.

Fetch-based alternatives for additional headers support

Consider using fetch-event-source, a fetch-based EventSource that provides more control and secure access to your authorization data, significantly when native solutions fall short.

// More fetch than a game of fetch const eventSourceWithHeaders = fetchEventSource(yourSSEndpoint, { headers: { 'Authorization': `Bearer ${yourToken}` }, onmessage(message) { console.log('New message:', message.data); }, onopen() { console.log('Connection opened'); }, onerror(error) { console.log('Error:', error); } });

This method supports a multitude of headers while making your SSE experience customized and secure.

Going beyond: Error handling, message management and client-side security

The fear of plain-text transmission through URLs is real! Use cookies to send your token if the authentication server and SSE server share the same domain and prevent any unauthorized sneaking around.

This method attaches the token to a secure, boundary-limited carriage for transport.

Throwing in more security measures

Always remember, when transmitting sensitive data like tokens, keep all communications over SSL to boot out any man-in-the-middle attack. Furthermore, make sure the token storage on the backend is encrypted. Combine it with more long-lasting credentials, and you've got enhanced client security.

Guarding against errors and handling incoming messages

With onmessage and onerror handlers, manage the data flow effectively and keep connection issues at bay:

// On a good day, handle the messages eventSource.onmessage = function(event) { // Process the incoming message. }; // On a bad day, handle the errors eventSource.onerror = function(error) { // Process the error. };