From 5cea7a22ea58e774e8cabd9c095d15afea487d33 Mon Sep 17 00:00:00 2001 From: Nigel Breslaw Date: Sat, 17 Feb 2024 12:43:03 +0200 Subject: [PATCH 1/2] Single static method to validate, update and set token --- native_gg/src/authentication/AuthService.ts | 41 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/native_gg/src/authentication/AuthService.ts b/native_gg/src/authentication/AuthService.ts index 67db513e3..31395498c 100644 --- a/native_gg/src/authentication/AuthService.ts +++ b/native_gg/src/authentication/AuthService.ts @@ -145,6 +145,41 @@ class AuthService { reject(AuthService.instance.authToken); }); } + // This function validates, gets refreshed tokens, saves and sets them. + private static validateAndSetToken(token: AuthToken): Promise { + return new Promise((resolve, reject) => { + let validToken = token; + + const isValidRefresh = isValidRefreshToken(token); + if (!isValidRefresh) { + // Nothing can be done. The user needs to re-auth. + console.error("Refresh token expired"); + return reject(false); + } + + const isValidAccess = isValidAccessToken(token); + if (!isValidAccess) { + getAccessToken(token) + .then((newAuthToken) => { + validToken = newAuthToken; + }) + .catch((e) => { + return reject(e); + }); + } + + AuthService.saveAndSetToken(validToken); + + return resolve(true); + }); + } + + private static saveAndSetToken(token: AuthToken) { + const currentUserID = AuthService.instance.currentUserID; + AsyncStorage.setItem(`${currentUserID}${Store._refresh_token}`, JSON.stringify(token)); + AuthService.getInstance().setAuthToken(token); + } + // Method to subscribe to auth changes subscribe(dispatch: React.Dispatch) { @@ -183,7 +218,7 @@ class AuthService { } } - setAuthToken(token: AuthToken | null) { + setAuthToken(token: RefreshToken | null) { this.authToken = token; if (this.dispatch) { this.dispatch({ type: "setAuthenticated", payload: this.isAuthenticated() }); @@ -231,7 +266,7 @@ class AuthService { // If this fails the user needs to auth again. It isn't safe to retry as it can result in 'invalid_grand'. const initialJSONToken = await getRefreshToken(code); try { - const validatedToken = v.parse(authTokenSchema, initialJSONToken); + const validatedToken = v.parse(refreshTokenSchema, initialJSONToken); const fullToken = await getAccessToken(validatedToken); this.buildBungieAccount(fullToken); } catch (e) { @@ -245,7 +280,7 @@ class AuthService { } } - async buildBungieAccount(authToken: AuthToken) { + async buildBungieAccount(authToken: RefreshToken) { if (authToken) { try { let rawLinkedProfiles = await getLinkedProfiles(authToken); From 9a17a6fd891531b123ce0f55d79b0678b77f0270 Mon Sep 17 00:00:00 2001 From: Nigel Breslaw Date: Sat, 17 Feb 2024 12:52:15 +0200 Subject: [PATCH 2/2] DRY --- native_gg/src/authentication/AuthService.ts | 63 +++++---------------- 1 file changed, 15 insertions(+), 48 deletions(-) diff --git a/native_gg/src/authentication/AuthService.ts b/native_gg/src/authentication/AuthService.ts index 31395498c..199676d08 100644 --- a/native_gg/src/authentication/AuthService.ts +++ b/native_gg/src/authentication/AuthService.ts @@ -76,31 +76,7 @@ class AuthService { try { const stringToken = v.parse(v.string(), token); const validatedToken = v.parse(authTokenSchema, JSON.parse(stringToken)); - - const isValidRefresh = isValidRefreshToken(validatedToken); - if (!isValidRefresh) { - console.error("Refresh token expired"); - return reject(false); - } - console.log("valid refresh token"); - const isValidAccess = isValidAccessToken(validatedToken); - if (!isValidAccess) { - console.log("Access token expired"); - getAccessToken(validatedToken) - .then((newAuthToken) => { - console.log("Got new access token"); - AsyncStorage.setItem( - `${this.currentUserID}${Store._refresh_token}`, - JSON.stringify(newAuthToken), - ); - this.setAuthToken(newAuthToken); - return resolve(true); - }) - .catch((e) => { - return reject(e); - }); - } - this.setAuthToken(validatedToken); + AuthService.validateAndSetToken(validatedToken); return resolve(true); } catch (error) { console.log(error); @@ -123,28 +99,20 @@ class AuthService { static getTokenAsync(): Promise { return new Promise((resolve, reject) => { if (AuthService.instance.authToken) { - /// is the access token valid? - const isValid = isValidAccessToken(AuthService.instance.authToken); - if (!isValid) { - console.log("Token expired"); - getAccessToken(AuthService.instance.authToken) - .then((authToken) => { - const currentUserID = AuthService.instance.currentUserID; - AsyncStorage.setItem(`${currentUserID}${Store._refresh_token}`, JSON.stringify(authToken)); - AuthService.instance.setAuthToken(authToken); - console.log("Got new token"); - return resolve(authToken); - }) - .catch((e) => { - return reject(e); - }); - } - - return resolve(AuthService.instance.authToken); + AuthService.validateAndSetToken(AuthService.instance.authToken) + .then(() => { + return resolve(AuthService.instance.authToken); + }) + .catch((e) => { + console.error("Failed to validate token", e); + return reject(null); + }); + } else { + return reject(null); } - reject(AuthService.instance.authToken); }); } + // This function validates, gets refreshed tokens, saves and sets them. private static validateAndSetToken(token: AuthToken): Promise { return new Promise((resolve, reject) => { @@ -180,7 +148,6 @@ class AuthService { AuthService.getInstance().setAuthToken(token); } - // Method to subscribe to auth changes subscribe(dispatch: React.Dispatch) { this.dispatch = dispatch; @@ -218,7 +185,7 @@ class AuthService { } } - setAuthToken(token: RefreshToken | null) { + setAuthToken(token: AuthToken | null) { this.authToken = token; if (this.dispatch) { this.dispatch({ type: "setAuthenticated", payload: this.isAuthenticated() }); @@ -266,7 +233,7 @@ class AuthService { // If this fails the user needs to auth again. It isn't safe to retry as it can result in 'invalid_grand'. const initialJSONToken = await getRefreshToken(code); try { - const validatedToken = v.parse(refreshTokenSchema, initialJSONToken); + const validatedToken = v.parse(authTokenSchema, initialJSONToken); const fullToken = await getAccessToken(validatedToken); this.buildBungieAccount(fullToken); } catch (e) { @@ -280,7 +247,7 @@ class AuthService { } } - async buildBungieAccount(authToken: RefreshToken) { + async buildBungieAccount(authToken: AuthToken) { if (authToken) { try { let rawLinkedProfiles = await getLinkedProfiles(authToken);