Authentication and Real-Time Data

By Syncfusion®, Inc. · Last updated

Logging in with a token, where to keep tokens safely, sending the Authorization header, an auth store with Pinia, protecting routes, refreshing an expired token and retrying, logging out, and live data with polling, Server-Sent Events and WebSockets, with reconnect and cleanup.

Who Are You, and What Is New?

  • Many pages are only for logged-in users: Meera's kitchen screen, a customer's orders.
  • Authentication = proving who you are, usually with an email and password.
  • After login, the server gives the app a token: a long secret text that says "this is Meera".
  • The app sends the token with every request. The server checks it.
  • Some data changes all the time: new orders, chat messages. Real-time data reaches the page without a refresh.

Simple lesson: log in once, send the token every time, and let live data flow in.

A Real-World Example

  • Meera logs in to her kitchen screen with her password.
  • The app keeps the token, then asks the server "who am I?" with it.
  • Try a wrong password first, then dosa123.
  • What happened: a wrong password got 401 and the server's message.
  • With dosa123, the server returned a token. /me accepted it in the Authorization header.

A real server checks passwords against a database and signs real tokens, often JWTs. In this lab, the pretend API accepts the password dosa123, gives tokens like tok-1, and logs every request in the Console.

What You Will Learn

  1. How a token login works.
  2. Where to keep a token, and the risks of each place.
  3. How to send the Authorization header on every request.
  4. How to keep login state in a Pinia store and protect pages.
  5. How to refresh an expired token and retry.
  6. How to log out properly.
  7. How to show live data with polling.
  8. How to use Server-Sent Events.
  9. How to use a WebSocket, with reconnect and cleanup.

The Token Flow

Animation: the app posts email and password to /login and receives a token. Later requests carry the token in the Authorization header. When the server answers 401 token expired, the app calls /refresh, gets a new token and retries the request

Vue app

Server

1. POST /login (email, password) → ← 2. 200 3. GET /secure/orders + Bearer token → ← 4. 401 token expired 5. POST /refresh → new token 6. retry the GET → 200 orders ✓

Log in once, send the token, refresh it when it expires, then retry.

Where to Keep the Token

PlaceSurvives reloadRiskUse when
A ref in memory (a Pinia store)NoLowest. Gone when the tab closesShort sessions, plus a refresh cookie
localStorageYesAny XSS bug can read itSmall apps that accept the risk
httpOnly cookie set by the serverYesJavaScript cannot read it at allMost secure. Needs server and CSRF care

Never store a password in the app. Keep tokens short-lived. If you use localStorage, the XSS rules from Templates and Directives and Errors, Security and Deployment matter even more.

Simple lesson: the token proves who you are. Keep it in the safest place your server allows.

An Auth Store and Protected Pages

  • Keep the token and user in a Pinia store, as in State Management with Pinia.
  • A router guard sends visitors without a token to /login, as in Navigation Guards and Advanced Routing.
  • The store's logIn action talks to the server. Pages only call it.
  • What happened: /kitchen redirected to the login page.
  • After logging in, you landed on the kitchen screen. "Log out" told the server, cleared the store and went back.

Sending the Token Every Time

  • Writing the header by hand in every request is easy to forget.
  • An Axios request interceptor adds it to every request, as in HTTP Requests.
  • A response interceptor handles 401: refresh the token once, then retry the request.
  • If the refresh also fails, log the user out.
  • What happened: the first request used an expired token and got 401.
  • The interceptor refreshed it, retried, and the orders appeared. The page never knew.

Mark the retried request (here _retried) so a second 401 does not start an endless refresh loop. When several requests fail at once, real apps share one refresh call between them.

Simple lesson: one interceptor adds the token. Another refreshes it once on 401 and retries.

Live Data

WayHow it worksGood for
PollingAsk the server again every few secondsSimple, rarely changing data
Server-Sent Events (SSE)The server pushes messages down one open connectionLive feeds, notifications
WebSocketA two-way open connectionChat, games, live kitchen screens

Polling

Server-Sent Events

  • new EventSource(url) opens a connection the server keeps open.
  • Each pushed message arrives in onmessage. The browser reconnects by itself if it drops.
  • Close it in onUnmounted.

WebSockets in a Composable

  • new WebSocket("wss://…") opens a two-way connection. Both sides can send at any time.
  • Wrap it in a composable, as in Composables, Directives and Plugins: state, send, reconnect and cleanup in one place.
  • Reconnect after a drop with a growing wait (1 s, 2 s, 4 s…), so a broken server is not flooded.
  • What happened: new orders streamed in. "Mark table 4 served" sent a message, and the Console shows the server's reply.
  • "Close" unmounted the screen, and the composable closed the socket.

In this lab, wss://api.meeraskitchen.dev and /events are pretend live servers inside the preview that send a new order every 1.2 seconds. A real server keeps the connection open over the network, and drops can happen at any time.

Simple lesson: poll for simple data, SSE for one-way feeds, WebSocket for two-way. Always close on unmount.

TL;DR

  • Token login = POST email and password, get a token, send it on every request.
  • Authorization: Bearer <token> = the header that carries the token.
  • Token storage = memory (safest), localStorage (XSS risk), httpOnly cookie (server-set).
  • Auth store + guard = Pinia keeps the token. A beforeEach guard protects pages.
  • Refresh and retry = on 401, refresh once, then retry the request.
  • Log out = tell the server, clear the store, go to the login page.
  • Polling = ask again every few seconds. Clear the timer on unmount.
  • SSE = EventSource: the server pushes, the browser reconnects.
  • WebSocket = two-way connection. Reconnect with growing waits, close on unmount.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Token in a plain global variable, no storeAny variable is fineKeep it in a Pinia storeComponents miss login changes
Forgetting the header on some requestsThe server remembers youOne request interceptorRandom 401 errors
Refreshing on every 401 foreverRefresh always helpsRetry once, then log outAn endless refresh loop
Logging out only in the browserClearing the store is enoughAlso tell the serverThe old token still works
Not closing sockets or timersThey stop by themselvesClose in onUnmountedDuplicate messages and leaks
Reconnecting instantly in a loopFaster reconnect is betterWait longer each timeThe server is flooded
Storing passwordsIt saves typingNever store passwordsA serious leak

Check Yourself

Exercises

What to Remember

  • Log in once, then send Authorization: Bearer <token> with every request.
  • Keep tokens in memory or a server-set cookie. Never store passwords.
  • Use a Pinia auth store and a router guard to protect pages.
  • On 401, refresh once and retry. Log out on the server too.
  • Poll, SSE or WebSocket for live data. Always clean up on unmount.

Next: Dynamic and Built-In Components