From 645dec2fca9ff49a04b90fcc98f55df1134f28e8 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Thu, 1 Jun 2023 16:49:28 -0300 Subject: [PATCH] Use Web Crypto for signing token requests on web MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO figure out secure context stuff and what the broad-reaching implications are Resolves #1295. TODO what can we use as the statusCode and code — used generic "bad request" --- src/common/lib/client/auth.ts | 8 ++++++-- src/platform/web/lib/util/crypto.ts | 10 ++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common/lib/client/auth.ts b/src/common/lib/client/auth.ts index 0c88bf78e1..a9662858c1 100644 --- a/src/common/lib/client/auth.ts +++ b/src/common/lib/client/auth.ts @@ -129,6 +129,7 @@ class Auth { if (useTokenAuth(options)) { /* Token auth */ if (options.key && !hmac) { + // TODO what is this const msg = 'client-side token request signing not supported'; Logger.logAction(Logger.LOG_ERROR, 'Auth()', msg); throw new Error(msg); @@ -413,6 +414,7 @@ class Auth { callback: StandardCallback ): void; + // TODO where is this called? it's public API but what else? _ensureValidAuthCredentials requestToken( tokenParams: API.Types.TokenParams | StandardCallback | null, authOptions?: any | StandardCallback, @@ -559,6 +561,7 @@ class Auth { }; } else if (authOptions.key) { Logger.logAction(Logger.LOG_MINOR, 'Auth.requestToken()', 'using token auth with client-side signing'); + // TODO what is this? tokenRequestCallback = (params: any, cb: Function) => { this.createTokenRequest(params, authOptions, cb); }; @@ -745,6 +748,7 @@ class Auth { * * @param callback */ + // TODO who calls this? it's public API but other than that I don't think called anywhere else except requestToken createTokenRequest(tokenParams: API.Types.TokenParams | null, authOptions: any, callback: Function) { /* shuffle and normalise arguments as necessary */ if (typeof tokenParams == 'function' && !callback) { @@ -829,8 +833,8 @@ class Auth { callback(null, request); }) .catch((err) => { - Logger.logAction(Logger.LOG_ERROR, 'Auth.getTokenRequest()', 'failed to sign request: ' + err.message); - callback(ErrorInfo.fromValues(err)); + Logger.logAction(Logger.LOG_ERROR, 'Auth.getTokenRequest()', 'failed to sign request: ' + err); + callback(new ErrorInfo('Failed to sign token request: ' + err.message, 40000, 400)); }); }); } diff --git a/src/platform/web/lib/util/crypto.ts b/src/platform/web/lib/util/crypto.ts index 61c8cd0e9a..bd7736c7a5 100644 --- a/src/platform/web/lib/util/crypto.ts +++ b/src/platform/web/lib/util/crypto.ts @@ -6,7 +6,6 @@ import ICipher from '../../../../common/types/ICipher'; import { CryptoDataTypes } from '../../../../common/types/cryptoDataTypes'; import BufferUtils, { Bufferlike, Output as BufferUtilsOutput } from './bufferutils'; import { IPlatformConfig } from 'common/types/IPlatformConfig'; -import HmacSHA256 from 'crypto-js/build/hmac-sha256'; // The type to which ./msgpack.ts deserializes elements of the `bin` or `ext` type type MessagePackBinaryType = ArrayBuffer; @@ -212,12 +211,11 @@ var CryptoFactory = function (config: IPlatformConfig, bufferUtils: typeof Buffe } static async hmacSha256(message: InputPlaintext, key: API.Types.CipherKey): Promise { - const messageWordArray = bufferUtils.toWordArray(message); - const keyWordArray = bufferUtils.toWordArray(key); + // TODO what if crypto.subtle not available + const cryptoKey = await crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']); + const digest = await crypto.subtle.sign('HMAC', cryptoKey, message); - const digest = HmacSHA256(messageWordArray, keyWordArray); - - return bufferUtils.toArrayBuffer(digest); + return digest; } }