Auth key vs certificate: use the auth key
Apple offers two ways to authenticate with Apple Push Notification service (APNs):
- APNs Auth Key (.p8) — a single key that works across all your apps and never expires. This is what Apple recommends and what every modern push provider (Firebase, OneSignal, your own server via
token-based auth) expects. - APNs Certificate (.p12) — the legacy per-app, per-environment (dev/production) certificate that expires annually and has to be regenerated and re-uploaded to every service that uses it.
Unless you're maintaining an old integration that specifically requires certificates, set up the auth key. It's less setup work, it doesn't expire, and it works for every app in your account with the same key — no more "push notifications stopped working" surprises every 12 months when a certificate silently lapses.
Setting up an APNs Auth Key
- Go to the Apple Developer portal → Certificates, Identifiers & Profiles → Keys.
- Create a new key and enable the "Apple Push Notifications service (APNs)" capability.
- Download the
.p8file immediately. This is the only time Apple lets you download it — there's no re-download later, only revoke-and-recreate. Store it somewhere durable (a secrets manager, not just a laptop). - Note the Key ID (shown after creation) and your Team ID (top-right of the developer portal, or Membership page).
- Upload the key to your push provider. Firebase Cloud Messaging: Project Settings → Cloud Messaging → APNs Authentication Key, paste the Key ID, Team ID, and upload the
.p8. For a custom server, you'll use the key to sign a JWT per-request per Apple's APNs provider documentation.
Setting up an APNs Certificate (legacy path)
If you specifically need the certificate-based approach:
- In Xcode or the Developer Portal, create an App ID with Push Notifications enabled as a capability.
- Generate a Certificate Signing Request (CSR) via Keychain Access on your Mac (Certificate Assistant → Request a Certificate from a Certificate Authority).
- Upload the CSR in the Developer Portal to generate a push certificate — separately for development and production environments. This is the step people most often mix up: a dev certificate won't authenticate against the production APNs endpoint, and vice versa.
- Download the certificate, double-click to install it in Keychain Access, then export it as a
.p12file (right-click the certificate → Export). - Upload the
.p12(and its export password, if set) to your push provider.
Remember: this certificate expires in one year and must be regenerated and re-uploaded everywhere it's used. Calendar-remind yourself, or migrate to the auth key to skip this entirely.
Client-side setup (your app code)
Certificates and keys authenticate your server to APNs — your app still needs to request permission and register for a device token:
- Enable the Push Notifications capability in Xcode (Signing & Capabilities tab) and enable Background Modes → Remote notifications if you need silent/background pushes.
- Request authorization with
UNUserNotificationCenter.current().requestAuthorization(options:), then callUIApplication.shared.registerForRemoteNotifications(). - Capture the device token in
application(_:didRegisterForRemoteNotificationsWithDeviceToken:)and send it to your backend — this is what your server uses to target a specific device. - Handle the failure delegate too —
didFailToRegisterForRemoteNotificationsWithErrortells you immediately if something's wrong (usually a provisioning profile without the push entitlement, or running on the Simulator, which can't receive real remote pushes).
Why pushes fail silently — the actual checklist
When "the code looks right but nothing arrives," it's almost always one of these:
- Environment mismatch. Using a development device token against the production APNs endpoint, or vice versa. TestFlight and App Store builds use the production environment; a debug build from Xcode uses sandbox/development. Sending a sandbox token to the production endpoint fails silently on many providers.
- Provisioning profile without the push entitlement. If you enabled the capability in Xcode after creating your provisioning profile, regenerate the profile — an outdated one won't have the entitlement baked in.
- Wrong Key ID / Team ID pairing. A typo in either field on your push provider's dashboard authenticates against nothing and typically returns a generic auth error, not a helpful one.
- Testing on the Simulator. Simulators can't receive real remote push notifications from APNs (only newer Xcode/simulator combos support simulated local push payloads for testing). Always verify on a physical device.
- Expired certificate. If you're on the legacy certificate path, check the expiration date first — this is the single most common "it used to work" cause.
- App not requesting authorization, or user denied it. No permission prompt accepted means no token, means no notifications, with no error visible in your own logs.
If you're using Firebase or another push provider
Most teams don't talk to APNs directly — they go through Firebase Cloud Messaging, OneSignal, or a similar service that handles the APNs connection for you. In that case, your setup work is the same auth key steps above, just uploaded into that provider's dashboard instead of your own server code. The provider still needs a correctly generated auth key or certificate — it can't skip that requirement, it just abstracts the request-signing away from you.
Where this connects to your App Store submission
If your app requests push permission, make sure your App Store screenshots and description don't overpromise what notifications actually do — a common metadata rejection pattern is describing notification features that aren't implemented yet, or showing a mocked notification banner that doesn't match the real UI. If notifications are a core feature, show the real permission prompt or notification content in at least one screenshot rather than describing it only in text.
Once the feature works and you're ready to show it off, ezscreenshots makes it quick to turn a real notification screenshot into a polished, correctly-sized App Store asset — drop the capture, pick your device presets, add a caption, export the full set in minutes. No account, no export limit, all in the browser.
Got push working? Show it in your listing.
A real notification screenshot builds more trust than description text alone — and keeps you clear of accuracy-based metadata rejections. ezscreenshots exports a polished, correctly-sized set in minutes. Free, browser-based, no account.
Try ezscreenshots →Summary
- Use an APNs Auth Key (.p8), not the legacy certificate — one key works for all your apps and never expires
- Auth key setup: Developer Portal → Keys → create with APNs enabled → download the .p8 immediately (one-time download) → note Key ID + Team ID → upload to your push provider
- Certificate setup (legacy): separate dev and production certificates, CSR via Keychain Access, exported as .p12, expires annually
- Client-side: enable the Push Notifications capability, request authorization, register for remote notifications, capture the device token, handle the failure delegate
- Most common silent failures: dev/production environment mismatch, stale provisioning profile, wrong Key ID/Team ID, testing on Simulator, expired certificate, denied permission
- If push notifications are a core feature, show real notification UI in a screenshot rather than describing it only in text