{"_id":"@bradford-tech/asc-auth","_rev":"3-c540a8c3f1b8bee9218a6b03c121bb5f","name":"@bradford-tech/asc-auth","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.2":{"name":"@bradford-tech/asc-auth","version":"0.0.2","keywords":["apple","app-store-connect","auth","jwt","es256"],"author":{"name":"Bradford Technologies","email":"asc-sdk@bradford.tech"},"license":"MIT","_id":"@bradford-tech/asc-auth@0.0.2","maintainers":[{"name":"sbs44","email":"focal-flusher.0g@icloud.com"}],"homepage":"https://github.com/bradford-tech/asc-sdk/tree/main/packages/asc-auth#readme","bugs":{"url":"https://github.com/bradford-tech/asc-sdk/issues"},"dist":{"shasum":"7115a63569624d58a1c60a67d84b04036ede4586","tarball":"https://registry.npmjs.org/@bradford-tech/asc-auth/-/asc-auth-0.0.2.tgz","fileCount":31,"integrity":"sha512-SIw0NMkLNpT07TPze2HPQChdlcLY5xusOlRhTkJrt1ionKYs3xH+SzMMzp6LASZufCPfuMMqmjKE/iuk9HQKEA==","signatures":[{"sig":"MEUCIE75bZfbUMYUE0mnYRaKCiC7OWqPHBgEY0PCuG8rNcBcAiEAseLbBMfin668S+SRb485TSHVkJhx/Sknjx1yr3k9WwI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bradford-tech%2fasc-auth@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":33606},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"5c3b6dea5ba12466d8eceb25e20a159347ef6e3a","scripts":{"test":"tsc -p tsconfig.test.json --outDir .test-out && node --test '.test-out/tests/*.test.js'","build":"tsc","clean":"rimraf dist .test-out","prepack":"npm run build","type-check":"tsc --noEmit"},"_npmUser":{"name":"sbs44","email":"focal-flusher.0g@icloud.com"},"repository":{"url":"git+https://github.com/bradford-tech/asc-sdk.git","type":"git","directory":"packages/asc-auth"},"_npmVersion":"11.11.0","description":"JWT authentication helper for the Apple App Store Connect API","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jose":"^6.2.2","rimraf":"^6.1.3","@types/node":"^20.19.39"},"_npmOperationalInternal":{"tmp":"tmp/asc-auth_0.0.2_1776589903143_0.664556141940337","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@bradford-tech/asc-auth","version":"0.0.3","keywords":["apple","app-store-connect","auth","jwt","es256"],"author":{"name":"Bradford Technologies","email":"asc-sdk@bradford.tech"},"license":"MIT","_id":"@bradford-tech/asc-auth@0.0.3","maintainers":[{"name":"sbs44","email":"focal-flusher.0g@icloud.com"}],"homepage":"https://github.com/bradford-tech/asc-sdk/tree/main/packages/asc-auth#readme","bugs":{"url":"https://github.com/bradford-tech/asc-sdk/issues"},"dist":{"shasum":"95b9dcecb1f6ee3f8d7dcaf3ea247d1bfbdc740b","tarball":"https://registry.npmjs.org/@bradford-tech/asc-auth/-/asc-auth-0.0.3.tgz","fileCount":31,"integrity":"sha512-1EDi9RvtY+LA6B/TrqSrraR17sMpjIpgY3zpwJfNLN+ZkHyjWvGwfBWDIbFkAVtx9d5ey7DsJ3ZMjuIvwekmQw==","signatures":[{"sig":"MEYCIQCMELPThs2CygbjTTUqS4hP8xApxcbeC1NukhQ1jU+TNQIhAOKRJaWRPFdmixdmfBVVL6cE82hEVuJhjKRXhiXWfUZL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bradford-tech%2fasc-auth@0.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":34479},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"e13fb2efc5e046cc42cef32ed122a7ef306d8adb","scripts":{"test":"tsc -p tsconfig.test.json --outDir .test-out && node --test '.test-out/tests/*.test.js'","build":"tsc","clean":"rimraf dist .test-out","prepack":"npm run build","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:607609ea-6871-4634-830a-9ad10ecc568d"}},"repository":{"url":"git+https://github.com/bradford-tech/asc-sdk.git","type":"git","directory":"packages/asc-auth"},"_npmVersion":"11.11.0","description":"JWT authentication helper for the Apple App Store Connect API","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jose":"^6.2.2","rimraf":"^6.1.3","@types/node":"^20.19.39"},"_npmOperationalInternal":{"tmp":"tmp/asc-auth_0.0.3_1776676670270_0.2580595934282497","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@bradford-tech/asc-auth","version":"0.0.4","description":"JWT authentication helper for the Apple App Store Connect API","keywords":["apple","app-store-connect","auth","jwt","es256"],"homepage":"https://github.com/bradford-tech/asc-sdk/tree/main/packages/asc-auth#readme","bugs":{"url":"https://github.com/bradford-tech/asc-sdk/issues"},"repository":{"type":"git","url":"git+https://github.com/bradford-tech/asc-sdk.git","directory":"packages/asc-auth"},"license":"MIT","author":{"name":"Bradford Technologies","email":"asc-sdk@bradford.tech"},"sideEffects":false,"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"tsc","clean":"rimraf dist .test-out","prepack":"npm run build","test":"tsc -p tsconfig.test.json --outDir .test-out && node --test '.test-out/tests/*.test.js'","type-check":"tsc --noEmit"},"devDependencies":{"@types/node":"^20.19.40","jose":"^6.2.3","rimraf":"^6.1.3"},"engines":{"node":">=20.0.0"},"publishConfig":{"access":"public"},"gitHead":"91294848c1bcff79fcaa8845f0d999facf3ae4a8","_id":"@bradford-tech/asc-auth@0.0.4","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-Cs81et+3l7PsVZJXerJcobOCIKH0DT6s9iAxcSJ4eExnwSnloDAxAflT+SWK94tmWDTD5Tl1LWtmLQh4WEdPrA==","shasum":"2eb5b23c865b3ff6714a5daf8f800d5fe737c241","tarball":"https://registry.npmjs.org/@bradford-tech/asc-auth/-/asc-auth-0.0.4.tgz","fileCount":31,"unpackedSize":36108,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bradford-tech%2fasc-auth@0.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICOeHbRdlQeGYtw+mu89UbU5YgSUcTxXVyI9ppR3PALxAiAk4PjVc0IrQUT9Sfw1FijtdvoQGl/2e0PYQ29eGMwknA=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:607609ea-6871-4634-830a-9ad10ecc568d"}},"directories":{},"maintainers":[{"name":"sbs44","email":"focal-flusher.0g@icloud.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/asc-auth_0.0.4_1778789284148_0.9883121867416769"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-19T09:11:42.998Z","modified":"2026-05-14T20:08:04.592Z","0.0.2":"2026-04-19T09:11:43.273Z","0.0.3":"2026-04-20T09:17:50.436Z","0.0.4":"2026-05-14T20:08:04.297Z"},"bugs":{"url":"https://github.com/bradford-tech/asc-sdk/issues"},"author":{"name":"Bradford Technologies","email":"asc-sdk@bradford.tech"},"license":"MIT","homepage":"https://github.com/bradford-tech/asc-sdk/tree/main/packages/asc-auth#readme","keywords":["apple","app-store-connect","auth","jwt","es256"],"repository":{"type":"git","url":"git+https://github.com/bradford-tech/asc-sdk.git","directory":"packages/asc-auth"},"description":"JWT authentication helper for the Apple App Store Connect API","maintainers":[{"name":"sbs44","email":"focal-flusher.0g@icloud.com"}],"readme":"# @bradford-tech/asc-auth\n\nZero-dependency JWT authentication for Apple's App Store Connect API, built on Web Crypto (`crypto.subtle`) for ES256 signing.\n\n## Install\n\n```bash\nnpm install @bradford-tech/asc-auth\n```\n\nAlso available on [jsr](https://jsr.io/@bradford-tech/asc-auth):\n\n```bash\ndeno add jsr:@bradford-tech/asc-auth   # Deno\nnpx jsr add @bradford-tech/asc-auth    # npm via jsr\n```\n\n## Usage\n\n```ts\nimport { createASCAuth } from \"@bradford-tech/asc-auth\";\n\nconst auth = createASCAuth({\n  issuerId: \"57246542-96fe-1a63-e053-0824d011072a\",\n  keyId: \"2X9R4HXF34\",\n  privateKey: process.env.ASC_PRIVATE_KEY!,\n});\n\nconst token = await auth();\nconsole.log(token.split(\".\").length);\n// => 3\n```\n\n`createASCAuth` returns a callable that produces cached, auto-refreshing JWTs.\n\n### With `@bradford-tech/asc-sdk`\n\nThe returned `auth` function is directly compatible with Hey API's `auth` callback:\n\n```ts\nimport { client } from \"@bradford-tech/asc-sdk\";\n\nclient.setConfig({ auth });\n```\n\n## Team keys vs. individual keys\n\n### Team keys (default)\n\nTeam keys are scoped to the organization and require an Issuer ID. The [usage example above](#usage) shows this pattern.\n\n### Individual keys\n\nIndividual keys are tied to a specific user's apps and permissions:\n\n```ts\nconst auth = createASCAuth({\n  keyType: \"individual\",\n  keyId: \"2X9R4HXF34\",\n  privateKey: process.env.ASC_PRIVATE_KEY!,\n});\n```\n\n## Key input formats\n\n### PEM string (most common)\n\nPass the `.p8` file contents directly. The PEM parser handles CRLF/LF line endings, missing `BEGIN`/`END` markers, single-line base64, literal `\\n` from environment variables, and extra whitespace.\n\n```ts\n// From environment variable\nconst auth = createASCAuth({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: process.env.ASC_PRIVATE_KEY!,\n});\n\n// From file (Node.js only)\nimport { readFileSync } from \"node:fs\";\nconst auth = createASCAuth({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: readFileSync(\"./AuthKey_2X9R4HXF34.p8\", \"utf8\"),\n});\n```\n\n### CryptoKey (pre-imported)\n\nFor KMS or Vault flows where the private key should never exist as a string in process memory:\n\n```ts\nconst key = await crypto.subtle.importKey(\n  \"pkcs8\",\n  derBuffer,\n  { name: \"ECDSA\", namedCurve: \"P-256\" },\n  false,\n  [\"sign\"],\n);\n\nconst auth = createASCAuth({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: key,\n});\n```\n\n## Token caching\n\nTokens are cached and automatically refreshed before expiry. Defaults:\n\n- Token lifetime: 1200 seconds (20 minutes, Apple's maximum for standard tokens)\n- Refresh buffer: 30 seconds (sign a new token 30s before expiry)\n\nConcurrent callers share a single in-flight signing operation rather than triggering duplicate signs.\n\n```ts\nconst auth = createASCAuth({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: \"...\",\n  expiration: 900, // 15-minute tokens\n  refreshBuffer: 60, // refresh 60s before expiry\n});\n```\n\nThe `expiration` parameter is the total token lifetime (`exp - iat`), which is what Apple checks -- not wall-clock \"seconds from now until expiry.\"\n\n### Manual cache control\n\n```ts\nauth.refresh(); // Force sign a new token, bypassing cache\nauth.clearCache(); // Drop the cached token (does NOT invalidate it on Apple's side -- JWTs are stateless)\n```\n\n## Scoped tokens\n\nRestrict a token to specific operations:\n\n```ts\nconst auth = createASCAuth({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: \"...\",\n  scope: [\"GET /v1/apps?filter[platform]=IOS\"],\n});\n```\n\nScoped tokens are GET-only by Apple's design. Apple ignores `limit`, `cursor`, and `sort` query params when matching scope entries.\n\nLong-lived tokens (up to 6 months) are accepted only for scoped GET requests against Xcode Cloud/CI resources: build actions, build runs, git references, issues, macOS versions, products, providers, power-and-performance-metrics-and-logs, pull requests, repositories, test results, workflows, and Xcode versions. All other resources reject `exp - iat > 1200`.\n\n## One-shot signing\n\nFor single-use tokens (e.g., pre-signing in CI):\n\n```ts\nimport { signASCToken } from \"@bradford-tech/asc-auth\";\n\nconst token = await signASCToken({\n  issuerId: \"...\",\n  keyId: \"...\",\n  privateKey: process.env.ASC_PRIVATE_KEY!,\n});\n```\n\n`signASCToken` is the low-level function. It signs once, returns the token string, and does no caching.\n\n## Error handling\n\nTwo error classes distinguish key-material problems from other auth failures:\n\n```ts\nimport { ASCAuthError, ASCAuthPEMError } from \"@bradford-tech/asc-auth\";\n\ntry {\n  const token = await auth();\n} catch (err) {\n  if (err instanceof ASCAuthPEMError) {\n    // Key parsing failed -- bad PEM format, corrupt key data\n    console.error(\"Key error:\", err.message);\n  } else if (err instanceof ASCAuthError) {\n    // Other auth error -- missing options, crypto unavailable, signing failure\n    console.error(\"Auth error:\", err.message);\n  }\n}\n```\n\n`ASCAuthPEMError` extends `ASCAuthError`, so catching `ASCAuthError` covers both.\n\n## Clock skew\n\nToken timestamps use the local system clock. Apple tolerates approximately 60 seconds of skew. On systems with unreliable NTP, set `expiration: 1140` (19 minutes) rather than the full 1200 to leave margin.\n\n## Runtime support\n\n| Runtime            | Status                                                |\n| ------------------ | ----------------------------------------------------- |\n| Node.js 20+        | Supported                                             |\n| Deno               | Supported                                             |\n| Bun                | Supported                                             |\n| Cloudflare Workers | Supported                                             |\n| Vercel Edge        | Supported                                             |\n| Browsers           | Not supported (private keys must not run client-side) |\n\nIf `crypto.subtle` is not available, the library throws an `ASCAuthError` immediately with a descriptive message.\n\n## When to pick something else\n\nIf you already depend on `jose` for other JWT work, [`appstore-connect-sdk`](https://www.npmjs.com/package/appstore-connect-sdk) is a reasonable choice with more download history. This package is for cases where at least one of these matters: zero runtime dependencies, concurrent request deduplication, KMS-resident keys, scoped or long-lived tokens, or forgiving PEM parsing from environment variables.\n\n## Exported types\n\nThe package exports TypeScript interfaces for all configuration shapes:\n\n- `ASCAuthOptions` -- union of `ASCTeamKeyOptions | ASCIndividualKeyOptions`\n- `ASCTeamKeyOptions` -- team key config (with `issuerId`)\n- `ASCIndividualKeyOptions` -- individual key config (with `keyType: \"individual\"`)\n- `ASCAuth` -- the returned auth provider type (callable + `refresh()` + `clearCache()`)\n\n## Contributing\n\nBug reports and pull requests are welcome on [GitHub](https://github.com/bradford-tech/asc-sdk).\n\n## License\n\n[MIT](https://github.com/bradford-tech/asc-sdk/blob/main/LICENSE)\n","readmeFilename":"README.md"}