From 185e9cfa5562135044595d67adc701a0d6bd30ef Mon Sep 17 00:00:00 2001 From: David Plugge <59972093+david-plugge@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:17:51 +0200 Subject: [PATCH] fix decodeBase64url (#488) * fix decodeBase64url * update pnpm version * add changeset --- .changeset/lemon-tigers-protect.md | 5 +++ .github/workflows/docs.yml | 2 +- packages/shared/src/utils/cookies.ts | 48 +++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 .changeset/lemon-tigers-protect.md diff --git a/.changeset/lemon-tigers-protect.md b/.changeset/lemon-tigers-protect.md new file mode 100644 index 00000000..45570011 --- /dev/null +++ b/.changeset/lemon-tigers-protect.md @@ -0,0 +1,5 @@ +--- +'@supabase/auth-helpers-shared': patch +--- + +fix decodeBase64url diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4b14c5af..fe841844 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,7 +21,7 @@ jobs: - uses: pnpm/action-setup@v2.2.3 with: - version: 7.13.4 + version: 8.1.0 - name: Set up Node uses: actions/setup-node@v1 diff --git a/packages/shared/src/utils/cookies.ts b/packages/shared/src/utils/cookies.ts index 7a0d3dca..43db3a69 100644 --- a/packages/shared/src/utils/cookies.ts +++ b/packages/shared/src/utils/cookies.ts @@ -45,8 +45,22 @@ export function isSecureEnvironment(headerHost?: string | string[]) { return true; } -export function decodeBase64URL(value: string): string { - const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +function decodeBase64URL_atob(value: string) { + return decodeURIComponent( + atob(value.replace(/[-]/g, '+').replace(/[_]/g, '/')) + .split('') + .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)) + .join('') + ); +} + +function decodeBase64URL_buffer(value: string) { + return Buffer.from(value, 'base64').toString('utf-8'); +} + +function decodeBase64URL_custom(value: string) { + const key = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; let base64 = ''; let chr1, chr2, chr3; let enc1, enc2, enc3, enc4; @@ -70,10 +84,34 @@ export function decodeBase64URL(value: string): string { base64 = base64 + String.fromCharCode(chr3); } } - return base64; } +export function decodeBase64URL(value: string): string { + try { + // atob is present in all browsers and nodejs >= 16 + // but if it is not it will throw a ReferenceError in which case we can try to use Buffer + // replace are here to convert the Base64-URL into Base64 which is what atob supports + // replace with //g regex acts like replaceAll + // Decoding base64 to UTF8 see https://stackoverflow.com/a/30106551/17622044 + return decodeBase64URL_atob(value); + } catch (e) { + if (e instanceof ReferenceError) { + // running on nodejs < 16 + // Buffer supports Base64-URL transparently + try { + return decodeBase64URL_buffer(value); + } catch (e) { + if (e instanceof ReferenceError) { + return decodeBase64URL_custom(value); + } + throw e; + } + } + throw e; + } +} + export function parseSupabaseCookie( str: string | null | undefined ): Partial | null { @@ -110,7 +148,7 @@ export function parseSupabaseCookie( user: { id: sub, factors: session[4], - ...user, + ...user } }; } catch (err) { @@ -125,6 +163,6 @@ export function stringifySupabaseSession(session: Session): string { session.refresh_token, session.provider_token, session.provider_refresh_token, - session.user.factors, + session.user.factors ]); }