Skip to content

Commit

Permalink
Error message regarding insecure context #183
Browse files Browse the repository at this point in the history
  • Loading branch information
vlad-ignatov committed Aug 26, 2024
1 parent 795ae9c commit 8b6d825
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
28 changes: 23 additions & 5 deletions src/security/browser.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import { encodeURL, fromUint8Array } from "js-base64"
import { fhirclient } from "../types"
import { fhirclient } from "../types"


const crypto: Crypto = typeof globalThis === "object" && globalThis.crypto ?
globalThis.crypto :
require("isomorphic-webcrypto").default;

const subtle: SubtleCrypto = crypto.subtle
const subtle = () => {
if (!window.isSecureContext) {
throw new Error(
"Some of the required subtle crypto functionality is not " +
"available unless you run this app in secure context (using " +
"HTTPS or running locally). See " +
"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts"
)
}
if (!crypto.subtle) {
throw new Error(
"Some of the required subtle crypto functionality is not " +
"available in the current environment (no crypto.subtle)"
)
}
return crypto.subtle
}


interface PkcePair {
codeChallenge: string
Expand Down Expand Up @@ -33,7 +51,7 @@ export function randomBytes(count: number): Uint8Array {

export async function digestSha256(payload: string): Promise<Uint8Array> {
const prepared = new TextEncoder().encode(payload);
const hash = await subtle.digest('SHA-256', prepared);
const hash = await subtle().digest('SHA-256', prepared);
return new Uint8Array(hash);
}

Expand Down Expand Up @@ -64,7 +82,7 @@ export async function importJWK(jwk: fhirclient.JWK): Promise<CryptoKey> {
}

try {
return await subtle.importKey(
return await subtle().importKey(
"jwk",
jwk,
ALGS[jwk.alg],
Expand All @@ -82,7 +100,7 @@ export async function signCompactJws(alg: keyof typeof ALGS, privateKey: CryptoK
const jwtPayload = JSON.stringify(payload);
const jwtAuthenticatedContent = `${encodeURL(jwtHeader)}.${encodeURL(jwtPayload)}`;

const signature = await subtle.sign(
const signature = await subtle().sign(
{ ...privateKey.algorithm, hash: 'SHA-384' },
privateKey,
new TextEncoder().encode(jwtAuthenticatedContent)
Expand Down
2 changes: 1 addition & 1 deletion src/smart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ function shouldIncludeChallenge(S256supported: boolean, pkceMode?: string) {
}
if (pkceMode === "required") {
if (!S256supported) {
throw new Error("Required PKCE code challenge method (`S256`) was not found.");
throw new Error("Required PKCE code challenge method (`S256`) was not found in the server's codeChallengeMethods declaration.");
}
return true;
}
Expand Down
47 changes: 33 additions & 14 deletions test/browser_security.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,45 +41,64 @@
Promise.resolve()

.then(function() {
console.info("Inspecting window.FHIR")
console.log(FHIR)
console.info("Inspecting window.FHIR and global crypto")
console.log(FHIR, crypto)
})

.then(function() {
console.info("Testing window.isSecureContext")
return window.isSecureContext
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.generatePKCEChallenge")
return FHIR.utils.security.generatePKCEChallenge()
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.importKey with RS384")
return FHIR.utils.security.importKey(JWK_RS384)
console.info("Testing window.FHIR.utils.security.importJWK with RS384")
return FHIR.utils.security.importJWK(JWK_RS384)
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.importKey with ES384")
return FHIR.utils.security.importKey(JWK_ES384)
console.info("Testing window.FHIR.utils.security.importJWK with ES384")
return FHIR.utils.security.importJWK(JWK_ES384)
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.generateKey with RS384")
return FHIR.utils.security.generateKey("RS384")
console.info("Testing window.FHIR.utils.security.randomBytes")
return FHIR.utils.security.randomBytes(10)
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.generateKey with ES384")
return FHIR.utils.security.generateKey("ES384")
console.info("Testing window.FHIR.utils.security.digestSha256")
return FHIR.utils.security.digestSha256("whatever")
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.signCompactJws with RS384")
return FHIR.utils.security.generateKey('RS384')
.then(function(key) { return FHIR.utils.security.signCompactJws(key.privateKey, {'jwku': 'sure'}, {iss: "issuer"}) })
return FHIR.utils.security.importJWK(JWK_RS384)
.then(function(key) {
return FHIR.utils.security.signCompactJws(
"RS384",
key,
{ jwku: 'sure' },
{ iss: "issuer" }
)
})
}).then(console.log, console.error)

.then(function() {
console.info("Testing window.FHIR.utils.security.signCompactJws with ES384")
return FHIR.utils.security.generateKey('ES384')
.then(function(key) { return FHIR.utils.security.signCompactJws(key.privateKey, {'jwku': 'sure'}, {iss: "issuer"}) })
return FHIR.utils.security.importJWK(JWK_ES384)
.then(function(key) {
return FHIR.utils.security.signCompactJws(
"ES384",
key,
{ jwku: 'sure' },
{ iss: "issuer" }
)
})
}).then(console.log, console.error)
})();
</script>
Expand Down

0 comments on commit 8b6d825

Please sign in to comment.