import type { PluginDefinition } from '@yaakapp/api'; import jwt from 'jsonwebtoken'; const algorithms = [ 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', 'ES256', 'ES384', 'ES512', 'none', ] as const; const defaultAlgorithm = algorithms[0]; export const plugin: PluginDefinition = { authentication: { name: 'jwt', label: 'JWT Bearer', shortLabel: 'JWT', args: [ { type: 'select', name: 'algorithm', label: 'Algorithm', hideLabel: true, defaultValue: defaultAlgorithm, options: algorithms.map((value) => ({ label: value === 'none' ? 'None' : value, value })), }, { type: 'text', name: 'secret', label: 'Secret or Private Key', password: true, optional: true, multiLine: true, }, { type: 'checkbox', name: 'secretBase64', label: 'Secret is base64 encoded', }, { type: 'editor', name: 'payload', label: 'JWT Payload', language: 'json', defaultValue: '{\n "foo": "bar"\n}', placeholder: '{ }', }, { type: 'accordion', label: 'Advanced', inputs: [ { type: 'editor', name: 'headers', label: 'JWT Header', description: 'Merged with auto-generated header fields like alg (e.g., kid)', language: 'json', defaultValue: '{}', placeholder: '{ }', optional: true, }, { type: 'select', name: 'location', label: 'Behavior', defaultValue: 'header', options: [ { label: 'Insert Header', value: 'header' }, { label: 'Append Query Parameter', value: 'query' }, ], }, { type: 'h_stack', inputs: [ { type: 'text', name: 'name', label: 'Header Name', defaultValue: 'Authorization', optional: true, description: 'The name of the header to add to the request', }, { type: 'text', name: 'headerPrefix', label: 'Header Prefix', optional: true, defaultValue: 'Bearer', }, ], dynamic(_ctx, args) { if (args.values.location === 'query') { return { hidden: true, }; } }, }, { type: 'text', name: 'name', label: 'Parameter Name', description: 'The name of the query parameter to add to the request', defaultValue: 'token', optional: true, dynamic(_ctx, args) { if (args.values.location !== 'query') { return { hidden: true, }; } }, }, ], }, ], async onApply(_ctx, { values }) { const { algorithm, secret: _secret, secretBase64, payload, headers } = values; const secret = secretBase64 ? Buffer.from(`${_secret}`, 'base64') : `${_secret}`; const parsedHeaders = headers ? JSON.parse(`${headers}`) : undefined; const token = jwt.sign(`${payload}`, secret, { algorithm: algorithm as (typeof algorithms)[number], // Extra header fields are merged with the auto-generated header (which includes alg) header: parsedHeaders as jwt.JwtHeader | undefined, }); if (values.location === 'query') { const paramName = String(values.name || 'token'); return { setQueryParameters: [{ name: paramName, value: token }] }; } const headerPrefix = values.headerPrefix != null ? values.headerPrefix : 'Bearer'; const headerName = String(values.name || 'Authorization'); const headerValue = `${headerPrefix} ${token}`.trim(); return { setHeaders: [{ name: headerName, value: headerValue }] }; }, }, };