diff --git a/index.ts b/index.ts index 9c87583..6327a22 100644 --- a/index.ts +++ b/index.ts @@ -1,84 +1,84 @@ // Copyright (c) 2023 Apple Inc. Licensed under MIT License. import fetch from 'node-fetch'; -import { CheckTestNotificationResponse, CheckTestNotificationResponseValidator } from './models/CheckTestNotificationResponse'; +import { type CheckTestNotificationResponse, CheckTestNotificationResponseValidator } from './models/CheckTestNotificationResponse'; import { ConsumptionRequest } from './models/ConsumptionRequest'; import { Environment } from './models/Environment'; -import { ExtendRenewalDateRequest } from './models/ExtendRenewalDateRequest'; -import { ExtendRenewalDateResponse, ExtendRenewalDateResponseValidator } from './models/ExtendRenewalDateResponse'; -import { HistoryResponse, HistoryResponseValidator } from './models/HistoryResponse'; -import { MassExtendRenewalDateRequest } from './models/MassExtendRenewalDateRequest'; -import { MassExtendRenewalDateResponse, MassExtendRenewalDateResponseValidator } from './models/MassExtendRenewalDateResponse'; -import { MassExtendRenewalDateStatusResponse, MassExtendRenewalDateStatusResponseValidator } from './models/MassExtendRenewalDateStatusResponse'; -import { OrderLookupResponse, OrderLookupResponseValidator } from './models/OrderLookupResponse'; -import { RefundHistoryResponse, RefundHistoryResponseValidator } from './models/RefundHistoryResponse'; -import { SendTestNotificationResponse, SendTestNotificationResponseValidator } from './models/SendTestNotificationResponse'; -import { StatusResponse, StatusResponseValidator } from './models/StatusResponse'; -import { TransactionHistoryRequest } from './models/TransactionHistoryRequest'; -import { TransactionInfoResponse, TransactionInfoResponseValidator } from './models/TransactionInfoResponse'; -import { Validator } from './models/Validator'; +import type { ExtendRenewalDateRequest } from './models/ExtendRenewalDateRequest'; +import { type ExtendRenewalDateResponse, ExtendRenewalDateResponseValidator } from './models/ExtendRenewalDateResponse'; +import { type HistoryResponse, HistoryResponseValidator } from './models/HistoryResponse'; +import { type MassExtendRenewalDateRequest } from './models/MassExtendRenewalDateRequest'; +import { type MassExtendRenewalDateResponse, MassExtendRenewalDateResponseValidator } from './models/MassExtendRenewalDateResponse'; +import { type MassExtendRenewalDateStatusResponse, MassExtendRenewalDateStatusResponseValidator } from './models/MassExtendRenewalDateStatusResponse'; +import { type OrderLookupResponse, OrderLookupResponseValidator } from './models/OrderLookupResponse'; +import { type RefundHistoryResponse, RefundHistoryResponseValidator } from './models/RefundHistoryResponse'; +import { type SendTestNotificationResponse, SendTestNotificationResponseValidator } from './models/SendTestNotificationResponse'; +import { type StatusResponse, StatusResponseValidator } from './models/StatusResponse'; +import { type TransactionHistoryRequest } from './models/TransactionHistoryRequest'; +import { type TransactionInfoResponse, TransactionInfoResponseValidator } from './models/TransactionInfoResponse'; +import type { Validator } from './models/Validator'; import { Status } from './models/Status'; export { SignedDataVerifier, VerificationException, VerificationStatus } from './jws_verification' export { ReceiptUtility } from './receipt_utility' export { AccountTenure } from "./models/AccountTenure" export { AutoRenewStatus } from './models/AutoRenewStatus' -export { CheckTestNotificationResponse } from './models/CheckTestNotificationResponse' -export { ConsumptionRequest } from './models/ConsumptionRequest' +export type { CheckTestNotificationResponse } from './models/CheckTestNotificationResponse' +export type { ConsumptionRequest } from './models/ConsumptionRequest' export { ConsumptionStatus } from './models/ConsumptionStatus' -export { Data } from './models/Data' +export type { Data } from './models/Data' export { DeliveryStatus } from './models/DeliveryStatus' export { Environment } from './models/Environment' export { ExpirationIntent } from './models/ExpirationIntent' export { ExtendReasonCode } from './models/ExtendReasonCode' -export { ExtendRenewalDateRequest } from './models/ExtendRenewalDateRequest' -export { ExtendRenewalDateResponse } from './models/ExtendRenewalDateResponse' +export type { ExtendRenewalDateRequest } from './models/ExtendRenewalDateRequest' +export type { ExtendRenewalDateResponse } from './models/ExtendRenewalDateResponse' export { SendAttemptResult } from './models/SendAttemptResult' -export { SendAttemptItem } from './models/SendAttemptItem' -export { HistoryResponse } from './models/HistoryResponse' +export type { SendAttemptItem } from './models/SendAttemptItem' +export type { HistoryResponse } from './models/HistoryResponse' export { InAppOwnershipType } from './models/InAppOwnershipType' -export { JWSRenewalInfoDecodedPayload } from './models/JWSRenewalInfoDecodedPayload' -export { JWSTransactionDecodedPayload } from './models/JWSTransactionDecodedPayload' -export { LastTransactionsItem } from './models/LastTransactionsItem' +export type { JWSRenewalInfoDecodedPayload } from './models/JWSRenewalInfoDecodedPayload' +export type { JWSTransactionDecodedPayload } from './models/JWSTransactionDecodedPayload' +export type { LastTransactionsItem } from './models/LastTransactionsItem' export { LifetimeDollarsPurchased } from './models/LifetimeDollarsPurchased' export { LifetimeDollarsRefunded } from './models/LifetimeDollarsRefunded' -export { MassExtendRenewalDateRequest } from './models/MassExtendRenewalDateRequest' -export { MassExtendRenewalDateResponse } from './models/MassExtendRenewalDateResponse' -export { MassExtendRenewalDateStatusResponse } from './models/MassExtendRenewalDateStatusResponse' -export { NotificationHistoryRequest } from './models/NotificationHistoryRequest' -export { NotificationHistoryResponse } from './models/NotificationHistoryResponse' -export { NotificationHistoryResponseItem } from './models/NotificationHistoryResponseItem' +export type { MassExtendRenewalDateRequest } from './models/MassExtendRenewalDateRequest' +export type { MassExtendRenewalDateResponse } from './models/MassExtendRenewalDateResponse' +export type { MassExtendRenewalDateStatusResponse } from './models/MassExtendRenewalDateStatusResponse' +export type { NotificationHistoryRequest } from './models/NotificationHistoryRequest' +export type { NotificationHistoryResponse } from './models/NotificationHistoryResponse' +export type { NotificationHistoryResponseItem } from './models/NotificationHistoryResponseItem' export { NotificationTypeV2 } from './models/NotificationTypeV2' export { OfferType } from './models/OfferType' export { OfferDiscountType } from './models/OfferDiscountType' -export { OrderLookupResponse } from './models/OrderLookupResponse' +export type { OrderLookupResponse } from './models/OrderLookupResponse' export { OrderLookupStatus } from './models/OrderLookupStatus' export { Platform } from './models/Platform' export { PlayTime } from './models/PlayTime' export { PriceIncreaseStatus } from './models/PriceIncreaseStatus' export { PurchasePlatform } from './models/PurchasePlatform' -export { RefundHistoryResponse } from './models/RefundHistoryResponse' -export { ResponseBodyV2 } from './models/ResponseBodyV2' -export { ResponseBodyV2DecodedPayload } from './models/ResponseBodyV2DecodedPayload' +export type { RefundHistoryResponse } from './models/RefundHistoryResponse' +export type { ResponseBodyV2 } from './models/ResponseBodyV2' +export type { ResponseBodyV2DecodedPayload } from './models/ResponseBodyV2DecodedPayload' export { RevocationReason } from './models/RevocationReason' -export { SendTestNotificationResponse } from './models/SendTestNotificationResponse' +export type { SendTestNotificationResponse } from './models/SendTestNotificationResponse' export { Status } from './models/Status' -export { StatusResponse } from './models/StatusResponse' -export { SubscriptionGroupIdentifierItem } from './models/SubscriptionGroupIdentifierItem' +export type { StatusResponse } from './models/StatusResponse' +export type { SubscriptionGroupIdentifierItem } from './models/SubscriptionGroupIdentifierItem' export { Subtype } from './models/Subtype' -export { Summary } from './models/Summary' -export { TransactionHistoryRequest, Order, ProductType } from './models/TransactionHistoryRequest' -export { TransactionInfoResponse } from './models/TransactionInfoResponse' +export type { Summary } from './models/Summary' +export { type TransactionHistoryRequest, Order, ProductType } from './models/TransactionHistoryRequest' +export type { TransactionInfoResponse } from './models/TransactionInfoResponse' export { TransactionReason } from './models/TransactionReason' export { Type } from './models/Type' export { UserStatus } from './models/UserStatus' export { PromotionalOfferSignatureCreator } from './promotional_offer' -export { PromotionalOfferV2SignatureCreator, AdvancedCommerceInAppSignatureCreator, AdvancedCommerceInAppRequest, IntroductoryOfferEligibilitySignatureCreator } from './jws_signature_creator' -export { DecodedSignedData } from './models/DecodedSignedData' -export { AppTransaction } from './models/AppTransaction' +export { PromotionalOfferV2SignatureCreator, AdvancedCommerceInAppSignatureCreator, type AdvancedCommerceInAppRequest, IntroductoryOfferEligibilitySignatureCreator } from './jws_signature_creator' +export type { DecodedSignedData } from './models/DecodedSignedData' +export type { AppTransaction } from './models/AppTransaction' import jsonwebtoken = require('jsonwebtoken'); -import { NotificationHistoryRequest } from './models/NotificationHistoryRequest'; -import { NotificationHistoryResponse, NotificationHistoryResponseValidator } from './models/NotificationHistoryResponse'; +import type { NotificationHistoryRequest } from './models/NotificationHistoryRequest'; +import { type NotificationHistoryResponse, NotificationHistoryResponseValidator } from './models/NotificationHistoryResponse'; import { URLSearchParams } from 'url'; export class AppStoreServerAPIClient { diff --git a/jws_verification.ts b/jws_verification.ts index 2ca0112..4685dcb 100644 --- a/jws_verification.ts +++ b/jws_verification.ts @@ -3,7 +3,7 @@ import jsonwebtoken = require('jsonwebtoken'); import base64url from 'base64url'; -import { KeyObject, X509Certificate, createHash, verify } from 'crypto'; +import { KeyObject, X509Certificate, createHash, verify, webcrypto } from 'crypto'; import { KJUR, X509, ASN1HEX } from 'jsrsasign'; import fetch, { Headers } from 'node-fetch'; import { Environment } from './models/Environment'; @@ -13,6 +13,7 @@ import { JWSRenewalInfoDecodedPayload, JWSRenewalInfoDecodedPayloadValidator } f import { Validator } from './models/Validator'; import { DecodedSignedData } from './models/DecodedSignedData'; import { AppTransaction, AppTransactionValidator } from './models/AppTransaction'; +import { isCryptoKey } from 'util/types'; const MAX_SKEW = 60000 @@ -31,11 +32,11 @@ class CacheValue { /** * A class providing utility methods for verifying and decoding App Store signed data. - * + * * Example Usage: * ```ts * const verifier = new SignedDataVerifier([appleRoot, appleRoot2], true, Environment.SANDBOX, "com.example") - * + * * try { * const decodedNotification = verifier.verifyAndDecodeNotification("ey...") * console.log(decodedNotification) @@ -58,8 +59,8 @@ export class SignedDataVerifier { protected verifiedPublicKeyCache: { [index: string]: CacheValue } /** - * - * @param appleRootCertificates A list of DER-encoded root certificates + * + * @param appleRootCertificates A list of DER-encoded root certificates * @param enableOnlineChecks Whether to enable revocation checking and check expiration using the current date * @param environment The App Store environment to target for checks * @param bundleId The app's bundle identifier @@ -176,6 +177,13 @@ export class SignedDataVerifier { return decodedAppTransaction } + protected getKeyFrom(publicKey: KeyObject | webcrypto.CryptoKey){ + if (isCryptoKey(publicKey)) { + return KeyObject.from(publicKey) + } + return publicKey + } + protected async verifyJWT(jwt: string, validator: Validator, signedDateExtractor: (decodedJWT: T) => Date): Promise { let certificateChain; let decodedJWT @@ -227,7 +235,7 @@ export class SignedDataVerifier { if (this.enableOnlineChecks) { if (cacheKey in this.verifiedPublicKeyCache) { if (this.verifiedPublicKeyCache[cacheKey].cacheExpiry > new Date().getTime()) { - return this.verifiedPublicKeyCache[cacheKey].publicKey + return this.getKeyFrom(this.verifiedPublicKeyCache[cacheKey].publicKey) } } } @@ -244,7 +252,7 @@ export class SignedDataVerifier { } } } - return publicKey + return this.getKeyFrom(publicKey) } protected async verifyCertificateChainWithoutCaching(trustedRoots: X509Certificate[], leaf: X509Certificate, intermediate: X509Certificate, effectiveDate: Date): Promise { @@ -285,13 +293,13 @@ export class SignedDataVerifier { const request = new KJUR.asn1.ocsp.OCSPRequest({reqList: [{issuerCert: issuer.toString(), subjectCert: cert.toString() , alg: "sha256"}]}) const headers = new Headers() headers.append('Content-Type', 'application/ocsp-request') - + const response = await fetch(matchResult[1], { headers: headers, method: 'POST', body: Buffer.from(request.getEncodedHex(), 'hex') }) - + const responseBuffer = await response.buffer() const parsedResponse = new (KJUR.asn1.ocsp as any).OCSPParser().getOCSPResponse(responseBuffer.toString('hex')) // The issuer could also be the signer @@ -337,7 +345,7 @@ export class SignedDataVerifier { } else { throw new VerificationException(VerificationStatus.INVALID_CERTIFICATE) } - + // Extract raw responseData const responseData = ASN1HEX.getTLVbyList(responseBuffer.toString('hex'), 0, [1, 0, 1, 0, 0]) as string // Verify Payload signed by cert @@ -349,7 +357,7 @@ export class SignedDataVerifier { if (!verify(shortAlg, Buffer.from(responseData, 'hex'), signingCert.publicKey, Buffer.from(parsedResponse.sighex, 'hex'))) { throw new VerificationException(VerificationStatus.FAILURE) } - + for (const singleResponse of parsedResponse.array) { // Confirm entry is for this cert const certIdBuilder = new KJUR.asn1.ocsp.CertID() as any @@ -361,7 +369,7 @@ export class SignedDataVerifier { // Validate contents const issueDate = this.parseX509Date(singleResponse.thisupdate) const nextDate = this.parseX509Date(singleResponse.nextupdate) - + if (singleResponse.status.status !== 'good' || new Date().getTime() - MAX_SKEW < issueDate.getTime() || nextDate.getTime() < new Date().getTime() + MAX_SKEW) { throw new VerificationException(VerificationStatus.FAILURE) } @@ -409,4 +417,4 @@ export class VerificationException extends Error { this.status = status this.cause = cause } -} \ No newline at end of file +} diff --git a/models/ExtendRenewalDateRequest.ts b/models/ExtendRenewalDateRequest.ts index 821667e..61d7f9d 100644 --- a/models/ExtendRenewalDateRequest.ts +++ b/models/ExtendRenewalDateRequest.ts @@ -1,6 +1,6 @@ // Copyright (c) 2023 Apple Inc. Licensed under MIT License. -import { ExtendReasonCode, ExtendReasonCodeValidator } from "./ExtendReasonCode" +import { ExtendReasonCode } from "./ExtendReasonCode" /** * The request body that contains subscription-renewal-extension data for an individual subscription. diff --git a/models/MassExtendRenewalDateRequest.ts b/models/MassExtendRenewalDateRequest.ts index e5accaf..314e9a8 100644 --- a/models/MassExtendRenewalDateRequest.ts +++ b/models/MassExtendRenewalDateRequest.ts @@ -1,6 +1,6 @@ // Copyright (c) 2023 Apple Inc. Licensed under MIT License. -import { ExtendReasonCode, ExtendReasonCodeValidator } from "./ExtendReasonCode"; +import { ExtendReasonCode } from "./ExtendReasonCode"; /** * The request body that contains subscription-renewal-extension data to apply for all eligible active subscribers. diff --git a/models/NotificationTypeV2.ts b/models/NotificationTypeV2.ts index 93da5d4..20af4dd 100644 --- a/models/NotificationTypeV2.ts +++ b/models/NotificationTypeV2.ts @@ -1,6 +1,6 @@ // Copyright (c) 2023 Apple Inc. Licensed under MIT License. -import { StringValidator, Validator } from "./Validator"; +import { StringValidator } from "./Validator"; /** * The type that describes the in-app purchase or external purchase event for which the App Store sends the version 2 notification. diff --git a/tests/unit-tests/jws_verification.test.ts b/tests/unit-tests/jws_verification.test.ts index a52b903..5d12d63 100644 --- a/tests/unit-tests/jws_verification.test.ts +++ b/tests/unit-tests/jws_verification.test.ts @@ -8,7 +8,7 @@ import { readFile, getSignedPayloadVerifierWithDefaultAppAppleId, getDefaultSign const ROOT_CA_BASE64_ENCODED = "MIIBgjCCASmgAwIBAgIJALUc5ALiH5pbMAoGCCqGSM49BAMDMDYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8wHhcNMjMwMTA1MjEzMDIyWhcNMzMwMTAyMjEzMDIyWjA2MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc+/Bl+gospo6tf9Z7io5tdKdrlN1YdVnqEhEDXDShzdAJPQijamXIMHf8xWWTa1zgoYTxOKpbuJtDplz1XriTaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDRwAwRAIgemWQXnMAdTad2JDJWng9U4uBBL5mA7WI05H7oH7c6iQCIHiRqMjNfzUAyiu9h6rOU/K+iTR0I/3Y/NSWsXHX+acc"; const INTERMEDIATE_CA_BASE64_ENCODED = "MIIBnzCCAUWgAwIBAgIBCzAKBggqhkjOPQQDAzA2MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMB4XDTIzMDEwNTIxMzEwNVoXDTMzMDEwMTIxMzEwNVowRTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlDdXBlcnRpbm8xFTATBgNVBAoMDEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBUN5V9rKjfRiMAIojEA0Av5Mp0oF+O0cL4gzrTF178inUHugj7Et46NrkQ7hKgMVnjogq45Q1rMs+cMHVNILWqjNTAzMA8GA1UdEwQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMBAGCiqGSIb3Y2QGAgEEAgUAMAoGCCqGSM49BAMDA0gAMEUCIQCmsIKYs41ullssHX4rVveUT0Z7Is5/hLK1lFPTtun3hAIgc2+2RG5+gNcFVcs+XJeEl4GZ+ojl3ROOmll+ye7dynQ="; -const LEAF_CERT_BASE64_ENCODED = "MIIBoDCCAUagAwIBAgIBDDAKBggqhkjOPQQDAzBFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUN1cGVydGlubzEVMBMGA1UECgwMSW50ZXJtZWRpYXRlMB4XDTIzMDEwNTIxMzEzNFoXDTMzMDEwMTIxMzEzNFowPTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlDdXBlcnRpbm8xDTALBgNVBAoMBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATitYHEaYVuc8g9AjTOwErMvGyPykPa+puvTI8hJTHZZDLGas2qX1+ErxgQTJgVXv76nmLhhRJH+j25AiAI8iGsoy8wLTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDAQBgoqhkiG92NkBgsBBAIFADAKBggqhkjOPQQDAwNIADBFAiBX4c+T0Fp5nJ5QRClRfu5PSByRvNPtuaTsk0vPB3WAIAIhANgaauAj/YP9s0AkEhyJhxQO/6Q2zouZ+H1CIOehnMzQ"; +const LEAF_CERT_BASE64_ENCODED = "MIIBoDCCAUagAwIBAgIBDDAKBggqhkjOPQQDAzBFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUN1cGVydGlubzEVMBMGA1UECgwMSW50ZXJtZWRpYXRlMB4XDTIzMDEwNTIxMzEzNFoXDTMzMDEwMTIxMzEzNFowPTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlDdXBlcnRpbm8xDTALBgNVBAoMBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATitYHEaYVuc8g9AjTOwErMvGyPykPa+puvTI8hJTHZZDLGas2qX1+ErxgQTJgVXv76nmLhhRJH+j25AiAI8iGsoy8wLTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDAQBgoqhkiG92NkBgsBBAIFADAKBggqhkjOPQQDAwNIADBFAiBX4c+T0Fp5nJ5QRClRfu5PSByRvNPtuaTsk0vPB3WAIAIhANgaauAj/YP9s0AkEhyJhxQO/6Q2zouZ+H1CIOehnMzQ"; const INTERMEDIATE_CA_INVALID_OID_BASE64_ENCODED = "MIIBnjCCAUWgAwIBAgIBDTAKBggqhkjOPQQDAzA2MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMB4XDTIzMDEwNTIxMzYxNFoXDTMzMDEwMTIxMzYxNFowRTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlDdXBlcnRpbm8xFTATBgNVBAoMDEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBUN5V9rKjfRiMAIojEA0Av5Mp0oF+O0cL4gzrTF178inUHugj7Et46NrkQ7hKgMVnjogq45Q1rMs+cMHVNILWqjNTAzMA8GA1UdEwQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMBAGCiqGSIb3Y2QGAgIEAgUAMAoGCCqGSM49BAMDA0cAMEQCIFROtTE+RQpKxNXETFsf7Mc0h+5IAsxxo/X6oCC/c33qAiAmC5rn5yCOOEjTY4R1H1QcQVh+eUwCl13NbQxWCuwxxA=="; const LEAF_CERT_FOR_INTERMEDIATE_CA_INVALID_OID_BASE64_ENCODED = "MIIBnzCCAUagAwIBAgIBDjAKBggqhkjOPQQDAzBFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUN1cGVydGlubzEVMBMGA1UECgwMSW50ZXJtZWRpYXRlMB4XDTIzMDEwNTIxMzY1OFoXDTMzMDEwMTIxMzY1OFowPTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlDdXBlcnRpbm8xDTALBgNVBAoMBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATitYHEaYVuc8g9AjTOwErMvGyPykPa+puvTI8hJTHZZDLGas2qX1+ErxgQTJgVXv76nmLhhRJH+j25AiAI8iGsoy8wLTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDAQBgoqhkiG92NkBgsBBAIFADAKBggqhkjOPQQDAwNHADBEAiAUAs+gzYOsEXDwQquvHYbcVymyNqDtGw9BnUFp2YLuuAIgXxQ3Ie9YU0cMqkeaFd+lyo0asv9eyzk6stwjeIeOtTU="; @@ -35,7 +35,7 @@ class SignedJWTVerifierTest extends SignedDataVerifier { getRootCertificates() { return this.rootCertificates - } + } } describe("Chain Verification Checks", () => { @@ -271,4 +271,4 @@ describe("Decoding checks", () => { const notification = await verifier.verifyAndDecodeRenewalInfo(transactionInfo) expect(notification.environment).toEqual(Environment.SANDBOX) }) -}); \ No newline at end of file +});