Files
app/ts/reception/classes.jwtmanager.ts
T

178 lines
5.7 KiB
TypeScript
Raw Normal View History

import * as plugins from '../plugins.js';
2024-09-29 13:56:38 +02:00
import { Reception } from './classes.reception.js';
import { Jwt } from './classes.jwt.js';
export class JwtManager {
public receptionRef: Reception;
public get db() {
return this.receptionRef.db.smartdataDb;
}
public smartjwtInstance = new plugins.smartjwt.SmartJwt();
public jwtManagerEasyStore: plugins.smartdata.EasyStore<{
jwtJsonKeypair: plugins.tsclass.network.IJwtKeypair;
}>;
public blockedJwtIdList: string[] = [];
public typedrouter = new plugins.typedrequest.TypedRouter();
public CJwt = plugins.smartdata.setDefaultManagerForDoc(this, Jwt);
constructor(receptionRefArg: Reception) {
this.receptionRef = receptionRefArg;
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_RefreshJwt>(
2024-09-29 13:56:38 +02:00
new plugins.typedrequest.TypedHandler(
'refreshJwt',
async (requestArg) => {
const sessionLookup =
await this.receptionRef.loginSessionManager.findLoginSessionByRefreshToken(
requestArg.refreshToken
);
if (!sessionLookup || sessionLookup.validationStatus === 'invalid') {
return {
status: 'not found',
};
}
if (sessionLookup.validationStatus === 'invalidated') {
return {
status: 'invalidated',
};
}
if (sessionLookup.validationStatus === 'reused') {
await sessionLookup.loginSession.invalidate();
return {
status: 'invalidated',
};
}
const rotatedRefreshToken = await sessionLookup.loginSession.getRefreshToken();
const resultJwt = await Jwt.createJwtForLoginSession(this, sessionLookup.loginSession);
if (!rotatedRefreshToken || !resultJwt) {
return {
status: 'invalidated',
};
}
2024-09-29 13:56:38 +02:00
return {
status: 'loggedIn',
jwt: resultJwt,
refreshToken: rotatedRefreshToken,
2024-09-29 13:56:38 +02:00
};
}
)
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_GetPublicKeyForValidation>(
2024-09-29 13:56:38 +02:00
'getPublicKeyForValidation',
async (requestArg) => {
// TODO control backend token
return {
publicKeyPem: this.smartjwtInstance.getKeyPairAsJson().publicPem,
};
}
)
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_PushOrGetJwtIdBlocklist>(
2024-09-29 13:56:38 +02:00
'pushOrGetJwtIdBlocklist',
async (requestArg) => {
// TODO control backend token
return {
blockedJwtIds: this.blockedJwtIdList
};
}
)
);
}
public async pushPublicKeyToClients() {
const targetConnections =
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.idpInterfaces.tags.ITag_LolePubapi>(
2024-09-29 13:56:38 +02:00
'lole-reception',
{
backendToken: '',
}
);
for (const targetConnection of targetConnections) {
const pushPublicKeyTr =
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_PushPublicKeyForValidation>(
2024-09-29 13:56:38 +02:00
'pushPublicKeyForValidation',
targetConnection
);
await pushPublicKeyTr.fire({
publicKeyPem: this.smartjwtInstance.getKeyPairAsJson().publicPem,
});
}
}
public async pushBlockedJwtIdListToClients() {
const targetConnections =
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.idpInterfaces.tags.ITag_LolePubapi>(
2024-09-29 13:56:38 +02:00
'lole-reception',
{
backendToken: '',
}
);
for (const targetConnection of targetConnections) {
const pushPublicKeyTr =
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_PushOrGetJwtIdBlocklist>(
2024-09-29 13:56:38 +02:00
'pushOrGetJwtIdBlocklist',
targetConnection
);
await pushPublicKeyTr.fire({
blockedJwtIds: this.blockedJwtIdList
});
}
}
public async start() {
this.jwtManagerEasyStore = await this.receptionRef.db.smartdataDb.createEasyStore(
'jwtManagerEasyStore'
);
await this.smartjwtInstance.init();
let existingKeyPair = await this.jwtManagerEasyStore.readKey('jwtJsonKeypair');
if (!existingKeyPair) {
await this.rotateKeyPair();
}
existingKeyPair = await this.jwtManagerEasyStore.readKey('jwtJsonKeypair');
this.smartjwtInstance.setKeyPairAsJson(existingKeyPair);
}
public async rotateKeyPair() {
await this.smartjwtInstance.createNewKeyPair();
await this.jwtManagerEasyStore.writeKey(
'jwtJsonKeypair',
this.smartjwtInstance.getKeyPairAsJson()
);
await this.pushPublicKeyToClients();
}
public async verifyJWTAndGetData(jwtArg: string): Promise<Jwt | null> {
const jwtData: plugins.idpInterfaces.data.IJwt = await this.smartjwtInstance.verifyJWTAndGetData(jwtArg);
const jwt = await this.CJwt.getInstance({
2024-09-29 13:56:38 +02:00
id: jwtData.id,
});
if (!jwt) {
return null;
}
2024-09-29 13:56:38 +02:00
if (jwt.blocked) {
return null;
}
if (jwt) {
const loginSession = await jwt.getLoginSession();
if (!loginSession || loginSession.data.invalidated) {
2024-09-29 13:56:38 +02:00
await jwt.block();
if (!this.blockedJwtIdList.includes(jwt.id)) {
this.blockedJwtIdList.push(jwt.id);
}
2024-09-29 13:56:38 +02:00
return null;
}
}
return jwt;
}
}