From ee16e540cf519ef09aec7cd7a278c3861c2740be Mon Sep 17 00:00:00 2001 From: clauspeterhuebner Date: Fri, 4 Jul 2025 03:41:46 +0200 Subject: [PATCH] save the current state of code --- .../src/federation/authenticateCommunities.ts | 8 +- core/src/auth/jwt/JWT.ts | 46 +++++----- .../AuthenticationJwtPayloadType.ts | 20 +++++ .../auth/jwt/payloadtypes/JwtPayloadType.ts | 4 +- .../src/client/1_0/AuthenticationClient.ts | 7 +- .../src/client/1_0/query/authenticate.ts | 2 +- .../1_0/query/openConnectionCallback.ts | 2 +- .../1_0/resolver/AuthenticationResolver.ts | 87 ++++++++----------- .../api/1_0/util/authenticateCommunity.ts | 56 +++++++----- 9 files changed, 122 insertions(+), 110 deletions(-) create mode 100644 core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType.ts diff --git a/backend/src/federation/authenticateCommunities.ts b/backend/src/federation/authenticateCommunities.ts index ec02d210c..d52de578b 100644 --- a/backend/src/federation/authenticateCommunities.ts +++ b/backend/src/federation/authenticateCommunities.ts @@ -6,10 +6,10 @@ import { CONFIG } from '@/config' import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient' import { ensureUrlEndsWithSlash } from '@/util/utilities' -import { encryptAndSign } from '@/auth/jwt/JWT' -import { OpenConnectionJwtPayloadType } from '@/auth/jwt/payloadtypes/OpenConnectionJwtPayloadType' +import { encryptAndSign } from 'core/src/auth/jwt/JWT' +import { OpenConnectionJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/OpenConnectionJwtPayloadType' import { getLogger } from 'log4js' -import { OpenConnectionArgs } from './client/1_0/model/OpenConnectionArgs' +import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' import { AuthenticationClientFactory } from './client/AuthenticationClientFactory' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' @@ -51,7 +51,7 @@ export async function startCommunityAuthentication( ) const jws = await encryptAndSign(payload, homeCom.privateJwtKey!, foreignCom.publicJwtKey) // prepare the args for the client invocation - const args = new OpenConnectionArgs() + const args = new EncryptedTransferArgs() args.publicKey = homeCom.publicKey.toString('hex') args.jwt = jws logger.debug( diff --git a/core/src/auth/jwt/JWT.ts b/core/src/auth/jwt/JWT.ts index 80aa9c655..566eb51e2 100644 --- a/core/src/auth/jwt/JWT.ts +++ b/core/src/auth/jwt/JWT.ts @@ -1,17 +1,18 @@ import { generateKeyPair, exportSPKI, exportPKCS8, SignJWT, decodeJwt, importPKCS8, importSPKI, jwtVerify, CompactEncrypt, compactDecrypt } from 'jose' -import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' +import { LOG4JS_BASE_CATEGORY_NAME } from '../../config/const' import { getLogger } from 'log4js' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.auth.jwt.JWT`) -import { LogError } from '@/server/LogError' - import { JwtPayloadType } from './payloadtypes/JwtPayloadType' import { EncryptedJWEJwtPayloadType } from './payloadtypes/EncryptedJWEJwtPayloadType' export const createKeyPair = async (): Promise<{ publicKey: string; privateKey: string }> => { // Generate key pair using jose library - const keyPair = await generateKeyPair('RS256'); + const keyPair = await generateKeyPair('RS256', { + modulusLength: 2048, // recommended key size + extractable: true, + }); logger.debug(`Federation: writeJwtKeyPairInHomeCommunity generated keypair...`); // Convert keys to PEM format for storage in database @@ -22,9 +23,10 @@ export const createKeyPair = async (): Promise<{ publicKey: string; privateKey: export const verify = async (token: string, publicKey: string): Promise => { if (!token) { - throw new LogError('401 Unauthorized') + logger.error('verify... token is empty') + throw new Error('401 Unauthorized') } - logger.debug('JWT.verify... token, publicKey=', token, publicKey) + logger.debug('verify... token, publicKey=', token, publicKey) try { const importedKey = await importSPKI(publicKey, 'RS256') @@ -37,17 +39,17 @@ export const verify = async (token: string, publicKey: string): Promise { } export const encrypt = async (payload: JwtPayloadType, publicKey: string): Promise => { - logger.debug('JWT.encrypt... payload=', payload) - logger.debug('JWT.encrypt... publicKey=', publicKey) + logger.debug('encrypt... payload=', payload) + logger.debug('encrypt... publicKey=', publicKey) try { const encryptKey = await importSPKI(publicKey, 'RSA-OAEP-256') // Convert the key to JWK format if needed @@ -96,7 +98,7 @@ export const encrypt = async (payload: JwtPayloadType, publicKey: string): Promi ) .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) .encrypt(recipientKey) - logger.debug('JWT.encrypt... jwe=', jwe) + logger.debug('encrypt... jwe=', jwe) return jwe.toString() } catch (e) { logger.error('Failed to encrypt JWT:', e) @@ -105,14 +107,14 @@ export const encrypt = async (payload: JwtPayloadType, publicKey: string): Promi } export const decrypt = async(jwe: string, privateKey: string): Promise => { - logger.debug('JWT.decrypt... jwe=', jwe) - logger.debug('JWT.decrypt... privateKey=', privateKey.substring(0, 10)) + logger.debug('decrypt... jwe=', jwe) + logger.debug('decrypt... privateKey=', privateKey.substring(0, 10)) try { const decryptKey = await importPKCS8(privateKey, 'RSA-OAEP-256') const { plaintext, protectedHeader } = await compactDecrypt(jwe, decryptKey) - logger.debug('JWT.decrypt... plaintext=', plaintext) - logger.debug('JWT.decrypt... protectedHeader=', protectedHeader) + logger.debug('decrypt... plaintext=', plaintext) + logger.debug('decrypt... protectedHeader=', protectedHeader) return new TextDecoder().decode(plaintext) } catch (e) { logger.error('Failed to decrypt JWT:', e) @@ -122,9 +124,9 @@ export const decrypt = async(jwe: string, privateKey: string): Promise = export const encryptAndSign = async (payload: JwtPayloadType, privateKey: string, publicKey: string): Promise => { const jwe = await encrypt(payload, publicKey) - logger.debug('JWT.encryptAndSign... jwe=', jwe) + logger.debug('encryptAndSign... jwe=', jwe) const jws = await encode(new EncryptedJWEJwtPayloadType(jwe), privateKey) - logger.debug('JWT.encryptAndSign... jws=', jws) + logger.debug('encryptAndSign... jws=', jws) return jws } @@ -134,7 +136,7 @@ export const verifyAndDecrypt = async (token: string, privateKey: string, public return null } const jwePayload = jweVerifyResult.payload as EncryptedJWEJwtPayloadType - logger.debug('JWT.verifyAndDecrypt... jwePayload=', jwePayload) + logger.debug('verifyAndDecrypt... jwePayload=', jwePayload) if (!jwePayload) { return null } @@ -143,8 +145,8 @@ export const verifyAndDecrypt = async (token: string, privateKey: string, public return null } const jwe = jwePayload.jwe - logger.debug('JWT.verifyAndDecrypt... jwe=', jwe) + logger.debug('verifyAndDecrypt... jwe=', jwe) const payload = await decrypt(jwe as string, privateKey) - logger.debug('JWT.verifyAndDecrypt... payload=', payload) + logger.debug('verifyAndDecrypt... payload=', payload) return JSON.parse(payload) as JwtPayloadType } diff --git a/core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType.ts b/core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType.ts new file mode 100644 index 000000000..d8e572d5e --- /dev/null +++ b/core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType.ts @@ -0,0 +1,20 @@ +import { JwtPayloadType } from './JwtPayloadType' + +export class AuthenticationJwtPayloadType extends JwtPayloadType { + static AUTHENTICATION_TYPE = 'authentication' + + oneTimeCode: string + uuid: string + + constructor( + oneTimeCode: string, + uuid: string, + ) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + super() + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + this.tokentype = AuthenticationJwtPayloadType.AUTHENTICATION_TYPE + this.oneTimeCode = oneTimeCode + this.uuid = uuid + } +} diff --git a/core/src/auth/jwt/payloadtypes/JwtPayloadType.ts b/core/src/auth/jwt/payloadtypes/JwtPayloadType.ts index c69ed1da4..1379653cc 100644 --- a/core/src/auth/jwt/payloadtypes/JwtPayloadType.ts +++ b/core/src/auth/jwt/payloadtypes/JwtPayloadType.ts @@ -1,6 +1,6 @@ import { JWTPayload } from 'jose' -import { CONFIG } from '@/config' +import { REDEEM_JWT_TOKEN_EXPIRATION } from '../../../config/const' export class JwtPayloadType implements JWTPayload { static ISSUER = 'urn:gradido:issuer' @@ -19,6 +19,6 @@ export class JwtPayloadType implements JWTPayload { expiration: string // in minutes (format: 10m for ten minutes) constructor() { this.tokentype = 'unknown jwt type' - this.expiration = CONFIG.REDEEM_JWT_TOKEN_EXPIRATION || '10m' + this.expiration = REDEEM_JWT_TOKEN_EXPIRATION || '10m' } } diff --git a/federation/src/client/1_0/AuthenticationClient.ts b/federation/src/client/1_0/AuthenticationClient.ts index 85daa706f..20d9b8d42 100644 --- a/federation/src/client/1_0/AuthenticationClient.ts +++ b/federation/src/client/1_0/AuthenticationClient.ts @@ -3,8 +3,7 @@ import { GraphQLClient } from 'graphql-request' import { getLogger } from 'log4js' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { AuthenticationArgs } from '@/graphql/api/1_0/model/AuthenticationArgs' -import { OpenConnectionCallbackArgs } from '@/graphql/api/1_0/model/OpenConnectionCallbackArgs' +import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' import { authenticate } from './query/authenticate' import { openConnectionCallback } from './query/openConnectionCallback' @@ -29,7 +28,7 @@ export class AuthenticationClient { }) } - async openConnectionCallback(args: OpenConnectionCallbackArgs): Promise { + async openConnectionCallback(args: EncryptedTransferArgs): Promise { logger.debug('openConnectionCallback with endpoint', this.endpoint, args) try { const { data } = await this.client.rawRequest(openConnectionCallback, { args }) @@ -46,7 +45,7 @@ export class AuthenticationClient { return false } - async authenticate(args: AuthenticationArgs): Promise { + async authenticate(args: EncryptedTransferArgs): Promise { logger.debug('authenticate with endpoint=', this.endpoint) try { const { data } = await this.client.rawRequest(authenticate, { args }) diff --git a/federation/src/client/1_0/query/authenticate.ts b/federation/src/client/1_0/query/authenticate.ts index 843d8b78b..fb68a0189 100644 --- a/federation/src/client/1_0/query/authenticate.ts +++ b/federation/src/client/1_0/query/authenticate.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const authenticate = gql` - mutation ($args: AuthenticationArgs!) { + mutation ($args: EncryptedTransferArgs!) { authenticate(data: $args) } ` diff --git a/federation/src/client/1_0/query/openConnectionCallback.ts b/federation/src/client/1_0/query/openConnectionCallback.ts index ba026e610..380e3daed 100644 --- a/federation/src/client/1_0/query/openConnectionCallback.ts +++ b/federation/src/client/1_0/query/openConnectionCallback.ts @@ -1,7 +1,7 @@ import { gql } from 'graphql-request' export const openConnectionCallback = gql` - mutation ($args: OpenConnectionCallbackArgs!) { + mutation ($args: EncryptedTransferArgs!) { openConnectionCallback(data: $args) } ` diff --git a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts index 9a64d9664..cdf3dc9de 100644 --- a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts @@ -5,17 +5,17 @@ import { Community as DbCommunity, FederatedCommunity as DbFedCommunity, FederatedCommunityLoggingView, + getHomeCommunity, } from 'database' import { getLogger } from 'log4js' import { Arg, Mutation, Resolver } from 'type-graphql' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { AuthenticationArgs } from '../model/AuthenticationArgs' -import { OpenConnectionArgs } from '../model/OpenConnectionArgs' -import { OpenConnectionCallbackArgs } from '../model/OpenConnectionCallbackArgs' +import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' import { startAuthentication, startOpenConnectionCallback } from '../util/authenticateCommunity' -import { verifyAndDecrypt } from 'backend/src/auth/jwt/JWT' -import { OpenConnectionJwtPayloadType } from 'backend/src/auth/jwt/payloadtypes/OpenConnectionJwtPayloadType' -import { JwtPayloadType } from 'backend/src/auth/jwt/payloadtypes/JwtPayloadType' +import { OpenConnectionJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/OpenConnectionJwtPayloadType' +import { interpretEncryptedTransferArgs } from 'core/src/graphql/logic/interpretEncryptedTransferArgs' +import { OpenConnectionCallbackJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType' +import { AuthenticationJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.api.1_0.resolver.AuthenticationResolver`) @@ -24,95 +24,76 @@ export class AuthenticationResolver { @Mutation(() => Boolean) async openConnection( @Arg('data') - args: OpenConnectionArgs, + args: EncryptedTransferArgs, ): Promise { - const pubKeyBuf = Buffer.from(args.publicKey, 'hex') logger.debug(`openConnection() via apiVersion=1_0:`, args) - - // first find with args.publicKey the community 'comA', which starts openConnection request - const comA = await DbCommunity.findOneBy({ - publicKey: pubKeyBuf, // Buffer.from(args.publicKey), - }) - if (!comA) { - throw new LogError(`unknown requesting community with publicKey`, pubKeyBuf.toString('hex')) - } - if (!comA.publicJwtKey) { - throw new LogError(`missing publicJwtKey of community with publicKey`, pubKeyBuf.toString('hex')) - } - logger.debug(`found requestedCom:`, new CommunityLoggingView(comA)) - // verify the signing of args.jwt with homeCom.privateJwtKey and decrypt args.jwt with comA.publicJwtKey - const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) - const openConnectionJwtPayload = await verifyAndDecrypt(args.jwt, homeCom.privateJwtKey!, comA.publicJwtKey) as OpenConnectionJwtPayloadType + const openConnectionJwtPayload = await interpretEncryptedTransferArgs(args) as OpenConnectionJwtPayloadType if (!openConnectionJwtPayload) { - throw new LogError(`invalid payload of community with publicKey`, pubKeyBuf.toString('hex')) - } - if (!openConnectionJwtPayload.url) { - throw new LogError(`invalid url of community with publicKey`, pubKeyBuf.toString('hex')) + throw new LogError(`invalid OpenConnection payload of requesting community with publicKey`, args.publicKey) } if (openConnectionJwtPayload.tokentype !== OpenConnectionJwtPayloadType.OPEN_CONNECTION_TYPE) { - throw new LogError(`invalid tokentype of community with publicKey`, pubKeyBuf.toString('hex')) + throw new LogError(`invalid tokentype of community with publicKey`, args.publicKey) } - /* - if (openConnectionJwtPayload.expiration < new Date().toISOString()) { - throw new LogError(`invalid expiration of community with publicKey`, pubKeyBuf.toString('hex')) + if (!openConnectionJwtPayload.url) { + throw new LogError(`invalid url of community with publicKey`, args.publicKey) } - if (openConnectionJwtPayload.issuer !== JwtPayloadType.ISSUER) { - throw new LogError(`invalid issuer of community with publicKey`, pubKeyBuf.toString('hex')) - } - if (openConnectionJwtPayload.audience !== JwtPayloadType.AUDIENCE) { - throw new LogError(`invalid audience of community with publicKey`, pubKeyBuf.toString('hex')) - } - */ - const fedComA = await DbFedCommunity.findOneByOrFail({ publicKey: comA.publicKey }) + const fedComA = await DbFedCommunity.findOneByOrFail({ publicKey: Buffer.from(args.publicKey, 'hex') }) if (!openConnectionJwtPayload.url.startsWith(fedComA.endPoint)) { - throw new LogError(`invalid url of community with publicKey`, pubKeyBuf.toString('hex')) + throw new LogError(`invalid url of community with publicKey`, args.publicKey) } // biome-ignore lint/complexity/noVoid: no await to respond immediately and invoke callback-request asynchronously - void startOpenConnectionCallback(comA, CONFIG.FEDERATION_API) + void startOpenConnectionCallback(args.publicKey, CONFIG.FEDERATION_API) return true } @Mutation(() => Boolean) async openConnectionCallback( @Arg('data') - args: OpenConnectionCallbackArgs, + args: EncryptedTransferArgs, ): Promise { logger.debug(`openConnectionCallback() via apiVersion=1_0 ...`, args) + const openConnectionCallbackJwtPayload = await interpretEncryptedTransferArgs(args) as OpenConnectionCallbackJwtPayloadType + if (!openConnectionCallbackJwtPayload) { + throw new LogError(`invalid OpenConnectionCallback payload of requesting community with publicKey`, args.publicKey) + } + // TODO decrypt args.url with homeCom.privateJwtKey and verify signing with callbackFedCom.publicKey - const endPoint = args.url.slice(0, args.url.lastIndexOf('/') + 1) - const apiVersion = args.url.slice(args.url.lastIndexOf('/') + 1, args.url.length) + const endPoint = openConnectionCallbackJwtPayload.url.slice(0, openConnectionCallbackJwtPayload.url.lastIndexOf('/') + 1) + const apiVersion = openConnectionCallbackJwtPayload.url.slice(openConnectionCallbackJwtPayload.url.lastIndexOf('/') + 1, openConnectionCallbackJwtPayload.url.length) logger.debug(`search fedComB per:`, endPoint, apiVersion) const fedComB = await DbFedCommunity.findOneBy({ endPoint, apiVersion }) if (!fedComB) { - throw new LogError(`unknown callback community with url`, args.url) + throw new LogError(`unknown callback community with url`, openConnectionCallbackJwtPayload.url) } logger.debug( `found fedComB and start authentication:`, new FederatedCommunityLoggingView(fedComB), ) // biome-ignore lint/complexity/noVoid: no await to respond immediately and invoke authenticate-request asynchronously - void startAuthentication(args.oneTimeCode, fedComB) + void startAuthentication(openConnectionCallbackJwtPayload.oneTimeCode, fedComB) return true } @Mutation(() => String) async authenticate( @Arg('data') - args: AuthenticationArgs, + args: EncryptedTransferArgs, ): Promise { logger.debug(`authenticate() via apiVersion=1_0 ...`, args) - const authCom = await DbCommunity.findOneByOrFail({ communityUuid: args.oneTimeCode }) + const authArgs = await interpretEncryptedTransferArgs(args) as AuthenticationJwtPayloadType + if (!authArgs) { + throw new LogError(`invalid authentication payload of requesting community with publicKey`, args.publicKey) + } + const authCom = await DbCommunity.findOneByOrFail({ communityUuid: authArgs.oneTimeCode }) logger.debug('found authCom:', new CommunityLoggingView(authCom)) if (authCom) { - // TODO decrypt args.uuid with authCom.publicKey - authCom.communityUuid = args.uuid + authCom.communityUuid = authArgs.uuid authCom.authenticatedAt = new Date() await DbCommunity.save(authCom) logger.debug('store authCom.uuid successfully:', new CommunityLoggingView(authCom)) - const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) - // TODO encrypt homeCom.uuid with homeCom.privateKey - if (homeCom.communityUuid) { + const homeCom = await getHomeCommunity() + if (homeCom?.communityUuid) { return homeCom.communityUuid } } diff --git a/federation/src/graphql/api/1_0/util/authenticateCommunity.ts b/federation/src/graphql/api/1_0/util/authenticateCommunity.ts index 3083293d8..2167655af 100644 --- a/federation/src/graphql/api/1_0/util/authenticateCommunity.ts +++ b/federation/src/graphql/api/1_0/util/authenticateCommunity.ts @@ -3,35 +3,36 @@ import { Community as DbCommunity, FederatedCommunity as DbFedCommunity, FederatedCommunityLoggingView, + getHomeCommunity, } from 'database' import { getLogger } from 'log4js' -import { OpenConnectionArgs } from '../model/OpenConnectionArgs' -import { OpenConnectionCallbackArgs } from '../model/OpenConnectionCallbackArgs' +import { EncryptedTransferArgs } from 'core/src/graphql/model/EncryptedTransferArgs' import { AuthenticationClientFactory } from '@/client/AuthenticationClientFactory' import { randombytes_random } from 'sodium-native' import { AuthenticationClient as V1_0_AuthenticationClient } from '@/client/1_0/AuthenticationClient' import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const' -import { AuthenticationArgs } from '../model/AuthenticationArgs' -import { encryptAndSign } from 'backend/src/auth/jwt/JWT' -import { OpenConnectionCallbackJwtPayloadType } from 'backend/src/auth/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType' +import { encryptAndSign } from 'core/src/auth/jwt/JWT' +import { OpenConnectionCallbackJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/OpenConnectionCallbackJwtPayloadType' +import { AuthenticationJwtPayloadType } from 'core/src/auth/jwt/payloadtypes/AuthenticationJwtPayloadType' const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.api.1_0.util.authenticateCommunity`) export async function startOpenConnectionCallback( - comA: DbCommunity, + publicKey: string, api: string, ): Promise { logger.debug(`Authentication: startOpenConnectionCallback() with:`, { - comA: new CommunityLoggingView(comA), + publicKey, }) try { - const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) + const homeCom = await getHomeCommunity() const homeFedCom = await DbFedCommunity.findOneByOrFail({ foreign: false, apiVersion: api, }) + const comA = await DbCommunity.findOneByOrFail({ publicKey: Buffer.from(publicKey, 'hex') }) const fedComA = await DbFedCommunity.findOneByOrFail({ foreign: true, apiVersion: api, @@ -55,12 +56,15 @@ export async function startOpenConnectionCallback( const callbackArgs = new OpenConnectionCallbackJwtPayloadType(oneTimeCode, url) logger.debug(`Authentication: start openConnectionCallback with args:`, callbackArgs) - // encrypt callbackArgs with requestedCom.publicKey and sign it with homeCom.privateKey - const encryptedCallbackArgs = await encryptAndSign(callbackArgs, homeCom.privateJwtKey!, comA.publicJwtKey!) - if (await client.openConnectionCallback(encryptedCallbackArgs)) { - logger.debug('startOpenConnectionCallback() successful:', encryptedCallbackArgs) + // encrypt callbackArgs with requestedCom.publicJwtKey and sign it with homeCom.privateJwtKey + const jwt = await encryptAndSign(callbackArgs, homeCom!.privateJwtKey!, comA.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = comA.publicKey.toString('hex') + args.jwt = jwt + if (await client.openConnectionCallback(args)) { + logger.debug('startOpenConnectionCallback() successful:', jwt) } else { - logger.error('startOpenConnectionCallback() failed:', encryptedCallbackArgs) + logger.error('startOpenConnectionCallback() failed:', jwt) } } } catch (err) { @@ -77,20 +81,26 @@ export async function startAuthentication( fedComB: new FederatedCommunityLoggingView(fedComB), }) try { - const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) + const homeCom = await getHomeCommunity() + const comB = await DbCommunity.findOneByOrFail({ + foreign: true, + publicKey: fedComB.publicKey, + }) + if (!comB.publicJwtKey) { + throw new Error('Public JWT key still not exist for foreign community') + } - // TODO encrypt homeCom.uuid with homeCom.privateKey and sign it with callbackFedCom.publicKey const client = AuthenticationClientFactory.getInstance(fedComB) if (client instanceof V1_0_AuthenticationClient) { - const authenticationArgs = new AuthenticationArgs() - authenticationArgs.oneTimeCode = oneTimeCode - // TODO encrypt callbackArgs.url with requestedCom.publicKey and sign it with homeCom.privateKey - if (homeCom.communityUuid) { - authenticationArgs.uuid = homeCom.communityUuid - } - logger.debug(`invoke authenticate() with:`, authenticationArgs) - const fedComUuid = await client.authenticate(authenticationArgs) + const authenticationArgs = new AuthenticationJwtPayloadType(oneTimeCode, homeCom!.communityUuid!) + // encrypt authenticationArgs.uuid with fedComB.publicJwtKey and sign it with homeCom.privateJwtKey + const jwt = await encryptAndSign(authenticationArgs, homeCom!.privateJwtKey!, comB.publicJwtKey!) + const args = new EncryptedTransferArgs() + args.publicKey = comB.publicKey.toString('hex') + args.jwt = jwt + logger.debug(`invoke authenticate() with:`, args) + const fedComUuid = await client.authenticate(args) logger.debug(`response of authenticate():`, fedComUuid) if (fedComUuid !== null) { logger.debug(