Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 2x 6x 6x 7x 7x 6x 6x 6x 6x 1x 5x 7x 6x 1x 5x 4x 4x 4x 2x 2x 2x 1x 1x | import { scrypt as scryptCallback, timingSafeEqual } from "node:crypto";
import { promisify } from "node:util";
import { getActiveClient, getExternalApiAuthConfig } from "./config";
import { CLIENT_CREDENTIALS_GRANT } from "./constants";
import { createExternalAccessToken, verifyExternalAccessToken } from "./jwt";
import { ExternalAccessTokenClaims, ExternalApiAuthConfig, ExternalApiClient } from "./types";
const scrypt = promisify(scryptCallback);
async function verifyClientSecret(
client: ExternalApiClient,
clientSecret: string,
): Promise<boolean> {
const derived = (await scrypt(
clientSecret,
client.secretSalt,
client.secretHash.length,
)) as Buffer;
return derived.length === client.secretHash.length && timingSafeEqual(derived, client.secretHash);
}
function clientSupportsClientCredentialsGrant(client: ExternalApiClient): boolean {
return client.grants.includes(CLIENT_CREDENTIALS_GRANT);
}
export async function validateClientCredentials(
clientId: string,
clientSecret: string,
): Promise<{ config: ExternalApiAuthConfig; client: ExternalApiClient } | null> {
const config = await getExternalApiAuthConfig();
const client = getActiveClient(config, clientId);
Iif (!client || !clientSupportsClientCredentialsGrant(client)) {
return null;
}
const isValidSecret = await verifyClientSecret(client, clientSecret);
if (!isValidSecret) {
return null;
}
return { config, client };
}
export async function issueClientCredentialsAccessToken(
clientId: string,
clientSecret: string,
): Promise<{ accessToken: string; client: ExternalApiClient } | null> {
const authResult = await validateClientCredentials(clientId, clientSecret);
if (!authResult) {
return null;
}
return {
accessToken: createExternalAccessToken(authResult.config, authResult.client),
client: authResult.client,
};
}
export async function authorizeExternalAccessToken(
token: string,
): Promise<{ claims: ExternalAccessTokenClaims; client: ExternalApiClient } | null> {
const config = await getExternalApiAuthConfig();
const claims = verifyExternalAccessToken(token, config);
if (!claims) {
return null;
}
const client = getActiveClient(config, claims.client_id);
if (!client || !clientSupportsClientCredentialsGrant(client)) {
return null;
}
return { claims, client };
}
|