I was trying to figure out how to get a menu to appear and disappear based on being logged in in a previous post. But I think a better and possibly easier question would be, how can I watch for changes to localstorage?
I am using json web tokens in local storage for my authentication, I would love to watch for a change to localStorage and then re-update my view on new information.
I set my localStorage with this
localStorage.setItem('jwt', my_token);
The things I would like to do is check if I have a token, if I don't nothing happens, but when there is a change fire an event. I would especially like it if I could only watch for a certain named event like localStorage.getItem('jwt').
Thanks!
EDIT:
Gunter pointed me in the right direction but just in case anyone is still fairly confused by that, here is a plunker showing you how to do it. http://plnkr.co/edit/TiUasGdutCsll1nI6USC?p=preview
You have all the code written to test it in your OP. You should assume that any data held on the client could be altered with the right amount of skills and knowledge. If security is an issue, you should not base your application security around presistent storage or persistent cookies for that matter.
On the downside, localStorage is potentially vulnerable to cross-site scripting (XSS) attacks. If an attacker can inject malicious JavaScript into a webpage, they can steal an access token in localStorage. Also, unlike cookies, localStorage doesn't provide secure attributes that you can set to block attacks.
The main features of localStorage are: Shared between all tabs and windows from the same origin. The data does not expire. It remains after the browser restart and even OS reboot.
Save the Angular app and run the application. After the app gets loaded, type in localStorage from the browser console and you will be able to see the encrypted data in local storage. While trying to access the local storage data inside the application, you can get the decrypted data.
The key thing is to use window.addEventListener("storage",
. While the library probably does it the "right" way for angular, here is a "light" version I put together, using .bind(this) instead of mucking about in angular's internals.
import { Injectable, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { share } from 'rxjs/operators'; @Injectable() export class StorageService implements OnDestroy { private onSubject = new Subject<{ key: string, value: any }>(); public changes = this.onSubject.asObservable().pipe(share()); constructor() { this.start(); } ngOnDestroy() { this.stop(); } public getStorage() { let s = []; for (let i = 0; i < localStorage.length; i++) { s.push({ key: localStorage.key(i), value: JSON.parse(localStorage.getItem(localStorage.key(i))) }); } return s; } public store(key: string, data: any): void { localStorage.setItem(key, JSON.stringify(data)); this.onSubject.next({ key: key, value: data}) } public clear(key) { localStorage.removeItem(key); this.onSubject.next({ key: key, value: null }); } private start(): void { window.addEventListener("storage", this.storageEventListener.bind(this)); } private storageEventListener(event: StorageEvent) { if (event.storageArea == localStorage) { let v; try { v = JSON.parse(event.newValue); } catch (e) { v = event.newValue; } this.onSubject.next({ key: event.key, value: v }); } } private stop(): void { window.removeEventListener("storage", this.storageEventListener.bind(this)); this.onSubject.complete(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With