diff --git a/src/security/browser.ts b/src/security/browser.ts index 3a0007f8..c723b5f5 100644 --- a/src/security/browser.ts +++ b/src/security/browser.ts @@ -32,7 +32,7 @@ export function randomBytes(count: number): Uint8Array { } export async function digestSha256(payload: string): Promise { - const prepared: ArrayBuffer = new Uint8Array(s2b(payload)); + const prepared = new TextEncoder().encode(payload); const hash = await subtle.digest('SHA-256', prepared); return new Uint8Array(hash); } @@ -85,27 +85,8 @@ export async function signCompactJws(alg: keyof typeof ALGS, privateKey: CryptoK const signature = await subtle.sign( { ...privateKey.algorithm, hash: 'SHA-384' }, privateKey, - s2b(jwtAuthenticatedContent) + new TextEncoder().encode(jwtAuthenticatedContent) ); return `${jwtAuthenticatedContent}.${fromUint8Array(new Uint8Array(signature), true)}` } - -function s2b ( s: string ) { - const b = new Uint8Array(s.length); - const bs = utf8ToBinaryString(s) - for ( var i = 0; i < bs.length; i++ ) b[i] = bs.charCodeAt(i); - return b; -} - -// UTF-8 to Binary String -// Source: https://coolaj86.com/articles/sign-jwt-webcrypto-vanilla-js/ -// Because JavaScript has a strange relationship with strings -// https://coolaj86.com/articles/base64-unicode-utf-8-javascript-and-you/ -function utf8ToBinaryString(str: string) { - // replaces any uri escape sequence, such as %0A, with binary escape, such as 0x0A - return encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(_, p1) { - return String.fromCharCode(parseInt(p1, 16)); - }); -} - diff --git a/src/smart.ts b/src/smart.ts index 7db8cbc2..f54a724c 100644 --- a/src/smart.ts +++ b/src/smart.ts @@ -328,8 +328,8 @@ export async function authorize( if (shouldIncludeChallenge(extensions.codeChallengeMethods.includes('S256'), pkceMode)) { let codes = await env.security.generatePKCEChallenge() Object.assign(state, codes); - await storage.set(stateKey, state); // note that the challenge is ALREADY encoded properly - redirectParams.push("code_challenge=" + state.codeChallenge); + await storage.set(stateKey, state); + redirectParams.push("code_challenge=" + state.codeChallenge);// note that the challenge is ALREADY encoded properly redirectParams.push("code_challenge_method=S256"); } @@ -438,7 +438,8 @@ export function onMessage(e: MessageEvent) { /** * The ready function should only be called on the page that represents * the redirectUri. We typically land there after a redirect from the - * authorization server.. + * authorization server, but this code will also be executed upon subsequent + * navigation or page refresh. */ export async function ready(env: fhirclient.Adapter, options: fhirclient.ReadyOptions = {}): Promise {