From 2a4f57c01b0b3f78c26207468d65893ba0e09da1 Mon Sep 17 00:00:00 2001 From: Guillaume Chervet Date: Thu, 25 Jan 2024 18:11:14 +0100 Subject: [PATCH 1/4] fix(oidc): parseJwt fails for some JWT because of wrong use of replace (alpha) --- packages/oidc-client-service-worker/src/utils/tokens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/oidc-client-service-worker/src/utils/tokens.ts b/packages/oidc-client-service-worker/src/utils/tokens.ts index 80a9157db..be88dd74e 100644 --- a/packages/oidc-client-service-worker/src/utils/tokens.ts +++ b/packages/oidc-client-service-worker/src/utils/tokens.ts @@ -12,7 +12,7 @@ import { countLetter } from './strings'; function parseJwt(token: string) { return JSON.parse( - b64DecodeUnicode(token.split('.')[1].replace('-', '+').replace('_', '/')), + b64DecodeUnicode(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')), ); } function b64DecodeUnicode(str: string) { From b20d359282cd3fbcf66db7c7d93886e252dccd4f Mon Sep 17 00:00:00 2001 From: Guillaume Chervet Date: Thu, 25 Jan 2024 18:13:43 +0100 Subject: [PATCH 2/4] fix2 (alpha) --- packages/oidc-client/src/parseTokens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/oidc-client/src/parseTokens.ts b/packages/oidc-client/src/parseTokens.ts index b1e6f83df..f6765fc31 100644 --- a/packages/oidc-client/src/parseTokens.ts +++ b/packages/oidc-client/src/parseTokens.ts @@ -2,7 +2,7 @@ import {sleepAsync} from './initWorker.js'; const b64DecodeUnicode = (str) => decodeURIComponent(Array.prototype.map.call(atob(str), (c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')); -const parseJwt = (token) => JSON.parse(b64DecodeUnicode(token.split('.')[1].replace('-', '+').replace('_', '/'))); +const parseJwt = (token) => JSON.parse(b64DecodeUnicode(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))); const extractTokenPayload = (token) => { try { From ed10922151e1595b44bb2b5b847b23ef75b46806 Mon Sep 17 00:00:00 2001 From: Guillaume Chervet Date: Thu, 25 Jan 2024 20:54:33 +0100 Subject: [PATCH 3/4] add tests --- .../src/utils/__tests__/tokens.spec.ts | 9 ++++++++- packages/oidc-client-service-worker/src/utils/tokens.ts | 6 +++--- packages/oidc-client/src/parseTokens.spec.ts | 8 +++++++- packages/oidc-client/src/parseTokens.ts | 6 +++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts b/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts index 41435f4b2..2108b3cd3 100644 --- a/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts +++ b/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { OidcServerConfiguration } from '../../types'; -import { _hideTokens, extractTokenPayload, isTokensOidcValid, isTokensValid } from '..'; +import {_hideTokens, extractTokenPayload, isTokensOidcValid, isTokensValid, parseJwt} from '..'; import { OidcConfigBuilder, OidcServerConfigBuilder, TokenBuilder } from './testHelper'; describe('tokens', () => { @@ -31,6 +31,13 @@ describe('tokens', () => { }); describe('extractTokenPayload', () => { + + it('parseJwtShouldExtractData', async () => { + const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" + const result = parseJwt(claimsPart); + expect(result!=null).toBe(true); + }); + it('can extract token payload', () => { const result = extractTokenPayload( 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', diff --git a/packages/oidc-client-service-worker/src/utils/tokens.ts b/packages/oidc-client-service-worker/src/utils/tokens.ts index be88dd74e..190416262 100644 --- a/packages/oidc-client-service-worker/src/utils/tokens.ts +++ b/packages/oidc-client-service-worker/src/utils/tokens.ts @@ -10,9 +10,9 @@ import { } from '../types'; import { countLetter } from './strings'; -function parseJwt(token: string) { +export const parseJwt = (payload: string) => { return JSON.parse( - b64DecodeUnicode(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')), + b64DecodeUnicode(payload.replace(/-/g, '+').replace(/_/g, '/')), ); } function b64DecodeUnicode(str: string) { @@ -51,7 +51,7 @@ const extractTokenPayload = (token?: string) => { return null; } if (countLetter(token, '.') === 2) { - return parseJwt(token); + return parseJwt(token.split('.')[1]); } else { return null; } diff --git a/packages/oidc-client/src/parseTokens.spec.ts b/packages/oidc-client/src/parseTokens.spec.ts index 070bbeea6..2f2b8797a 100644 --- a/packages/oidc-client/src/parseTokens.spec.ts +++ b/packages/oidc-client/src/parseTokens.spec.ts @@ -1,6 +1,6 @@ import { describe, expect,it } from 'vitest'; -import {getValidTokenAsync, isTokensOidcValid, parseOriginalTokens} from "./parseTokens"; +import { getValidTokenAsync, isTokensOidcValid, parseJwt, parseOriginalTokens} from "./parseTokens"; describe('ParseTokens test Suite', () => { const currentTimeUnixSecond = new Date().getTime() / 1000; @@ -25,6 +25,12 @@ describe('ParseTokens test Suite', () => { }); }); + it('parseJwtShouldExtractData', async () => { + const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" + const result = parseJwt(claimsPart); + expect(result!=null).toBe(true); + }); + const id_token ="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjUwNWZkODljLTM4YzktNGI2Mi04ZjQ3LWI4MGQ0ZTNhYjYxNSJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MCIsInN1YiI6ImFkbWluIiwiYXVkIjoiM2FTbk5XUGxZQWQwOGVES3c1UUNpSWVMcWpIdHkxTTVzSGFzcDJDZWREcWYzbmJkZm8xUFo1cXhmbWoyaFhkUyIsImV4cCI6MTY5MDk4NzQ1NCwiYXV0aF90aW1lIjoxNjkwOTg2NTUxLCJpYXQiOjE2OTA5ODY1NTQsImFjciI6IjAiLCJhenAiOiIzYVNuTldQbFlBZDA4ZURLdzVRQ2lJZUxxakh0eTFNNXNIYXNwMkNlZERxZjNuYmRmbzFQWjVxeGZtajJoWGRTIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGdyb3VwcyBvZmZsaW5lX2FjY2VzcyIsIm5iZiI6MTY5MDk4NjU1NCwianRpIjoiNjMiLCJub25jZSI6ImNpQkVVOTdaVmRWVSIsImdyb3VwcyI6WyJhZG1pbiJdLCJuYW1lIjoiQWRtaW5pc3RyYXRvciIsInVwZGF0ZWRfYXQiOjE2OTA5ODY1NDV9.2MUdtQR_QtzDY9BTMctG8C4uvg92DgMIUUoJed2cI7WTd5_VEPFW87esDQLw4snVdAJM1_Wf3wB88B2MXFDMCnMTNn0TMnzetRDiG3xlr2LL-geL5SNgwD0Y6RPK_aITjrC9uiQCTj3LPEENrBulNRZPURwaVon9WUVNuuBmMTKd7QKEuFN0zYDoRs0HnXo6WKnFy1rldLGh_JpA3PBUuXt4VMjfGQ7yYEuNn7MkFVDX6OnTffR8jTQp74hREvuRLFjYxfgfgu547X7yIcboOl81D0ZQlP-gfvBOeypZolRLScuqAA3fHBYvE0vCtOM6ObekfeeTDfms75csMLUuZtTR07x32xYC8vdoFsY0sRpMByTqlhsae9VX_rETJ7PIWEfruojzcj47WN9dG0K3pdPiJHEwZ1CKgZfU_cY0gtuAGaIcIjKL0txXCevaiIiIsrgSU_HTjNVybp4WHSAs3h6x0XLz4_91luCylsaoMQbwKOQNwAfr2L74jF6DOg-8DIPb-WClRQzaQtrkx_iv6FtqCB3ogFoZwi6xljdYUc2EHUmoAo-LXal-QAgUXGGzfFU2YOpxV3RyAbMGPm7PfkMVzDsDJwORJNhh38QQ6o88GgNnV28BT-d2G0n7okc0QC6o2IW0jpyCrI6v0hWOBUX2EqiJ5Wao-4LYZfCaRgU"; const refresh_token ="DEsqDca7nDGSgT6tJPkCwbPy98B8VOC4AA55lOPs03G3hqhZ8WH08REBcwTZg1s0jZyVoA3iCXzm4PPJ096gjV7ZKYyN8vnFKw6P6KLV3tUI6mWFaSROoh1LipThFrkS"; diff --git a/packages/oidc-client/src/parseTokens.ts b/packages/oidc-client/src/parseTokens.ts index f6765fc31..0df18cb16 100644 --- a/packages/oidc-client/src/parseTokens.ts +++ b/packages/oidc-client/src/parseTokens.ts @@ -2,15 +2,15 @@ import {sleepAsync} from './initWorker.js'; const b64DecodeUnicode = (str) => decodeURIComponent(Array.prototype.map.call(atob(str), (c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')); -const parseJwt = (token) => JSON.parse(b64DecodeUnicode(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))); +export const parseJwt = (payload:string) => JSON.parse(b64DecodeUnicode(payload.replace(/-/g, '+').replace(/_/g, '/'))); -const extractTokenPayload = (token) => { +const extractTokenPayload = (token:string) => { try { if (!token) { return null; } if (countLetter(token, '.') === 2) { - return parseJwt(token); + return parseJwt(token.split('.')[1]); } else { return null; } From d38829ee601f75a9d624e02d809c1598509392e7 Mon Sep 17 00:00:00 2001 From: Guillaume Chervet Date: Thu, 25 Jan 2024 20:57:12 +0100 Subject: [PATCH 4/4] better --- .../src/utils/__tests__/tokens.spec.ts | 10 +++++++++- packages/oidc-client/src/parseTokens.spec.ts | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts b/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts index 2108b3cd3..b8559154b 100644 --- a/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts +++ b/packages/oidc-client-service-worker/src/utils/__tests__/tokens.spec.ts @@ -35,7 +35,15 @@ describe('tokens', () => { it('parseJwtShouldExtractData', async () => { const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" const result = parseJwt(claimsPart); - expect(result!=null).toBe(true); + expect(result).toStrictEqual({ + "session_state": "75cc5ed2-df2d-4569-bfc5-18a98e68be11", + "scope": "openid email profile", + "email_verified": true, + "name": "ƴǢÁìÇ 小名-ホルヘ", + "preferred_username": "testingcharacters@inventedmail.com", + "given_name": "ƴǢÁìÇ", + "family_name": "小名-ホルヘ" + }); }); it('can extract token payload', () => { diff --git a/packages/oidc-client/src/parseTokens.spec.ts b/packages/oidc-client/src/parseTokens.spec.ts index 2f2b8797a..e520d7b4a 100644 --- a/packages/oidc-client/src/parseTokens.spec.ts +++ b/packages/oidc-client/src/parseTokens.spec.ts @@ -28,7 +28,15 @@ describe('ParseTokens test Suite', () => { it('parseJwtShouldExtractData', async () => { const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" const result = parseJwt(claimsPart); - expect(result!=null).toBe(true); + expect(result).toStrictEqual({ + "session_state": "75cc5ed2-df2d-4569-bfc5-18a98e68be11", + "scope": "openid email profile", + "email_verified": true, + "name": "ƴǢÁìÇ 小名-ホルヘ", + "preferred_username": "testingcharacters@inventedmail.com", + "given_name": "ƴǢÁìÇ", + "family_name": "小名-ホルヘ" + }); });