libmodulor
Version:
A TypeScript library to create platform-agnostic applications
122 lines (121 loc) • 5.26 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { inject, injectable } from 'inversify';
import { decodeJwt, decodeProtectedHeader, importPKCS8, importSPKI, jwtVerify, SignJWT, } from 'jose';
import { JWSSignatureVerificationFailed } from 'jose/errors';
import { UnauthorizedError } from '../../error/index.js';
import { assertIsDefined } from '../../utils/index.js';
let JoseJWTManager = class JoseJWTManager {
clockManager;
settingsManager;
constructor(clockManager, settingsManager) {
this.clockManager = clockManager;
this.settingsManager = settingsManager;
}
s() {
return {
jwt_manager_algorithm: this.settingsManager.get()('jwt_manager_algorithm'),
jwt_manager_audience: this.settingsManager.get()('jwt_manager_audience'),
jwt_manager_expires_in_s: this.settingsManager.get()('jwt_manager_expires_in_s'),
jwt_manager_issuer: this.settingsManager.get()('jwt_manager_issuer'),
jwt_manager_key_id: this.settingsManager.get()('jwt_manager_key_id'),
jwt_manager_secret: this.settingsManager.get()('jwt_manager_secret'),
jwt_manager_subject: this.settingsManager.get()('jwt_manager_subject'),
};
}
async decode(value, opts) {
try {
const { alg } = decodeProtectedHeader(value);
assertIsDefined(alg, 'alg');
const secret = opts?.secret || this.s().jwt_manager_secret;
if (alg.startsWith('HS')) {
return (await jwtVerify(value, new TextEncoder().encode(secret))).payload;
}
if (alg.startsWith('RS')) {
assertIsDefined(opts?.spki, 'opts.spki');
const publicKey = await importSPKI(opts?.spki, alg);
return (await jwtVerify(value, publicKey)).payload;
}
}
catch (err) {
if (err instanceof JWSSignatureVerificationFailed) {
throw new UnauthorizedError();
}
// See node_modules/jose/dist/webapi/util/decode_protected_header.js
if (err instanceof TypeError &&
err.message.toLowerCase().includes('invalid token')) {
throw new UnauthorizedError();
}
}
throw new UnauthorizedError();
}
async decodeUnsafe(value) {
const decoded = decodeJwt(value);
return decoded;
}
async encode(payload, opts) {
const alg = opts?.alg ?? this.s().jwt_manager_algorithm;
const aud = opts?.aud ?? this.s().jwt_manager_audience;
const exp = opts?.exp ?? this.s().jwt_manager_expires_in_s;
const iss = opts?.iss ?? this.s().jwt_manager_issuer;
const kid = opts?.kid ?? this.s().jwt_manager_key_id;
const secret = opts?.secret ?? this.s().jwt_manager_secret;
const subject = opts?.sub ?? this.s().jwt_manager_subject;
const typ = 'JWT';
const header = { alg, typ };
if (kid) {
header.kid = kid;
}
const issuedAt = this.clockManager.time();
const expiresAt = issuedAt + exp;
const builder = new SignJWT(payload)
.setAudience(aud)
.setExpirationTime(expiresAt)
.setIssuer(iss)
.setIssuedAt(issuedAt)
.setProtectedHeader(header);
if (subject) {
builder.setSubject(subject);
}
if (alg.startsWith('HS')) {
return builder.sign(new TextEncoder().encode(secret));
}
if (alg.startsWith('RS')) {
return builder.sign(await importPKCS8(secret, alg));
}
throw new Error(`Unsupported alg ${alg}`);
}
async isUsable(value) {
const decoded = decodeJwt(value);
if (!(decoded &&
typeof decoded === 'object' &&
'exp' in decoded &&
typeof decoded.exp === 'number')) {
return false;
}
const now = this.clockManager.time();
const { exp } = decoded;
const isExpired = exp < now;
if (isExpired) {
return false;
}
return true;
}
};
JoseJWTManager = __decorate([
injectable(),
__param(0, inject('ClockManager')),
__param(1, inject('SettingsManager')),
__metadata("design:paramtypes", [Object, Object])
], JoseJWTManager);
export { JoseJWTManager };