@@ -21,6 +21,7 @@ import { AcctStore, AcctStoreDict } from '../../../platform/store/acct-store.js'
2121import { AccountServer } from '../../account-server.js' ;
2222import { EnterpriseServer } from '../../account-servers/enterprise-server.js' ;
2323import { InMemoryStore } from '../../../platform/store/in-memory-store.js' ;
24+ import { InMemoryStoreKeys } from '../../../core/const.js' ;
2425
2526type GoogleAuthTokenInfo = { issued_to : string , audience : string , scope : string , expires_in : number , access_type : 'offline' } ;
2627type GoogleAuthTokensResponse = { access_token : string , expires_in : number , refresh_token ?: string , id_token : string , token_type : 'Bearer' } ;
@@ -80,22 +81,27 @@ export class GoogleAuth {
8081 if ( ! acctEmail ) {
8182 throw new Error ( 'missing account_email in api_gmail_call' ) ;
8283 }
83- const storage = await AcctStore . get ( acctEmail , [ 'google_token_access' , 'google_token_expires' , ' google_token_scopes', 'google_token_refresh' ] ) ;
84- if ( ! storage . google_token_access || ! storage . google_token_refresh ) {
84+ const storage = await AcctStore . get ( acctEmail , [ 'google_token_scopes' , 'google_token_refresh' ] ) ;
85+ if ( ! storage . google_token_refresh ) {
8586 throw new GoogleAuthErr ( `Account ${ acctEmail } not connected to FlowCrypt Browser Extension` ) ;
86- } else if ( GoogleAuth . googleApiIsAuthTokenValid ( storage ) && ! forceRefresh ) {
87- return `Bearer ${ storage . google_token_access } ` ;
88- } else { // refresh token
89- const refreshTokenRes = await GoogleAuth . googleAuthRefreshToken ( storage . google_token_refresh ) ;
87+ }
88+ if ( ! forceRefresh ) {
89+ const googleAccessToken = await InMemoryStore . get ( acctEmail , InMemoryStoreKeys . GOOGLE_TOKEN_ACCESS ) ;
90+ if ( googleAccessToken ) {
91+ return `Bearer ${ googleAccessToken } ` ;
92+ }
93+ }
94+ // refresh token
95+ const refreshTokenRes = await GoogleAuth . googleAuthRefreshToken ( storage . google_token_refresh ) ;
96+ if ( refreshTokenRes . access_token ) {
9097 await GoogleAuth . googleAuthCheckAccessToken ( refreshTokenRes . access_token ) ; // https://groups.google.com/forum/#!topic/oauth2-dev/QOFZ4G7Ktzg
9198 await GoogleAuth . googleAuthSaveTokens ( acctEmail , refreshTokenRes , storage . google_token_scopes || [ ] ) ;
92- const auth = await AcctStore . get ( acctEmail , [ 'google_token_access' , 'google_token_expires' ] ) ;
93- if ( GoogleAuth . googleApiIsAuthTokenValid ( auth ) ) { // have a valid gmail_api oauth token
94- return `Bearer ${ auth . google_token_access } ` ;
95- } else {
96- throw new GoogleAuthErr ( `Could not refresh google auth token - did not become valid (access:${ ! ! auth . google_token_access } ,expires:${ auth . google_token_expires } ,now:${ Date . now ( ) } )` ) ;
99+ const googleAccessToken = await InMemoryStore . get ( acctEmail , InMemoryStoreKeys . GOOGLE_TOKEN_ACCESS ) ;
100+ if ( googleAccessToken ) {
101+ return `Bearer ${ googleAccessToken } ` ;
97102 }
98103 }
104+ throw new GoogleAuthErr ( `Could not refresh google auth token - did not become valid (access:${ refreshTokenRes . access_token } ,expires_in:${ refreshTokenRes . expires_in } ,now:${ Date . now ( ) } )` ) ;
99105 } ;
100106
101107 public static apiGoogleCallRetryAuthErrorOneTime = async ( acctEmail : string , request : JQuery . AjaxSettings ) : Promise < any > => {
@@ -282,9 +288,8 @@ export class GoogleAuth {
282288 private static googleAuthSaveTokens = async ( acctEmail : string , tokensObj : GoogleAuthTokensResponse , scopes : string [ ] ) => {
283289 const parsedOpenId = GoogleAuth . parseIdToken ( tokensObj . id_token ) ;
284290 const { full_name, picture } = await AcctStore . get ( acctEmail , [ 'full_name' , 'picture' ] ) ;
291+ const googleTokenExpires = new Date ( ) . getTime ( ) + ( tokensObj . expires_in as number - 120 ) * 1000 ; // let our copy expire 2 minutes beforehand
285292 const toSave : AcctStoreDict = {
286- google_token_access : tokensObj . access_token ,
287- google_token_expires : new Date ( ) . getTime ( ) + ( tokensObj . expires_in as number ) * 1000 ,
288293 google_token_scopes : scopes ,
289294 full_name : full_name || parsedOpenId . name ,
290295 picture : picture || parsedOpenId . picture ,
@@ -293,7 +298,8 @@ export class GoogleAuth {
293298 toSave . google_token_refresh = tokensObj . refresh_token ;
294299 }
295300 await AcctStore . set ( acctEmail , toSave ) ;
296- await InMemoryStore . set ( acctEmail , InMemoryStore . ID_TOKEN_STORAGE_KEY , tokensObj . id_token ) ;
301+ await InMemoryStore . set ( acctEmail , InMemoryStoreKeys . ID_TOKEN , tokensObj . id_token ) ;
302+ await InMemoryStore . set ( acctEmail , InMemoryStoreKeys . GOOGLE_TOKEN_ACCESS , tokensObj . access_token , googleTokenExpires ) ;
297303 } ;
298304
299305 private static googleAuthGetTokens = async ( code : string ) => {
@@ -322,13 +328,6 @@ export class GoogleAuth {
322328 } , Catch . stackTrace ( ) ) as any as GoogleAuthTokenInfo ;
323329 } ;
324330
325- /**
326- * oauth token will be valid for another 2 min
327- */
328- private static googleApiIsAuthTokenValid = ( s : AcctStoreDict ) => {
329- return s . google_token_access && ( ! s . google_token_expires || s . google_token_expires > Date . now ( ) + ( 120 * 1000 ) ) ;
330- } ;
331-
332331 // todo - would be better to use a TS type guard instead of the type cast when checking OpenId
333332 // check for things we actually use: photo/name/locale
334333 private static parseIdToken = ( idToken : string ) : GmailRes . OpenId => {
0 commit comments