mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-03 19:17:07 -04:00
58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
import type { PathLike } from 'node:fs';
|
|
import fs from 'node:fs/promises';
|
|
|
|
import * as Sentry from '@sentry/node';
|
|
import { importPKCS8, importSPKI, jwtVerify, SignJWT } from 'jose';
|
|
import type { KeyLike, JWTPayload } from 'jose';
|
|
|
|
import { rootDir } from './paths.ts';
|
|
|
|
import { getUrlForLocale, getUrlsForAllLocales } from '~/src/domain.ts';
|
|
|
|
class Jwt {
|
|
constructor(private privateKey: KeyLike, private publicKey: KeyLike) {}
|
|
|
|
static async from(privateKeyPath: PathLike, publicKeyPath: PathLike) {
|
|
const privateKeyPromise = fs.readFile(privateKeyPath, 'utf-8')
|
|
.then((privateKeyContent) => importPKCS8(privateKeyContent, 'RS256'));
|
|
const publicKeyPromise = fs.readFile(publicKeyPath, 'utf-8')
|
|
.then((publicKeyContent) => importSPKI(publicKeyContent, 'RS256'));
|
|
const [privateKey, publicKey] = await Promise.all([privateKeyPromise, publicKeyPromise]);
|
|
return new Jwt(privateKey, publicKey);
|
|
}
|
|
|
|
async sign(
|
|
locale: string,
|
|
payload: JWTPayload,
|
|
expiresIn = '365d',
|
|
domainBase: string | undefined = undefined,
|
|
): Promise<string> {
|
|
return await new SignJWT(payload)
|
|
.setProtectedHeader({ alg: 'RS256' })
|
|
.setExpirationTime(expiresIn)
|
|
.setAudience(getUrlsForAllLocales(locale, false, domainBase))
|
|
.setIssuer(getUrlForLocale(locale, domainBase))
|
|
.sign(this.privateKey);
|
|
}
|
|
|
|
async validate<PayloadType = JWTPayload>(
|
|
locale: string,
|
|
token: string,
|
|
domainBase: string | undefined = undefined,
|
|
): Promise<PayloadType | undefined> {
|
|
const urls = getUrlsForAllLocales(locale, false, domainBase);
|
|
try {
|
|
const { payload } = await jwtVerify<PayloadType>(token, this.publicKey, {
|
|
algorithms: ['RS256'],
|
|
audience: urls,
|
|
issuer: urls,
|
|
});
|
|
return payload;
|
|
} catch (error) {
|
|
Sentry.captureException(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default await Jwt.from(`${rootDir}/keys/private.pem`, `${rootDir}/keys/public.pem`);
|