Class: Mysigner::Auth::AscJwtMinter

Inherits:
Object
  • Object
show all
Defined in:
lib/mysigner/auth/asc_jwt_minter.rb

Overview

Mints an Apple App Store Connect API JWT locally from a .p8 private key.

Used by the CLI’s local-only mode (epic mysigner-22) so credentials never leave the user’s machine. The MySigner server path mints the same shape server-side; this class produces a token equivalent to what the server would return, so downstream ASC callers (e.g. Mysigner::Upload::AscRestUploader) are agnostic to where the token came from.

Apple’s spec (developer.apple.com/documentation/appstoreconnectapi/ generating-tokens-for-api-requests):

- header: { alg: ES256, kid: <key_id>, typ: JWT }
- claims: iss=<issuer_id>, iat=<now>, exp=<iat+TTL>, aud=appstoreconnect-v1
- signed ES256 over base64url(header).base64url(claims) with the .p8 EC key

Apple caps token lifetime at 20 minutes. We default to 19 minutes so consumers can safely reuse a token throughout a typical ASC upload session without bumping into the cap mid-request.

Constant Summary collapse

DEFAULT_TTL =
19 * 60
AUDIENCE =
'appstoreconnect-v1'

Instance Method Summary collapse

Constructor Details

#initialize(key_id:, issuer_id:, p8_pem:) ⇒ AscJwtMinter

Returns a new instance of AscJwtMinter.



29
30
31
32
33
# File 'lib/mysigner/auth/asc_jwt_minter.rb', line 29

def initialize(key_id:, issuer_id:, p8_pem:)
  @key_id    = present!(key_id, 'key_id')
  @issuer_id = present!(issuer_id, 'issuer_id')
  @ec_key    = parse_ec_key(present!(p8_pem, 'p8_pem'))
end

Instance Method Details

#mint(ttl: DEFAULT_TTL, now: Time.now) ⇒ Object

Returns a String JWT. ‘now` is injectable for testability.



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/mysigner/auth/asc_jwt_minter.rb', line 36

def mint(ttl: DEFAULT_TTL, now: Time.now)
  iat = now.to_i
  payload = {
    iss: @issuer_id,
    iat: iat,
    exp: iat + ttl,
    aud: AUDIENCE
  }
  headers = { kid: @key_id, typ: 'JWT' }
  # JWT.encode with ES256 produces a fixed-width raw r||s signature per
  # JWA RFC 7518, which is what Apple requires.
  JWT.encode(payload, @ec_key, 'ES256', headers)
end