import * as plugins from '../plugins.js'; 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( 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', }; } return { status: 'loggedIn', jwt: resultJwt, refreshToken: rotatedRefreshToken, }; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getPublicKeyForValidation', async (requestArg) => { // TODO control backend token return { publicKeyPem: this.smartjwtInstance.getKeyPairAsJson().publicPem, }; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'pushOrGetJwtIdBlocklist', async (requestArg) => { // TODO control backend token return { blockedJwtIds: this.blockedJwtIdList }; } ) ); } public async pushPublicKeyToClients() { const targetConnections = await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag( 'lole-reception', { backendToken: '', } ); for (const targetConnection of targetConnections) { const pushPublicKeyTr = this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest( 'pushPublicKeyForValidation', targetConnection ); await pushPublicKeyTr.fire({ publicKeyPem: this.smartjwtInstance.getKeyPairAsJson().publicPem, }); } } public async pushBlockedJwtIdListToClients() { const targetConnections = await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag( 'lole-reception', { backendToken: '', } ); for (const targetConnection of targetConnections) { const pushPublicKeyTr = this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest( '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 { const jwtData: plugins.idpInterfaces.data.IJwt = await this.smartjwtInstance.verifyJWTAndGetData(jwtArg); const jwt = await this.CJwt.getInstance({ id: jwtData.id, }); if (!jwt) { return null; } if (jwt.blocked) { return null; } if (jwt) { const loginSession = await jwt.getLoginSession(); if (!loginSession || loginSession.data.invalidated) { await jwt.block(); if (!this.blockedJwtIdList.includes(jwt.id)) { this.blockedJwtIdList.push(jwt.id); } return null; } } return jwt; } }