mirror of https://github.com/grafana/grafana.git
				
				
				
			ClientTokenRotation: Rotate only expired tokens (#74010)
* ClientTokenRotation: Rotate only expired tokens * Don't expose getSessionExpiry
This commit is contained in:
		
							parent
							
								
									6277c04caf
								
							
						
					
					
						commit
						75fd019068
					
				|  | @ -20,6 +20,7 @@ import { GrafanaEdition } from '@grafana/data/src/types/config'; | ||||||
| import { BackendSrv as BackendService, BackendSrvRequest, config, FetchError, FetchResponse } from '@grafana/runtime'; | import { BackendSrv as BackendService, BackendSrvRequest, config, FetchError, FetchResponse } from '@grafana/runtime'; | ||||||
| import appEvents from 'app/core/app_events'; | import appEvents from 'app/core/app_events'; | ||||||
| import { getConfig } from 'app/core/config'; | import { getConfig } from 'app/core/config'; | ||||||
|  | import { getSessionExpiry } from 'app/core/utils/auth'; | ||||||
| import { loadUrlToken } from 'app/core/utils/urlToken'; | import { loadUrlToken } from 'app/core/utils/urlToken'; | ||||||
| import { DashboardModel } from 'app/features/dashboard/state'; | import { DashboardModel } from 'app/features/dashboard/state'; | ||||||
| import { DashboardSearchItem } from 'app/features/search/types'; | import { DashboardSearchItem } from 'app/features/search/types'; | ||||||
|  | @ -389,7 +390,12 @@ export class BackendSrv implements BackendService { | ||||||
|                   return throwError(() => error); |                   return throwError(() => error); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let authChecker = config.featureToggles.clientTokenRotation ? this.rotateToken() : this.loginPing(); |                 let authChecker = this.loginPing(); | ||||||
|  | 
 | ||||||
|  |                 const expired = getSessionExpiry() * 1000 < Date.now(); | ||||||
|  |                 if (config.featureToggles.clientTokenRotation && expired) { | ||||||
|  |                   authChecker = this.rotateToken(); | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 return from(authChecker).pipe( |                 return from(authChecker).pipe( | ||||||
|                   catchError((err) => { |                   catchError((err) => { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import { extend } from 'lodash'; | ||||||
| 
 | 
 | ||||||
| import { AnalyticsSettings, OrgRole, rangeUtil, WithAccessControlMetadata } from '@grafana/data'; | import { AnalyticsSettings, OrgRole, rangeUtil, WithAccessControlMetadata } from '@grafana/data'; | ||||||
| import { featureEnabled, getBackendSrv } from '@grafana/runtime'; | import { featureEnabled, getBackendSrv } from '@grafana/runtime'; | ||||||
|  | import { getSessionExpiry } from 'app/core/utils/auth'; | ||||||
| import { AccessControlAction, UserPermission } from 'app/types'; | import { AccessControlAction, UserPermission } from 'app/types'; | ||||||
| import { CurrentUserInternal } from 'app/types/config'; | import { CurrentUserInternal } from 'app/types/config'; | ||||||
| 
 | 
 | ||||||
|  | @ -209,7 +210,7 @@ export class ContextSrv { | ||||||
|     // check if we can schedula the token rotation job
 |     // check if we can schedula the token rotation job
 | ||||||
|     if (this.canScheduleRotation()) { |     if (this.canScheduleRotation()) { | ||||||
|       // get the time token is going to expire
 |       // get the time token is going to expire
 | ||||||
|       let expires = this.getSessionExpiry(); |       let expires = getSessionExpiry(); | ||||||
| 
 | 
 | ||||||
|       // because this job is scheduled for every tab we have open that shares a session we try
 |       // because this job is scheduled for every tab we have open that shares a session we try
 | ||||||
|       // to distribute the scheduling of the job. For now this can be between 1 and 20 seconds
 |       // to distribute the scheduling of the job. For now this can be between 1 and 20 seconds
 | ||||||
|  | @ -222,7 +223,7 @@ export class ContextSrv { | ||||||
|       this.tokenRotationJobId = setTimeout(() => { |       this.tokenRotationJobId = setTimeout(() => { | ||||||
|         // if we have a new expiry time from the expiry cookie another tab have already performed the rotation
 |         // if we have a new expiry time from the expiry cookie another tab have already performed the rotation
 | ||||||
|         // so the only thing we need to do is reschedule the job and exit
 |         // so the only thing we need to do is reschedule the job and exit
 | ||||||
|         if (this.getSessionExpiry() > expires) { |         if (getSessionExpiry() > expires) { | ||||||
|           this.scheduleTokenRotationJob(); |           this.scheduleTokenRotationJob(); | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|  | @ -247,7 +248,7 @@ export class ContextSrv { | ||||||
|     // from an older version of grafana, we never schedule the job and the fallback logic
 |     // from an older version of grafana, we never schedule the job and the fallback logic
 | ||||||
|     // in backend_srv will take care of rotations until first rotation has been made and
 |     // in backend_srv will take care of rotations until first rotation has been made and
 | ||||||
|     // page has been reloaded.
 |     // page has been reloaded.
 | ||||||
|     if (this.getSessionExpiry() === 0) { |     if (getSessionExpiry() === 0) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -278,20 +279,6 @@ export class ContextSrv { | ||||||
|         console.error(e); |         console.error(e); | ||||||
|       }); |       }); | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   private getSessionExpiry() { |  | ||||||
|     const expiryCookie = document.cookie.split('; ').find((row) => row.startsWith('grafana_session_expiry=')); |  | ||||||
|     if (!expiryCookie) { |  | ||||||
|       return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let expiresStr = expiryCookie.split('=').at(1); |  | ||||||
|     if (!expiresStr) { |  | ||||||
|       return 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return parseInt(expiresStr, 10); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| let contextSrv = new ContextSrv(); | let contextSrv = new ContextSrv(); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | export function getSessionExpiry() { | ||||||
|  |   const expiryCookie = document.cookie.split('; ').find((row) => row.startsWith('grafana_session_expiry=')); | ||||||
|  |   if (!expiryCookie) { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let expiresStr = expiryCookie.split('=').at(1); | ||||||
|  |   if (!expiresStr) { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return parseInt(expiresStr, 10); | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue