diff --git a/server/auth/types/openid/helper.test.ts b/server/auth/types/openid/helper.test.ts index e68e8b315..539199ec7 100644 --- a/server/auth/types/openid/helper.test.ts +++ b/server/auth/types/openid/helper.test.ts @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -import { composeLogoutUrl, getRootUrl } from './helper'; +import { composeLogoutUrl, getExpirationDate, getRootUrl } from './helper'; describe('test OIDC helper utility', () => { test('test compose logout url', () => { @@ -137,4 +137,13 @@ describe('test OIDC helper utility', () => { expect('http://server.com:80').toEqual(getRootUrl(config, core, request)); }); + + test('extract expiration time from jwt token', () => { + expect(1658582700000).toEqual( + getExpirationDate({ + idToken: + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imtld2lRcTlqaUM4NEN2U3NKWU9CLU42QThXRkxTVjIwTWIteTdJbFdEU1EifQ.eyJpc3MiOiJodHRwczovL2dpdGxhYi5jb20iLCJzdWIiOiI5ODc5ODQ1IiwiYXVkIjoiOTkzZWM3MTA3YjNlZmJiZTRkZDdjYmE1NDRmMDU4YTMyMmIwN2M0ZmQ5MTljMzdkMGM4ODQ5MjljYzVkM2U5NiIsImV4cCI6MTY1ODU4MjcwMCwiaWF0IjoxNjU4NTgyNTgwLCJhdXRoX3RpbWUiOjE2NTgzMjU1ODgsInN1Yl9sZWdhY3kiOiIxYWNiYzI5ZGFkOWViMGI0MjM3YTVhMTEzNzg2M2E4ZDNlNDFkOGRjOWJhMzJlYzFkOGIwMWJjODY5NzczMGM0IiwiZ3JvdXBzX2RpcmVjdCI6WyJlb3NmaW50ZWsiLCJlNDM4NyJdfQ.CVgOC3K4e95cOY2akmGBWJcSGjkyO517N_784ob2Tj3aeMpyk-O_OsbUhmt_Fu_XvqSk5dY02c1a8Ngav8_7MOsHb6MovYQsnIE0ddxtJSY2uswOWX53cE2SPU-G-s8vVLX-MfIG1_Mfg2cYE-eL2nRlSSrMug9IXiiWGoQuS0vrjuomgoq3gZnNCM-Yn-2TI3YZSsluyaODMnW2yVCeu8ZMJp6ZbCMBwAwq-dMVENF9jEHJqtRgOOP1OXJ9scapS14IHXaUrHkxlyRDRYKMZ727hQs_aMHZAlLyycz_9xI2RgZ4dTOldbXZeBUrOZvwe5ZMdok3a9LYr91clFu-pA24zHFUeFqjcVRMxhYZAD4wYdG26pYk1Otk9auvSaPd6Rsk4fK_tA7hVWCM1NMO1lhQ0RzLl4MRKx4NJrjm4jlodUGx3k_js2YtXYdKGNwWcm2ESTUgPdL1dQus3ll5Lr_wt5uY3GYjCtDA6BcZWhRewgWdmJ8hPx8JNuz3Sw2bDxjgmZqCQ4I4WMa-HncAshfZY-mLlWOkxN9kzHSXIZGa-No6_u9JZwfKdZXkK9UJMAuY4SH5PcvJitVAVDPg6EQa1Ne8AkVFOBfPF0_S3QZnW4D7kRNhs0pr-eyBb3cUACLPjS4maCccQ6MSBZ9RYy3l0wgitRv2SVIBvBH0eN4', + }) + ); + }); }); diff --git a/server/auth/types/openid/helper.ts b/server/auth/types/openid/helper.ts index dfc948ba3..a420b442e 100644 --- a/server/auth/types/openid/helper.ts +++ b/server/auth/types/openid/helper.ts @@ -120,3 +120,19 @@ export interface TokenResponse { refreshToken?: string; expiresIn?: number; } + +export function getExpirationDate(tokenResponse: TokenResponse | undefined) { + if (!tokenResponse) { + throw new Error('Invalid token'); + } else if (tokenResponse.idToken) { + const idToken = tokenResponse.idToken; + const parts = idToken.split('.'); + if (parts.length !== 3) { + throw new Error('Invalid token'); + } + const claim = JSON.parse(Buffer.from(parts[1], 'base64').toString()); + return claim.exp * 1000; + } else { + return Date.now() + tokenResponse.expiresIn! * 1000; + } +} diff --git a/server/auth/types/openid/openid_auth.ts b/server/auth/types/openid/openid_auth.ts index 7ce4b3401..1fb0f3d00 100644 --- a/server/auth/types/openid/openid_auth.ts +++ b/server/auth/types/openid/openid_auth.ts @@ -35,6 +35,7 @@ import { OpenIdAuthRoutes } from './routes'; import { AuthenticationType } from '../authentication_type'; import { callTokenEndpoint } from './helper'; import { composeNextUrlQueryParam } from '../../../utils/next_url'; +import { getExpirationDate } from './helper'; export interface OpenIdAuthConfig { authorizationEndpoint?: string; @@ -189,7 +190,7 @@ export class OpenIdAuthentication extends AuthenticationType { cookie.credentials = { authHeaderValue: `Bearer ${refreshTokenResponse.idToken}`, refresh_token: refreshTokenResponse.refreshToken, - expires_at: Date.now() + refreshTokenResponse.expiresIn! * 1000, // expiresIn is in second + expires_at: getExpirationDate(refreshTokenResponse), // expiresIn is in second }; return true; } else { diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index 8f17eae2b..627170f97 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -29,6 +29,7 @@ import { OpenIdAuthConfig } from './openid_auth'; import { SecurityClient } from '../../../backend/opensearch_security_client'; import { getBaseRedirectUrl, callTokenEndpoint, composeLogoutUrl } from './helper'; import { validateNextUrl } from '../../../utils/next_url'; +import { getExpirationDate } from './helper'; export class OpenIdAuthRoutes { private static readonly NONCE_LENGTH: number = 22; @@ -148,7 +149,6 @@ export class OpenIdAuthRoutes { query, this.wreckClient ); - const user = await this.securityClient.authenticateWithHeader( request, this.openIdAuthConfig.authHeaderName as string, @@ -160,7 +160,7 @@ export class OpenIdAuthRoutes { username: user.username, credentials: { authHeaderValue: `Bearer ${tokenResponse.idToken}`, - expires_at: Date.now() + tokenResponse.expiresIn! * 1000, // expiresIn is in second + expires_at: getExpirationDate(tokenResponse), }, authType: 'openid', expiryTime: Date.now() + this.config.session.ttl,