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
401and the server's message. - With
dosa123, the server returned a token./meaccepted it in theAuthorizationheader.
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
- How a token login works.
- Where to keep a token, and the risks of each place.
- How to send the
Authorizationheader on every request. - How to keep login state in a Pinia store and protect pages.
- How to refresh an expired token and retry.
- How to log out properly.
- How to show live data with polling.
- How to use Server-Sent Events.
- 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
| Place | Survives reload | Risk | Use when |
|---|---|---|---|
| A ref in memory (a Pinia store) | No | Lowest. Gone when the tab closes | Short sessions, plus a refresh cookie |
localStorage | Yes | Any XSS bug can read it | Small apps that accept the risk |
httpOnly cookie set by the server | Yes | JavaScript cannot read it at all | Most 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
logInaction talks to the server. Pages only call it.
- What happened:
/kitchenredirected 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
| Way | How it works | Good for |
|---|---|---|
| Polling | Ask the server again every few seconds | Simple, rarely changing data |
| Server-Sent Events (SSE) | The server pushes messages down one open connection | Live feeds, notifications |
| WebSocket | A two-way open connection | Chat, 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),httpOnlycookie (server-set). - Auth store + guard = Pinia keeps the token. A
beforeEachguard 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
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Token in a plain global variable, no store | Any variable is fine | Keep it in a Pinia store | Components miss login changes |
| Forgetting the header on some requests | The server remembers you | One request interceptor | Random 401 errors |
| Refreshing on every 401 forever | Refresh always helps | Retry once, then log out | An endless refresh loop |
| Logging out only in the browser | Clearing the store is enough | Also tell the server | The old token still works |
| Not closing sockets or timers | They stop by themselves | Close in onUnmounted | Duplicate messages and leaks |
| Reconnecting instantly in a loop | Faster reconnect is better | Wait longer each time | The server is flooded |
| Storing passwords | It saves typing | Never store passwords | A 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