ClientTokenRotation: Rotate only expired tokens (#74010)

* ClientTokenRotation: Rotate only expired tokens

* Don't expose getSessionExpiry
This commit is contained in:
Alexander Zobnin 2023-08-30 14:43:52 +03:00 committed by GitHub
parent 6277c04caf
commit 75fd019068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 18 deletions

View File

@ -20,6 +20,7 @@ import { GrafanaEdition } from '@grafana/data/src/types/config';
import { BackendSrv as BackendService, BackendSrvRequest, config, FetchError, FetchResponse } from '@grafana/runtime';
import appEvents from 'app/core/app_events';
import { getConfig } from 'app/core/config';
import { getSessionExpiry } from 'app/core/utils/auth';
import { loadUrlToken } from 'app/core/utils/urlToken';
import { DashboardModel } from 'app/features/dashboard/state';
import { DashboardSearchItem } from 'app/features/search/types';
@ -389,7 +390,12 @@ export class BackendSrv implements BackendService {
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(
catchError((err) => {

View File

@ -2,6 +2,7 @@ import { extend } from 'lodash';
import { AnalyticsSettings, OrgRole, rangeUtil, WithAccessControlMetadata } from '@grafana/data';
import { featureEnabled, getBackendSrv } from '@grafana/runtime';
import { getSessionExpiry } from 'app/core/utils/auth';
import { AccessControlAction, UserPermission } from 'app/types';
import { CurrentUserInternal } from 'app/types/config';
@ -209,7 +210,7 @@ export class ContextSrv {
// check if we can schedula the token rotation job
if (this.canScheduleRotation()) {
// 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
// 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(() => {
// 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
if (this.getSessionExpiry() > expires) {
if (getSessionExpiry() > expires) {
this.scheduleTokenRotationJob();
return;
}
@ -247,7 +248,7 @@ export class ContextSrv {
// 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
// page has been reloaded.
if (this.getSessionExpiry() === 0) {
if (getSessionExpiry() === 0) {
return false;
}
@ -278,20 +279,6 @@ export class ContextSrv {
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();

View File

@ -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);
}