From 59a194378a8419462478dd8fe5e8f0ed3de43904 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 21 Feb 2024 18:34:00 -0800 Subject: [PATCH] Resolves https://github.com/apple/app-store-server-library-node/issues/85, add appAppleId + Production IllegalArgumentException --- README.md | 3 ++- jws_verification.ts | 3 +++ tests/unit-tests/jws_verification.test.ts | 16 ++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1eecc0d..499b357 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,9 @@ const bundleId = "com.example" const filePath = "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8" const encodedKey = readFile(filePath) // Specific implementation may vary const environment = Environment.SANDBOX +const appAppleId = undefined // appAppleId is required when the environment is Production -const client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment) +const client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment, appAppleId) try { const response: SendTestNotificationResponse = await client.requestTestNotification() diff --git a/jws_verification.ts b/jws_verification.ts index e2ce194..02b2da7 100644 --- a/jws_verification.ts +++ b/jws_verification.ts @@ -57,6 +57,9 @@ export class SignedDataVerifier { this.bundleId = bundleId; this.environment = environment this.appAppleId = appAppleId + if (environment === Environment.PRODUCTION && appAppleId === undefined) { + throw new Error("appAppleId is required when the environment is Production") + } } /** diff --git a/tests/unit-tests/jws_verification.test.ts b/tests/unit-tests/jws_verification.test.ts index 9fc4d20..bc46919 100644 --- a/tests/unit-tests/jws_verification.test.ts +++ b/tests/unit-tests/jws_verification.test.ts @@ -34,7 +34,7 @@ class SignedJWTVerifierTest extends SignedDataVerifier { describe("Chain Verification Checks", () => { it('should validate a chain without OCSP', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example", 1234); const publicKey = await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) expect(Buffer.from(LEAF_CERT_PUBLIC_KEY_BASE64_ENCODED, 'base64')).toMatchObject(publicKey.export({ type: 'spki', @@ -43,7 +43,7 @@ describe("Chain Verification Checks", () => { }) it('should fail to validate a chain with an invalid intermediate OID', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example", 1234); try { await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_FOR_INTERMEDIATE_CA_INVALID_OID_BASE64_ENCODED, INTERMEDIATE_CA_INVALID_OID_BASE64_ENCODED) assert(false) @@ -54,7 +54,7 @@ describe("Chain Verification Checks", () => { }) it('should fail to validate a chain with an invalid leaf OID', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example", 1234); try { await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_INVALID_OID_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) assert(false) @@ -65,7 +65,7 @@ describe("Chain Verification Checks", () => { }) it('should fail to validate a chain with empty root certificate array', async () => { - const verifier = new SignedJWTVerifierTest([], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([], false, Environment.PRODUCTION, "com.example", 1234); try { await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) assert(false) @@ -76,7 +76,7 @@ describe("Chain Verification Checks", () => { }) it('should fail to validate a chain with an expired chain', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(ROOT_CA_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example", 1234); verifier.effectiveDate = new Date(2280946846000) try { await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) @@ -88,12 +88,12 @@ describe("Chain Verification Checks", () => { }) it('should validate a real chain with OCSP', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(REAL_APPLE_ROOT_BASE64_ENCODED, 'base64')], true, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(REAL_APPLE_ROOT_BASE64_ENCODED, 'base64')], true, Environment.PRODUCTION, "com.example", 1234); await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, REAL_APPLE_INTERMEDIATE_BASE64_ENCODED) }) it('should fail to validate a chain with mismatched root certificates', async () => { - const verifier = new SignedJWTVerifierTest([Buffer.from(REAL_APPLE_ROOT_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from(REAL_APPLE_ROOT_BASE64_ENCODED, 'base64')], false, Environment.PRODUCTION, "com.example", 1234); try { await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) assert(false) @@ -106,7 +106,7 @@ describe("Chain Verification Checks", () => { it('should fail to validate a chain with invalid root certificates', async () => { try { - const verifier = new SignedJWTVerifierTest([Buffer.from("abc", "utf-8")], false, Environment.PRODUCTION, "com.example"); + const verifier = new SignedJWTVerifierTest([Buffer.from("abc", "utf-8")], false, Environment.PRODUCTION, "com.example", 1234); await verifier.testVerifyCertificateChain(verifier.getRootCertificates(), LEAF_CERT_BASE64_ENCODED, INTERMEDIATE_CA_BASE64_ENCODED) } catch (e) { return