AUTH_VALIDATION_SCHEMA |
Type : object
|
Default value : {
OIDC: Joi.string().optional(),
KEYCLOAK_INTERNAL_ISSUER_URL: Joi.when('OIDC', {
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
KEYCLOAK_CLIENT_ID: Joi.when('OIDC', {
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
JWT_SECRET: Joi.when('OIDC', {
then: Joi.string().optional(),
otherwise: Joi.string().required(),
}),
JWT_ISSUER: Joi.when('OIDC', {
then: Joi.string().optional(),
otherwise: Joi.string().optional().default('eudiplo-service'),
}),
JWT_EXPIRES_IN: Joi.when('OIDC', {
then: Joi.string().optional(),
otherwise: Joi.string().default('24h'),
}),
AUTH_CLIENT_SECRET: Joi.when('OIDC', {
then: Joi.string().optional(),
otherwise: Joi.string().required(),
}),
AUTH_CLIENT_ID: Joi.when('OIDC', {
then: Joi.string().optional(),
otherwise: Joi.string().required(),
}),
}
|
extraPrefixes |
Default value : Object.entries(extraPrefixesMap)
|
extraPrefixesMap |
Type : Record<string, Slot>
|
Default value : {
$body_: 'body',
$headers_: 'headers',
$path_: 'path',
$query_: 'query',
}
|
defaultHeaders |
Type : object
|
Default value : {
'Content-Type': 'application/json',
}
|
defaultQuerySerializer |
Default value : createQuerySerializer({
allowReserved: false,
array: {
explode: true,
style: 'form',
},
object: {
explode: true,
style: 'deepObject',
},
})
|
PATH_PARAM_RE |
Default value : /\{[^{}]+\}/g
|
callbacks |
Type : any
|
Default value : {
hash: (data, alg) =>
crypto
.createHash(alg.replace('-', '').toLowerCase())
.update(data)
.digest(),
generateRandom: (bytes) => crypto.randomBytes(bytes),
/* clientAuthentication: clientAuthenticationNone({
clientId: 'some-random-client-id',
}), */
verifyJwt: async (signer, { compact, payload }) => {
let jwk: Jwk;
let publicKey: CryptoKey;
if (signer.method === 'jwk') {
jwk = signer.publicJwk;
publicKey = (await importJWK(jwk as JWK, signer.alg)) as CryptoKey;
} else if (signer.method === 'x5c') {
const headerB64 = compact.split('.')[0];
const header = JSON.parse(
Buffer.from(headerB64, 'base64url').toString(),
);
const certPem = `-----BEGIN CERTIFICATE-----\n${header.x5c}\n-----END CERTIFICATE-----`;
publicKey = await importX509(certPem, signer.alg);
jwk = (await exportJWK(publicKey)) as Jwk;
} else {
throw new Error('Signer method not supported');
}
try {
await jwtVerify(compact, publicKey, {
currentDate: payload.exp
? new Date((payload.exp - 300) * 1000)
: undefined,
});
return {
verified: true,
signerJwk: jwk,
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return {
verified: false,
};
}
},
getX509CertificateMetadata: (
certificate: string,
): {
sanDnsNames: string[];
sanUriNames: string[];
} => {
const cert1 = new crypto.X509Certificate(
`-----BEGIN CERTIFICATE-----\n${certificate}\n-----END CERTIFICATE-----`,
);
const sanDnsNames = cert1
.subjectAltName!.split(',')
.map((name) => name.replace('DNS:', '').trim());
const sanUriNames = [];
sanDnsNames.push('example.com');
return {
sanDnsNames,
sanUriNames,
};
},
} as const satisfies Partial<CallbackContext>
|
client |
Default value : createClient(createConfig<ClientOptions>())
|
clientId |
Type : string
|
Default value : 'root'
|
clientSecret |
Type : string
|
Default value : 'root'
|
url |
Type : string
|
Default value : 'http://localhost:3000'
|
CRYPTO_VALIDATION_SCHEMA |
Type : object
|
Default value : {
CRYPTO_ALG: Joi.string().valid('ES256', 'Ed25519').default('ES256'),
}
|
DB_VALIDATION_SCHEMA |
Type : object
|
Default value : {
DB_TYPE: Joi.string().valid('sqlite', 'postgres').default('sqlite'),
DB_HOST: Joi.string().when('DB_TYPE', {
is: 'sqlite',
then: Joi.optional(),
otherwise: Joi.required(),
}),
DB_PORT: Joi.number().when('DB_TYPE', {
is: 'sqlite',
then: Joi.optional(),
otherwise: Joi.required(),
}),
DB_USERNAME: Joi.string().when('DB_TYPE', {
is: 'sqlite',
then: Joi.optional(),
otherwise: Joi.required(),
}),
DB_PASSWORD: Joi.string().when('DB_TYPE', {
is: 'sqlite',
then: Joi.optional(),
otherwise: Joi.required(),
}),
DB_DATABASE: Joi.string().when('DB_TYPE', {
is: 'sqlite',
then: Joi.optional(),
otherwise: Joi.required(),
}),
}
|
ED25519 |
Type : CryptoImplementation
|
Default value : {
alg: 'EdDSA',
async generateKeyPair() {
const keyPair = await crypto.webcrypto.subtle.generateKey(
{
name: 'EdDSA',
namedCurve: 'Ed25519',
},
true,
['sign', 'verify'],
);
const publicKey = await crypto.webcrypto.subtle.exportKey(
'jwk',
keyPair.publicKey,
);
const privateKey = await crypto.webcrypto.subtle.exportKey(
'jwk',
keyPair.privateKey,
);
return { publicKey, privateKey };
},
async getSigner(privateKeyJWK: object) {
const privateKey = await crypto.webcrypto.subtle.importKey(
'jwk',
privateKeyJWK,
{
name: 'EdDSA',
namedCurve: 'Ed25519',
},
false,
['sign'],
);
return async (data: string) => {
const signature = await crypto.webcrypto.subtle.sign(
'EdDSA',
privateKey,
new TextEncoder().encode(data),
);
return Buffer.from(signature).toString('base64url');
};
},
async getVerifier(publicKeyJWK: object) {
const publicKey = await crypto.webcrypto.subtle.importKey(
'jwk',
publicKeyJWK,
{
name: 'EdDSA',
namedCurve: 'Ed25519',
},
false,
['verify'],
);
return async (data: string, signatureBase64url: string) => {
const signature = Buffer.from(signatureBase64url, 'base64url');
const isVerified = await crypto.webcrypto.subtle.verify(
'EdDSA',
publicKey,
signature,
new TextEncoder().encode(data),
);
return isVerified;
};
},
}
|
formDataBodySerializer |
Type : object
|
Default value : {
bodySerializer: <
T extends Record<string, any> | Array<Record<string, any>>,
>(
body: T,
): FormData => {
const data = new FormData();
Object.entries(body).forEach(([key, value]) => {
if (value === undefined || value === null) {
return;
}
if (Array.isArray(value)) {
value.forEach((v) => serializeFormDataPair(data, key, v));
} else {
serializeFormDataPair(data, key, value);
}
});
return data;
},
}
|
jsonBodySerializer |
Type : object
|
Default value : {
bodySerializer: <T>(body: T): string =>
JSON.stringify(body, (_key, value) =>
typeof value === 'bigint' ? value.toString() : value,
),
}
|
urlSearchParamsBodySerializer |
Type : object
|
Default value : {
bodySerializer: <
T extends Record<string, any> | Array<Record<string, any>>,
>(
body: T,
): string => {
const data = new URLSearchParams();
Object.entries(body).forEach(([key, value]) => {
if (value === undefined || value === null) {
return;
}
if (Array.isArray(value)) {
value.forEach((v) =>
serializeUrlSearchParamsPair(data, key, v),
);
} else {
serializeUrlSearchParamsPair(data, key, value);
}
});
return data.toString();
},
}
|
IS_PUBLIC_KEY |
Type : string
|
Default value : 'isPublic'
|
Public |
Default value : () => SetMetadata(IS_PUBLIC_KEY, true)
|
ISSUER_VALIDATION_SCHEMA |
Type : object
|
Default value : {
PUBLIC_URL: Joi.string(),
}
|
KEY_VALIDATION_SCHEMA |
Type : object
|
Default value : {
KM_TYPE: Joi.string().valid('file', 'vault').default('file'),
// Vault-related config
VAULT_URL: Joi.string().uri().when('KM_TYPE', {
is: 'vault',
then: Joi.required(),
otherwise: Joi.optional(),
}),
VAULT_TOKEN: Joi.string().when('KM_TYPE', {
is: 'vault',
then: Joi.required(),
otherwise: Joi.optional(),
}),
VAULT_KEY_ID: Joi.string().when('KM_TYPE', {
is: 'vault',
then: Joi.string().default('key-id'),
otherwise: Joi.optional(),
}),
}
|
REGISTRAR_VALIDATION_SCHEMA |
Type : object
|
Default value : {
REGISTRAR_URL: Joi.string(),
OIDC_ISSUER_URL: Joi.string().when('REGISTRAR_URL', {
is: Joi.exist(),
then: Joi.required(),
}),
OIDC_CLIENT_ID: Joi.string().when('REGISTRAR_URL', {
is: Joi.exist(),
then: Joi.required(),
}),
OIDC_CLIENT_SECRET: Joi.string().when('REGISTRAR_URL', {
is: Joi.exist(),
then: Joi.required(),
}),
}
|
separatorArrayExplode |
Default value : (style: ArraySeparatorStyle) => {
switch (style) {
case 'label':
return '.';
case 'matrix':
return ';';
case 'simple':
return ',';
default:
return '&';
}
}
|
separatorObjectExplode |
Default value : (style: ObjectSeparatorStyle) => {
switch (style) {
case 'label':
return '.';
case 'matrix':
return ';';
case 'simple':
return ',';
default:
return '&';
}
}
|
SESSION_LOGGER_KEY |
Type : string
|
Default value : 'session-logger'
|
SESSION_VALIDATION_SCHEMA |
Type : object
|
Default value : {
SESSION_TIDY_UP_INTERVAL: Joi.number().default(60 * 60), // default to every hour
SESSION_TTL: Joi.number().default(24 * 60 * 60), // default to 24 hours
}
|
TENANT_EVENTS |
Type : object
|
Default value : {
TENANT_INIT: 'tenant.init',
TENANT_KEYS: 'tenant.keys',
}
|