aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar André Oliveira <37463445+SpecialAro@users.noreply.github.com>2023-10-13 13:14:08 +0100
committerLibravatar GitHub <noreply@github.com>2023-10-13 13:14:08 +0100
commita91fa7066a554fa5aabd9df5ca33365e6bc8663d (patch)
tree5c75b2b482536242dbcd983b1e0757c6e7b9942c /src
parent6.5.2-nightly.2 [skip ci] (diff)
downloadferdium-app-a91fa7066a554fa5aabd9df5ca33365e6bc8663d.tar.gz
ferdium-app-a91fa7066a554fa5aabd9df5ca33365e6bc8663d.tar.zst
ferdium-app-a91fa7066a554fa5aabd9df5ca33365e6bc8663d.zip
Add new token request (#1384)
* Add new token request This exists so that the user generates a new JWT token with the new adonisjs update on the server (that is now stored - hashed and using the adonis5-jwt package - which previously wasn't). This logic enhances security as we can delete the tokens on the jwt_tokens database in order to log-off users in case the APP_KEY is compromised (if we are hacked, for instance). After some time (maybe months after the migration) we can delete the old code on the server side that handles the deprecated JWT tokens (and possibly change the APP_KEY used to sign the old certificates - we can now probably use certs to sign the JWT - to enhance security as well). * Update src/api/server/ServerApi.ts Co-authored-by: MCMXC <16797721+mcmxcdev@users.noreply.github.com> * Update src/stores/UserStore.ts Co-authored-by: MCMXC <16797721+mcmxcdev@users.noreply.github.com> --------- Co-authored-by: MCMXC <16797721+mcmxcdev@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/api/UserApi.ts4
-rw-r--r--src/api/server/ServerApi.ts16
-rw-r--r--src/stores/UserStore.ts36
3 files changed, 56 insertions, 0 deletions
diff --git a/src/api/UserApi.ts b/src/api/UserApi.ts
index 2b319207a..9364b3383 100644
--- a/src/api/UserApi.ts
+++ b/src/api/UserApi.ts
@@ -38,6 +38,10 @@ export default class UserApi {
38 return this.server.userInfo(); 38 return this.server.userInfo();
39 } 39 }
40 40
41 requestNewToken() {
42 return this.server.requestNewToken();
43 }
44
41 updateInfo(data: { oldPassword: string; newPassword: string }) { 45 updateInfo(data: { oldPassword: string; newPassword: string }) {
42 const userData = data; 46 const userData = data;
43 if (userData.oldPassword && userData.newPassword) { 47 if (userData.oldPassword && userData.newPassword) {
diff --git a/src/api/server/ServerApi.ts b/src/api/server/ServerApi.ts
index 8e1d45588..c6cbbd2e2 100644
--- a/src/api/server/ServerApi.ts
+++ b/src/api/server/ServerApi.ts
@@ -151,6 +151,22 @@ export default class ServerApi {
151 return user; 151 return user;
152 } 152 }
153 153
154 async requestNewToken() {
155 if (apiBase() === SERVER_NOT_LOADED) {
156 throw new Error('Server not loaded');
157 }
158
159 const request = await sendAuthRequest(`${apiBase()}/me/newtoken`);
160 if (!request.ok) {
161 throw new Error(request.statusText);
162 }
163 const data = await request.json();
164
165 debug('ServerApi::requestNewToken new authToken received');
166
167 return data;
168 }
169
154 async updateUserInfo(data: any) { 170 async updateUserInfo(data: any) {
155 const request = await sendAuthRequest(`${apiBase()}/me`, { 171 const request = await sendAuthRequest(`${apiBase()}/me`, {
156 method: 'PUT', 172 method: 'PUT',
diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts
index 0616acdad..f98f7d340 100644
--- a/src/stores/UserStore.ts
+++ b/src/stores/UserStore.ts
@@ -50,6 +50,11 @@ export default class UserStore extends TypedStore {
50 'getInfo', 50 'getInfo',
51 ); 51 );
52 52
53 @observable requestNewTokenRequest: CachedRequest = new CachedRequest(
54 this.api.user,
55 'requestNewToken',
56 );
57
53 @observable updateUserInfoRequest: Request = new Request( 58 @observable updateUserInfoRequest: Request = new Request(
54 this.api.user, 59 this.api.user,
55 'updateInfo', 60 'updateInfo',
@@ -174,6 +179,11 @@ export default class UserStore extends TypedStore {
174 @computed get data() { 179 @computed get data() {
175 if (!this.isLoggedIn) return {}; 180 if (!this.isLoggedIn) return {};
176 181
182 const newTokenNeeded = this._shouldRequestNewToken(this.authToken);
183 if (newTokenNeeded) {
184 this._requestNewToken();
185 }
186
177 return this.getUserInfoRequest.execute().result || {}; 187 return this.getUserInfoRequest.execute().result || {};
178 } 188 }
179 189
@@ -367,6 +377,32 @@ export default class UserStore extends TypedStore {
367 } 377 }
368 378
369 // Helpers 379 // Helpers
380 _shouldRequestNewToken(authToken): boolean {
381 try {
382 const decoded = jwt.decode(authToken);
383 if (!decoded) {
384 throw new Error('Invalid token');
385 }
386
387 if (decoded.uid) {
388 return true;
389 }
390
391 return false;
392 } catch {
393 return true;
394 }
395 }
396
397 _requestNewToken(): void {
398 // Logic to request new token (use an endpoint for that)
399 const data = this.requestNewTokenRequest.execute().result;
400 if (data) {
401 this.authToken = data.token;
402 localStorage.setItem('authToken', data.token);
403 }
404 }
405
370 _parseToken(authToken) { 406 _parseToken(authToken) {
371 try { 407 try {
372 const decoded = jwt.decode(authToken); 408 const decoded = jwt.decode(authToken);