Skip to content

Commit 6f4c696

Browse files
committed
auth: Use webcrypto & Uint8Array instead of NodeJS crypto & Buffer
1 parent 7bcd50a commit 6f4c696

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/OAuth2User.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Copyright 2021 Twitter, Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import crypto from "crypto";
5-
import { buildQueryString, basicAuthHeader } from "./utils";
4+
import { buildQueryString, basicAuthHeader, base64Encode } from "./utils";
65
import { AuthClient, AuthHeader } from "./types";
76
import { RequestOptions, rest } from "./request";
87

@@ -63,13 +62,12 @@ export interface RevokeAccessTokenParams {
6362
client_id: string;
6463
}
6564

66-
function sha256(buffer: string) {
67-
return crypto.createHash("sha256").update(buffer).digest();
65+
async function sha256(buffer: string): Promise<Uint8Array> {
66+
return new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(buffer)));
6867
}
6968

70-
function base64URLEncode(str: Buffer) {
71-
return str
72-
.toString("base64")
69+
function base64URLEncode(str: Uint8Array) {
70+
return base64Encode(str)
7371
.replace(/\+/g, "-")
7472
.replace(/\//g, "_")
7573
.replace(/=/g, "");
@@ -247,9 +245,9 @@ export class OAuth2User implements AuthClient {
247245
if (!callback) throw new Error("callback required");
248246
if (!scopes) throw new Error("scopes required");
249247
if (options.code_challenge_method === "s256") {
250-
const code_verifier = base64URLEncode(crypto.randomBytes(32));
248+
const code_verifier = base64URLEncode(crypto.getRandomValues(new Uint8Array(32)));
251249
this.#code_verifier = code_verifier;
252-
this.#code_challenge = base64URLEncode(sha256(code_verifier));
250+
this.#code_challenge = base64URLEncode(await sha256(code_verifier));
253251
} else {
254252
this.#code_challenge = options.code_challenge;
255253
this.#code_verifier = options.code_challenge;

src/utils.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ export function buildQueryString(query: Record<string, any>): string {
1212
.join("&");
1313
}
1414

15+
export function base64Encode(byteValues: Uint8Array): string {
16+
return btoa([...byteValues].map(byteValue => String.fromCharCode(byteValue)).join(''))
17+
}
18+
1519
export function basicAuthHeader(client_id: string, client_secret: string) {
16-
return `Basic ${Buffer.from(`${client_id}:${client_secret}`).toString(
17-
"base64"
18-
)}`;
20+
return `Basic ${base64Encode(new TextEncoder().encode(`${client_id}:${client_secret}`))}`
1921
}

test/utils.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2021 Twitter, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { base64Encode } from "../src/utils";
5+
6+
describe("test utils", () => {
7+
8+
test("base64Encode is equivalent to Buffer.toString('base64')", () => {
9+
for (let i = 0; i < 64; i++) { // go through all 64 symbols
10+
const byteValues = new Uint8Array([i << 2]);
11+
expect(base64Encode(byteValues)).toEqual(Buffer.from(Buffer.from(byteValues)).toString("base64"));
12+
}
13+
});
14+
15+
});

0 commit comments

Comments
 (0)