Class: AppStore::SignedDataVerifier

Inherits:
Object
  • Object
show all
Defined in:
lib/app_store/signed_data_verifier.rb

Constant Summary collapse

ENVIRONMENTS =
{
  sandbox: 'Sandbox',
  production: 'Production',
  xcode: 'Xcode',
  local_testing: 'LocalTesting'
}.freeze
MAX_SKEW =
60_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root_certificates, environment, bundle_id, app_apple_id = nil) ⇒ SignedDataVerifier

Returns a new instance of SignedDataVerifier.



20
21
22
23
24
25
26
27
28
# File 'lib/app_store/signed_data_verifier.rb', line 20

def initialize(root_certificates, environment, bundle_id, app_apple_id = nil)
  @root_certificates = root_certificates.map { |cert| OpenSSL::X509::Certificate.new(cert) }
  @bundle_id = bundle_id
  @environment = environment
  @app_apple_id = app_apple_id
  return unless environment == ENVIRONMENTS[:production] && app_apple_id.nil?

  raise 'app_apple_id is required when the environment is Production'
end

Instance Attribute Details

#app_apple_idObject (readonly)

Returns the value of attribute app_apple_id.



18
19
20
# File 'lib/app_store/signed_data_verifier.rb', line 18

def app_apple_id
  @app_apple_id
end

#bundle_idObject (readonly)

Returns the value of attribute bundle_id.



18
19
20
# File 'lib/app_store/signed_data_verifier.rb', line 18

def bundle_id
  @bundle_id
end

#environmentObject (readonly)

Returns the value of attribute environment.



18
19
20
# File 'lib/app_store/signed_data_verifier.rb', line 18

def environment
  @environment
end

#root_certificatesObject (readonly)

Returns the value of attribute root_certificates.



18
19
20
# File 'lib/app_store/signed_data_verifier.rb', line 18

def root_certificates
  @root_certificates
end

Instance Method Details

#verify_and_decode_app_transaction(signed_app_transaction) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/app_store/signed_data_verifier.rb', line 58

def verify_and_decode_app_transaction(signed_app_transaction)
  decoded_app_transaction = verify_jwt(signed_app_transaction) do |t|
    t['receiptCreationDate'].nil? ? Time.now : Time.parse(t['receiptCreationDate'])
  end
  environment = decoded_app_transaction['receiptType']
  if @bundle_id != decoded_app_transaction['bundleId'] || (@environment == :production && @app_apple_id != decoded_app_transaction['appAppleId'])
    raise VerificationException, :invalid_app_identifier
  end
  raise VerificationException, :invalid_environment if @environment != environment

  decoded_app_transaction
end

#verify_and_decode_notification(signed_payload) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/app_store/signed_data_verifier.rb', line 45

def verify_and_decode_notification(signed_payload)
  decoded_jwt = verify_jwt(signed_payload)
  payload = decoded_jwt['data'] || decoded_jwt['summary'] || decoded_jwt['externalPurchaseToken']
  app_apple_id = payload['appAppleId']
  bundle_id = payload['bundleId']
  environment = payload['environment']
  if payload['externalPurchaseId']
    environment = payload['externalPurchaseId']&.start_with?('SANDBOX') ? ENVIRONMENTS[:sandbox] : ENVIRONMENTS[:production]
  end
  verify_notification(bundle_id, app_apple_id, environment)
  decoded_jwt
end

#verify_and_decode_renewal_info(signed_renewal_info) ⇒ Object



38
39
40
41
42
43
# File 'lib/app_store/signed_data_verifier.rb', line 38

def verify_and_decode_renewal_info(signed_renewal_info)
  decoded_renewal_info = verify_jwt(signed_renewal_info)
  raise VerificationException, :invalid_environment if decoded_renewal_info['environment'] != @environment

  decoded_renewal_info
end

#verify_and_decode_transaction(signed_transaction_info) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/app_store/signed_data_verifier.rb', line 30

def verify_and_decode_transaction(signed_transaction_info)
  decoded_jwt = verify_jwt(signed_transaction_info)
  raise VerificationException, :invalid_app_identifier if decoded_jwt['bundleId'] != bundle_id
  raise VerificationException, :invalid_environment if decoded_jwt['environment'] != environment

  decoded_jwt
end