From 9d307a3c97eff585962dd633200cc3c8b2f4b25b Mon Sep 17 00:00:00 2001 From: Guillaume Chervet Date: Sun, 18 Feb 2024 15:03:48 +0100 Subject: [PATCH] fix(oidc): parse token with many _ or - --- .../src/utils/__tests__/tokens.spec.ts | 27 +++-- .../src/utils/tokens.ts | 2 +- packages/oidc-client/src/parseTokens.spec.ts | 101 ++++++++++-------- packages/oidc-client/src/parseTokens.ts | 2 +- 4 files changed, 79 insertions(+), 53 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 d4853fd9d..b35b6ba6d 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 @@ -30,12 +30,9 @@ describe('tokens', () => { }); }); - describe('extractTokenPayload', () => { - - it('parseJwtShouldExtractData', async () => { - const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" - const result = parseJwt(claimsPart); - expect(result).toStrictEqual({ + describe.each([ + ["eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0", + { "session_state": "75cc5ed2-df2d-4569-bfc5-18a98e68be11", "scope": "openid email profile", "email_verified": true, @@ -43,8 +40,24 @@ describe('tokens', () => { "preferred_username": "testingcharacters@inventedmail.com", "given_name": "ƴǢÁìÇ", "family_name": "小名-ホルヘ" - }); + }], + [ + "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCI_IjoiYWE_In0", + { + "?": "aa?", + "iat": 1516239022, + "name": "John Doe", + "sub": "1234567890", + } + ] + ])('parseJwtShouldExtractData', (claimsPart, expectedResult) => { + it('should parseJwtShouldExtractData ', async () => { + const result = parseJwt(claimsPart); + expect(expectedResult).toStrictEqual(result); }); + }); + + describe('extractTokenPayload', () => { it('can extract token payload', () => { const result = extractTokenPayload( diff --git a/packages/oidc-client-service-worker/src/utils/tokens.ts b/packages/oidc-client-service-worker/src/utils/tokens.ts index 90c8ff693..e21933e55 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'; export const parseJwt = (payload: string) => { return JSON.parse( - b64DecodeUnicode(payload.replace(/-/g, '+').replace(/_/g, '/')), + b64DecodeUnicode(payload.replaceAll(/-/g, '+').replaceAll(/_/g, '/')), ); } function b64DecodeUnicode(str: string) { diff --git a/packages/oidc-client/src/parseTokens.spec.ts b/packages/oidc-client/src/parseTokens.spec.ts index 4d2c2e169..380f05d90 100644 --- a/packages/oidc-client/src/parseTokens.spec.ts +++ b/packages/oidc-client/src/parseTokens.spec.ts @@ -32,54 +32,67 @@ describe('ParseTokens test Suite', () => { }); }); - it('parseJwtShouldExtractData', async () => { - const claimsPart = "eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0" - const result = parseJwt(claimsPart); - 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": "小名-ホルヘ" + describe.each([ + ["eyJzZXNzaW9uX3N0YXRlIjoiNzVjYzVlZDItZGYyZC00NTY5LWJmYzUtMThhOThlNjhiZTExIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoixrTHosOBw6zDhyDlsI_lkI0t44Ob44Or44OYIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdGluZ2NoYXJhY3RlcnNAaW52ZW50ZWRtYWlsLmNvbSIsImdpdmVuX25hbWUiOiLGtMeiw4HDrMOHIiwiZmFtaWx5X25hbWUiOiLlsI_lkI0t44Ob44Or44OYIn0", + { + "session_state": "75cc5ed2-df2d-4569-bfc5-18a98e68be11", + "scope": "openid email profile", + "email_verified": true, + "name": "ƴǢÁìÇ 小名-ホルヘ", + "preferred_username": "testingcharacters@inventedmail.com", + "given_name": "ƴǢÁìÇ", + "family_name": "小名-ホルヘ" + }], + [ + "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCI_IjoiYWE_In0", + { + "?": "aa?", + "iat": 1516239022, + "name": "John Doe", + "sub": "1234567890", + } + ] + ])('parseJwtShouldExtractData', (claimsPart, expectedResult) => { + it('should parseJwtShouldExtractData ', async () => { + const result = parseJwt(claimsPart); + expect(expectedResult).toStrictEqual(result); }); }); - - 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"; - const access_token ="opqavdgHEYx8nhCdc3iByd1HD0jiYN30LevhJy4f5wIavINXKdh4lQ9C3kA49QF0OH0XeA02"; - describe.each([ - [{ - "access_token":access_token, - "token_type":"Bearer", - "expires_in":"900", // Here a string instead of a number - "refresh_token":refresh_token, - "id_token":id_token - }], - [{ - "access_token":access_token, - "token_type":"Bearer", - "expires_in":900, - "refresh_token":refresh_token, - "id_token":id_token - }], - [{ - "access_token":access_token, - "token_type":"Bearer", - "expires_in":900, - "expiresAt": 1609987454, // Here expiresAt that come from Service Worker - "refresh_token":refresh_token, - "id_token":id_token - }], - ])('getValidTokenAsync', (tokens) => { - it('should parseOriginalTokens', async () => { - // @ts-ignore - const result = parseOriginalTokens(tokens); - expect(typeof result.issuedAt).toEqual("number"); + 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"; + const access_token = "opqavdgHEYx8nhCdc3iByd1HD0jiYN30LevhJy4f5wIavINXKdh4lQ9C3kA49QF0OH0XeA02"; + describe.each([ + [{ + "access_token": access_token, + "token_type": "Bearer", + "expires_in": "900", // Here a string instead of a number + "refresh_token": refresh_token, + "id_token": id_token + }], + [{ + "access_token": access_token, + "token_type": "Bearer", + "expires_in": 900, + "refresh_token": refresh_token, + "id_token": id_token + }], + [{ + "access_token": access_token, + "token_type": "Bearer", + "expires_in": 900, + "expiresAt": 1609987454, // Here expiresAt that come from Service Worker + "refresh_token": refresh_token, + "id_token": id_token + }], + ])('getValidTokenAsync', (tokens) => { + it('should parseOriginalTokens', async () => { + // @ts-ignore + const result = parseOriginalTokens(tokens); + expect(typeof result.issuedAt).toEqual("number"); + }); }); - }); + const idTokenPayload = {iss: "toto", exp: currentTimeUnixSecond +900, iat: currentTimeUnixSecond -900, nonce: "nonce"}; const oidcServerConfiguration = {issuer:"toto"}; diff --git a/packages/oidc-client/src/parseTokens.ts b/packages/oidc-client/src/parseTokens.ts index 0d745320d..eec9e2ba1 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('')); -export const parseJwt = (payload:string) => JSON.parse(b64DecodeUnicode(payload.replace(/-/g, '+').replace(/_/g, '/'))); +export const parseJwt = (payload:string) => JSON.parse(b64DecodeUnicode(payload.replaceAll(/-/g, '+').replaceAll(/_/g, '/'))); const extractTokenPayload = (token:string) => { try {