mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
change to encryption on openCommunication()
This commit is contained in:
parent
582fc6c58c
commit
de2566d09b
@ -1,6 +1,5 @@
|
||||
import { createPrivateKey, sign } from 'node:crypto'
|
||||
|
||||
import { JWTPayload, SignJWT, decodeJwt, jwtVerify } from 'jose'
|
||||
import { GeneralEncrypt, KeyLike, SignJWT, decodeJwt, jwtVerify } from 'jose'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
@ -68,3 +67,39 @@ export const decode = (token: string): JwtPayloadType => {
|
||||
const { payload } = decodeJwt(token)
|
||||
return payload as JwtPayloadType
|
||||
}
|
||||
|
||||
export const encrypt = async(payload: JwtPayloadType, encryptkey: KeyLike): Promise<string> => {
|
||||
logger.info('JWT.encrypt... payload=', payload)
|
||||
logger.info('JWT.encrypt... encryptkey=', encryptkey)
|
||||
try {
|
||||
// Convert the key to JWK format if needed
|
||||
const recipientKey = typeof encryptkey === 'string'
|
||||
? JSON.parse(encryptkey)
|
||||
: encryptkey;
|
||||
|
||||
const jwe = await new GeneralEncrypt(
|
||||
new TextEncoder().encode(JSON.stringify(payload)),
|
||||
)
|
||||
.setProtectedHeader({ enc: 'A256GCM' })
|
||||
.addRecipient(recipientKey)
|
||||
.setUnprotectedHeader({ alg: 'ECDH-ES+A256KW' })
|
||||
.encrypt()
|
||||
/*
|
||||
const token = await new EncryptJWT({ payload, 'urn:gradido:claim': true })
|
||||
.setProtectedHeader({
|
||||
alg: 'HS256',
|
||||
enc: 'A256GCM',
|
||||
})
|
||||
.setIssuedAt()
|
||||
.setIssuer('urn:gradido:issuer')
|
||||
.setAudience('urn:gradido:audience')
|
||||
.setExpirationTime(payload.expiration)
|
||||
.encrypt(encryptkey)
|
||||
*/
|
||||
logger.info('JWT.encrypt... jwe=', jwe)
|
||||
return jwe.toString()
|
||||
} catch (e) {
|
||||
logger.error('Failed to encrypt JWT:', e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
// import { JWTPayload } from 'jose'
|
||||
import { JwtPayloadType } from './JwtPayloadType'
|
||||
|
||||
export class OpenConnectionJwtPayloadType extends JwtPayloadType {
|
||||
static OPEN_CONNECTION_TYPE = 'open-connection'
|
||||
|
||||
url: string
|
||||
|
||||
constructor(
|
||||
url: string,
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
super()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
this.tokentype = OpenConnectionJwtPayloadType.OPEN_CONNECTION_TYPE
|
||||
this.url = url
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,9 @@ import { ensureUrlEndsWithSlash } from '@/util/utilities'
|
||||
|
||||
import { OpenConnectionArgs } from './client/1_0/model/OpenConnectionArgs'
|
||||
import { AuthenticationClientFactory } from './client/AuthenticationClientFactory'
|
||||
import { OpenConnectionJwtPayloadType } from '@/auth/jwt/payloadtypes/OpenConnectionJwtPayloadType'
|
||||
import { importSPKI } from 'jose'
|
||||
import { encrypt } from '@/auth/jwt/JWT'
|
||||
|
||||
export async function startCommunityAuthentication(
|
||||
foreignFedCom: DbFederatedCommunity,
|
||||
@ -36,14 +39,22 @@ export async function startCommunityAuthentication(
|
||||
const client = AuthenticationClientFactory.getInstance(foreignFedCom)
|
||||
|
||||
if (client instanceof V1_0_AuthenticationClient) {
|
||||
if (!foreignCom.publicJwtKey) {
|
||||
throw new Error('Public JWT key not found for foreign community')
|
||||
}
|
||||
const args = new OpenConnectionArgs()
|
||||
args.publicKey = homeCom.publicKey.toString('hex')
|
||||
// TODO encrypt url with foreignCom.publicKey and sign it with homeCom.privateKey
|
||||
args.url = ensureUrlEndsWithSlash(homeFedCom.endPoint).concat(homeFedCom.apiVersion)
|
||||
//create JWT with url in payload encrypted by foreignCom.publicKey and signed with homeCom.privateKey
|
||||
const payload = new OpenConnectionJwtPayloadType(
|
||||
ensureUrlEndsWithSlash(homeFedCom.endPoint).concat(homeFedCom.apiVersion),
|
||||
)
|
||||
const encryptKey = await importSPKI(foreignCom.publicJwtKey!, 'RS256')
|
||||
const jwt = await encrypt(payload, encryptKey)
|
||||
args.jwt = jwt
|
||||
logger.debug(
|
||||
'Authentication: before client.openConnection() args:',
|
||||
homeCom.publicKey.toString('hex'),
|
||||
args.url,
|
||||
args.jwt,
|
||||
)
|
||||
if (await client.openConnection(args)) {
|
||||
logger.debug(`Authentication: successful initiated at community:`, foreignFedCom.endPoint)
|
||||
|
||||
@ -6,5 +6,5 @@ export class OpenConnectionArgs {
|
||||
publicKey: string
|
||||
|
||||
@Field(() => String)
|
||||
url: string
|
||||
jwt: string
|
||||
}
|
||||
|
||||
@ -3,4 +3,5 @@ export interface PublicCommunityInfo {
|
||||
description: string
|
||||
creationDate: Date
|
||||
publicKey: string
|
||||
publicJwtKey: string
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ export const getPublicCommunityInfo = gql`
|
||||
description
|
||||
creationDate
|
||||
publicKey
|
||||
publicJwtKey
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@ -37,6 +37,7 @@ export async function startValidateCommunities(timerInterval: number): Promise<v
|
||||
}
|
||||
|
||||
export async function validateCommunities(): Promise<void> {
|
||||
// search all foreign federated communities which are still not verified or have not been verified since last dht-announcement
|
||||
const dbFederatedCommunities: DbFederatedCommunity[] =
|
||||
await DbFederatedCommunity.createQueryBuilder()
|
||||
.where({ foreign: true, verifiedAt: IsNull() })
|
||||
@ -104,12 +105,14 @@ export async function writeJwtKeyPairInHomeCommunity(): Promise<DbCommunity> {
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity publicKey=`, publicKeyPem);
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity privateKey=`, privateKeyPem);
|
||||
|
||||
homeCom.publicJwtKey = Buffer.from(publicKeyPem);
|
||||
homeCom.publicJwtKey = publicKeyPem;
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity publicJwtKey.length=`, homeCom.publicJwtKey.length);
|
||||
homeCom.privateJwtKey = Buffer.from(privateKeyPem);
|
||||
homeCom.privateJwtKey = privateKeyPem;
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity privateJwtKey.length=`, homeCom.privateJwtKey.length);
|
||||
await DbCommunity.save(homeCom)
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity done`)
|
||||
} else {
|
||||
logger.debug(`Federation: writeJwtKeyPairInHomeCommunity: keypair already exists`)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Error! A HomeCommunity-Entry still not exist! Please start the DHT-Modul first.`)
|
||||
@ -141,6 +144,7 @@ async function writeForeignCommunity(
|
||||
com.foreign = true
|
||||
com.name = pubInfo.name
|
||||
com.publicKey = dbCom.publicKey
|
||||
com.publicJwtKey = pubInfo.publicJwtKey
|
||||
com.url = dbCom.endPoint
|
||||
await DbCommunity.save(com)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ export class GetPublicCommunityInfoResultLoggingView extends AbstractLoggingView
|
||||
description: this.self.description,
|
||||
creationDate: this.dateToString(this.self.creationDate),
|
||||
publicKey: this.self.publicKey,
|
||||
publicJwtKey: this.self.publicJwtKey,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@ import { Field, ObjectType } from 'type-graphql'
|
||||
export class GetPublicCommunityInfoResult {
|
||||
constructor(dbCom: DbCommunity) {
|
||||
this.publicKey = dbCom.publicKey.toString('hex')
|
||||
if (dbCom.publicJwtKey) {
|
||||
this.publicJwtKey = dbCom.publicJwtKey
|
||||
}
|
||||
this.name = dbCom.name
|
||||
this.description = dbCom.description
|
||||
this.creationDate = dbCom.creationDate
|
||||
@ -22,4 +25,7 @@ export class GetPublicCommunityInfoResult {
|
||||
|
||||
@Field(() => String)
|
||||
publicKey: string
|
||||
|
||||
@Field(() => String)
|
||||
publicJwtKey: string
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user