Files
homarr/packages/integrations/src/http-auth.ts
T
+12 fcd7c979df feat!: release v2 (#6545)
Co-authored-by: Artur <145776561+arturict@users.noreply.github.com>
Co-authored-by: arturict <arturict@users.noreply.github.com>
Co-authored-by: Thomas <thomas@ajnart.fr>
Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com>
Co-authored-by: Danura30082 <danura30082+github@gmail.com>
Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com>
Co-authored-by: ajnart <thomas@ajnart.fr>
Co-authored-by: ajnart <thomas@ajnart.dev>
Co-authored-by: chenjun <chenjun@foxmail.com>
Co-authored-by: Wikibear <wikibear@users.noreply.github.com>
Co-authored-by: Bergasha <bergasha@gmail.com>
Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com>
Co-authored-by: Lucas Araujo <lucas.lra@gmail.com>
Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com>
Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social>
Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com>
Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com>
Co-authored-by: thrawnx <tight.bulb9384@fastmail.com>
Co-authored-by: Chris <58918656+nordada@users.noreply.github.com>
Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com>
Co-authored-by: Yanis <naamaneyanis@gmail.com>
Co-authored-by: Wikibear <me@sej.de>
Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
2026-10-02 21:00:14 +02:00

75 lines
2.9 KiB
TypeScript

import { Buffer } from "node:buffer";
import type {
IntegrationHttpAuthDefinition,
IntegrationHttpBodyAuth,
IntegrationSecretKind,
} from "@homarr/definitions";
import type { IntegrationInput } from "./base/integration";
/** Server-only credentials supplied by the integration's native adapter. */
export interface IntegrationHttpAuthentication {
headers: Record<string, string>;
query?: Record<string, string>;
body?: IntegrationHttpBodyAuth;
redactValues?: string[];
}
function secret(input: IntegrationInput, kind: IntegrationSecretKind) {
const value = input.decryptedSecrets.find((entry) => entry.kind === kind)?.value;
if (!value) throw new Error(`Integration credential ${kind} is missing`);
return value;
}
export function apiKeyAuth(input: IntegrationInput): IntegrationHttpAuthentication {
return { headers: { "X-API-Key": secret(input, "apiKey") } };
}
export function resolveDeclaredHttpAuthentication(
input: IntegrationInput,
definition: IntegrationHttpAuthDefinition,
): IntegrationHttpAuthentication {
if (definition.type === "modes") {
const savedKinds = new Set(input.decryptedSecrets.map(({ kind }) => kind));
const mode = definition.modes.find(
({ when }) => when.length === savedKinds.size && when.every((kind) => savedKinds.has(kind)),
);
if (!mode) throw new Error("Saved credentials do not support generic HTTP requests");
return resolveDeclaredHttpAuthentication(input, mode.auth);
}
switch (definition.type) {
case "none":
return { headers: {} };
case "bearer":
return { headers: { Authorization: `Bearer ${secret(input, definition.secretKind ?? "apiKey")}` } };
case "apiKeyHeader":
return {
headers: { [definition.name]: `${definition.prefix ?? ""}${secret(input, definition.secretKind ?? "apiKey")}` },
};
case "apiKeyQuery":
return { headers: {}, query: { [definition.name]: secret(input, definition.secretKind ?? "apiKey") } };
case "basic":
if (definition.username !== undefined) {
const credentials = Buffer.from(
`${definition.username}:${secret(input, definition.passwordKind ?? "password")}`,
).toString("base64");
return { headers: { Authorization: `Basic ${credentials}` }, redactValues: [credentials] };
}
return basicAuth(definition.usernameKind, definition.passwordKind)(input);
case "adapter":
throw new Error("This integration requires adapter-owned HTTP authentication");
}
}
export const basicAuth =
(
username: IntegrationSecretKind = "username",
password: IntegrationSecretKind = "password",
headers: Record<string, string> = {},
) =>
(input: IntegrationInput): IntegrationHttpAuthentication => {
const credentials = Buffer.from(`${secret(input, username)}:${secret(input, password)}`).toString("base64");
return { headers: { ...headers, Authorization: `Basic ${credentials}` }, redactValues: [credentials] };
};