From eb5e94dbf8141e1ca01c59aba9be26b896876b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Tue, 1 Apr 2025 01:53:25 +0900 Subject: [PATCH] =?UTF-8?q?fix(SSO):=20JWK=E9=96=A2=E6=95=B0=E3=81=AE?= =?UTF-8?q?=E4=BB=95=E6=A7=98=E5=A4=89=E6=9B=B4=E3=81=AB=E5=AF=BE=E5=BF=9C?= =?UTF-8?q?=20(MisskeyIO#959)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MisskeyIO#950 --- packages/backend/src/misc/gen-x509-cert-from-jwk.ts | 5 +++-- .../backend/src/server/api/endpoints/admin/sso/create.ts | 3 ++- .../backend/src/server/api/endpoints/admin/sso/update.ts | 3 ++- .../backend/src/server/sso/JWTIdentifyProviderService.ts | 8 ++++---- .../backend/src/server/sso/SAMLIdentifyProviderService.ts | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/misc/gen-x509-cert-from-jwk.ts b/packages/backend/src/misc/gen-x509-cert-from-jwk.ts index 4eb64e705..2d5698daa 100644 --- a/packages/backend/src/misc/gen-x509-cert-from-jwk.ts +++ b/packages/backend/src/misc/gen-x509-cert-from-jwk.ts @@ -7,6 +7,7 @@ export async function genX509CertFromJWK( notAfter: Date, publicKey: string, privateKey: string, + alg: string, ): Promise { const cert = forge.pki.createCertificate(); cert.serialNumber = '01'; @@ -17,13 +18,13 @@ export async function genX509CertFromJWK( cert.setSubject(attrs); cert.setIssuer(attrs); cert.publicKey = await jose - .importJWK(JSON.parse(publicKey)) + .importJWK(JSON.parse(publicKey), alg) .then((k) => jose.exportSPKI(k as jose.CryptoKey)) .then((k) => forge.pki.publicKeyFromPem(k)); cert.sign( await jose - .importJWK(JSON.parse(privateKey)) + .importJWK(JSON.parse(privateKey), alg) .then((k) => jose.exportPKCS8(k as jose.CryptoKey)) .then((k) => forge.pki.privateKeyFromPem(k)), forge.md.sha256.create(), diff --git a/packages/backend/src/server/api/endpoints/admin/sso/create.ts b/packages/backend/src/server/api/endpoints/admin/sso/create.ts index 8d58880f5..79cfafe9c 100644 --- a/packages/backend/src/server/api/endpoints/admin/sso/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/sso/create.ts @@ -123,7 +123,7 @@ export default class extends Endpoint { // eslint- } const { publicKey, privateKey } = ps.useCertificate - ? await jose.generateKeyPair(ps.signatureAlgorithm).then(async keypair => ({ + ? await jose.generateKeyPair(ps.signatureAlgorithm, { extractable: true }).then(async keypair => ({ publicKey: JSON.stringify(await jose.exportJWK(keypair.publicKey)), privateKey: JSON.stringify(await jose.exportJWK(keypair.privateKey)), })) @@ -139,6 +139,7 @@ export default class extends Endpoint { // eslint- tenYearsLaterTime, publicKey, privateKey ?? '', + ps.signatureAlgorithm, ) : undefined; const ssoServiceProvider = await this.singleSignOnServiceProviderRepository.insert({ diff --git a/packages/backend/src/server/api/endpoints/admin/sso/update.ts b/packages/backend/src/server/api/endpoints/admin/sso/update.ts index 552415daf..da8597cb4 100644 --- a/packages/backend/src/server/api/endpoints/admin/sso/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/sso/update.ts @@ -60,7 +60,7 @@ export default class extends Endpoint { // eslint- const alg = ps.signatureAlgorithm ? ps.signatureAlgorithm : service.signatureAlgorithm; const { publicKey, privateKey } = ps.regenerateCertificate - ? await jose.generateKeyPair(alg).then(async keypair => ({ + ? await jose.generateKeyPair(alg, { extractable: true }).then(async keypair => ({ publicKey: JSON.stringify(await jose.exportJWK(keypair.publicKey)), privateKey: JSON.stringify(await jose.exportJWK(keypair.privateKey)), })) @@ -76,6 +76,7 @@ export default class extends Endpoint { // eslint- tenYearsLaterTime, publicKey ?? '', privateKey ?? '', + alg, ) : undefined; await this.singleSignOnServiceProviderRepository.update(service.id, { diff --git a/packages/backend/src/server/sso/JWTIdentifyProviderService.ts b/packages/backend/src/server/sso/JWTIdentifyProviderService.ts index 63e412ff1..4e202688f 100644 --- a/packages/backend/src/server/sso/JWTIdentifyProviderService.ts +++ b/packages/backend/src/server/sso/JWTIdentifyProviderService.ts @@ -193,7 +193,7 @@ export class JWTIdentifyProviderService { try { if (ssoServiceProvider.cipherAlgorithm) { const key = ssoServiceProvider.publicKey.startsWith('{') - ? await jose.importJWK(JSON.parse(ssoServiceProvider.publicKey)) + ? await jose.importJWK(JSON.parse(ssoServiceProvider.publicKey), ssoServiceProvider.signatureAlgorithm) : jose.base64url.decode(ssoServiceProvider.publicKey); jwt = await new jose.EncryptJWT(payload) @@ -211,7 +211,7 @@ export class JWTIdentifyProviderService { .encrypt(key); } else { const key = ssoServiceProvider.privateKey - ? await jose.importJWK(JSON.parse(ssoServiceProvider.privateKey)) + ? await jose.importJWK(JSON.parse(ssoServiceProvider.privateKey), ssoServiceProvider.signatureAlgorithm) : jose.base64url.decode(ssoServiceProvider.publicKey); jwt = await new jose.SignJWT(payload) @@ -311,7 +311,7 @@ export class JWTIdentifyProviderService { try { if (ssoServiceProvider.cipherAlgorithm) { const key = ssoServiceProvider.privateKey - ? await jose.importJWK(JSON.parse(ssoServiceProvider.privateKey)) + ? await jose.importJWK(JSON.parse(ssoServiceProvider.privateKey), ssoServiceProvider.signatureAlgorithm) : jose.base64url.decode(ssoServiceProvider.publicKey); const { payload } = await jose.jwtDecrypt(jwt, key, { @@ -323,7 +323,7 @@ export class JWTIdentifyProviderService { return; } else { const key = ssoServiceProvider.publicKey.startsWith('{') - ? await jose.importJWK(JSON.parse(ssoServiceProvider.publicKey)) + ? await jose.importJWK(JSON.parse(ssoServiceProvider.publicKey), ssoServiceProvider.signatureAlgorithm) : jose.base64url.decode(ssoServiceProvider.publicKey); const { payload } = await jose.jwtVerify(jwt, key, { diff --git a/packages/backend/src/server/sso/SAMLIdentifyProviderService.ts b/packages/backend/src/server/sso/SAMLIdentifyProviderService.ts index 63ca46ddb..fcae13987 100644 --- a/packages/backend/src/server/sso/SAMLIdentifyProviderService.ts +++ b/packages/backend/src/server/sso/SAMLIdentifyProviderService.ts @@ -238,7 +238,7 @@ export class SAMLIdentifyProviderService { const idp = saml.IdentityProvider({ metadata: await this.createIdPMetadataXml(ssoServiceProvider), privateKey: await jose - .importJWK(JSON.parse(ssoServiceProvider.privateKey ?? '{}')) + .importJWK(JSON.parse(ssoServiceProvider.privateKey ?? '{}'), ssoServiceProvider.signatureAlgorithm) .then(k => jose.exportPKCS8(k as jose.CryptoKey)), }); @@ -392,7 +392,7 @@ export class SAMLIdentifyProviderService { const idp = saml.IdentityProvider({ metadata: await this.createIdPMetadataXml(ssoServiceProvider), privateKey: await jose - .importJWK(JSON.parse(ssoServiceProvider.privateKey ?? '{}')) + .importJWK(JSON.parse(ssoServiceProvider.privateKey ?? '{}'), ssoServiceProvider.signatureAlgorithm) .then(k => jose.exportPKCS8(k as jose.CryptoKey)), loginResponseTemplate: { context: 'ignored' }, });