NeahNew/node_modules/@keycloak/keycloak-admin-client/lib/utils/auth.js
2025-05-03 15:36:20 +02:00

55 lines
2.8 KiB
JavaScript

import camelize from "camelize-ts";
import { defaultBaseUrl, defaultRealm } from "./constants.js";
import { fetchWithError } from "./fetchWithError.js";
import { stringifyQueryParams } from "./stringifyQueryParams.js";
// See: https://developer.mozilla.org/en-US/docs/Glossary/Base64
const bytesToBase64 = (bytes) => btoa(Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(""));
const toBase64 = (input) => bytesToBase64(new TextEncoder().encode(input));
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986
const encodeRFC3986URIComponent = (input) => encodeURIComponent(input).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
// Specifically, the section on encoding `application/x-www-form-urlencoded`.
const encodeFormURIComponent = (data) => encodeRFC3986URIComponent(data).replaceAll("%20", "+");
export const getToken = async (settings) => {
// Construct URL
const baseUrl = settings.baseUrl || defaultBaseUrl;
const realmName = settings.realmName || defaultRealm;
const url = `${baseUrl}/realms/${realmName}/protocol/openid-connect/token`;
// Prepare credentials for openid-connect token request
// ref: http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
const credentials = settings.credentials || {};
const payload = stringifyQueryParams({
username: credentials.username,
password: credentials.password,
grant_type: credentials.grantType,
client_id: credentials.clientId,
totp: credentials.totp,
...(credentials.offlineToken ? { scope: "offline_access" } : {}),
...(credentials.scopes ? { scope: credentials.scopes.join(" ") } : {}),
...(credentials.refreshToken
? {
refresh_token: credentials.refreshToken,
client_secret: credentials.clientSecret,
}
: {}),
});
const options = settings.requestOptions ?? {};
const headers = new Headers(options.headers);
if (credentials.clientSecret) {
// See: https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1
const username = encodeFormURIComponent(credentials.clientId);
const password = encodeFormURIComponent(credentials.clientSecret);
// See: https://datatracker.ietf.org/doc/html/rfc2617#section-2
headers.set("authorization", `Basic ${toBase64(`${username}:${password}`)}`);
}
headers.set("content-type", "application/x-www-form-urlencoded");
const response = await fetchWithError(url, {
...options,
method: "POST",
headers,
body: payload,
});
const data = (await response.json());
return camelize(data);
};