How to store tokens securely in Angular
Storing authentication tokens securely is critical for preventing XSS attacks and unauthorized access. As the creator of CoreUI with 12 years of Angular development experience, I’ve implemented token storage strategies for enterprise applications handling sensitive financial and healthcare data.
The most secure approach is to use httpOnly cookies for storage and avoid localStorage entirely for sensitive tokens.
Best Practice: HttpOnly Cookies
Configure your backend to send tokens in httpOnly cookies:
// Backend (Node.js/Express example)
res.cookie('auth_token', token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000
})
Angular automatically includes cookies in requests. Configure HttpClient:
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get('/api/data', {
withCredentials: true
})
}
}
Alternative: Memory Storage with Refresh Tokens
If you must handle tokens client-side, store access tokens in memory and refresh tokens in httpOnly cookies:
import { Injectable } from '@angular/core'
import { BehaviorSubject, Observable } from 'rxjs'
interface TokenPair {
accessToken: string
expiresAt: number
}
@Injectable({
providedIn: 'root'
})
export class TokenService {
private tokenSubject = new BehaviorSubject<string | null>(null)
private tokenExpiry: number | null = null
get token$(): Observable<string | null> {
return this.tokenSubject.asObservable()
}
get accessToken(): string | null {
if (this.isTokenExpired()) {
return null
}
return this.tokenSubject.value
}
setTokens(accessToken: string, expiresIn: number): void {
this.tokenSubject.next(accessToken)
this.tokenExpiry = Date.now() + expiresIn * 1000
}
clearTokens(): void {
this.tokenSubject.next(null)
this.tokenExpiry = null
}
private isTokenExpired(): boolean {
if (!this.tokenExpiry) return true
return Date.now() >= this.tokenExpiry
}
}
HTTP Interceptor
Add tokens to requests automatically:
import { Injectable } from '@angular/core'
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'
import { Observable } from 'rxjs'
import { TokenService } from './token.service'
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private tokenService: TokenService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.tokenService.accessToken
if (token) {
const cloned = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
})
return next.handle(cloned)
}
return next.handle(req)
}
}
Register the interceptor:
import { HTTP_INTERCEPTORS } from '@angular/common/http'
export const appConfig: ApplicationConfig = {
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
]
}
Security Comparison
Never use localStorage for sensitive tokens:
- ❌ Vulnerable to XSS attacks
- ❌ Accessible by any JavaScript code
- ❌ No expiration mechanism
HttpOnly cookies (recommended):
- ✅ Not accessible via JavaScript
- ✅ Automatic expiration
- ✅ CSRF protection with SameSite
Memory storage (acceptable):
- ✅ Cleared on page refresh
- ✅ Not vulnerable to XSS theft
- ⚠️ Requires refresh token strategy
Best Practice Note
This is the same token storage strategy we use in CoreUI’s Angular admin templates for maximum security. HttpOnly cookies provide the best protection against XSS attacks, which are the most common web vulnerability.
For production applications, consider using CoreUI’s Angular Admin Template which includes pre-built secure authentication with httpOnly cookie support and automatic token refresh.
Related Articles
If you’re implementing authentication, you might also want to learn how to refresh JWT tokens in Angular to maintain user sessions securely.



