Browse docs
Frontelio Access · iOS

Apple Wallet pass setup.

Turn on the iOS Apple Wallet pass for Frontelio Access. The phone becomes the credential — Add to Apple Wallet, double-click home, tap reader. Cert provisioning is one-time and takes about 30 minutes.

What the pass is

Apple doesn't let third-party apps emulate NFC cards (Android does — that's the HCE service Frontelio uses on Android). On iOS we use the supported alternative: a PassKit Passcontaining a QR code. The worker adds the pass to Apple Wallet once, double-clicks home / Side Button, holds the phone up to a reader, the reader's camera (or the bridge's PN532 + QR cam) reads the QR, the door opens.

The QR code on the pass IS the daily-rotating credential JWT — the same one Android broadcasts via HCE. When the credential rotates at 00:00 Asia/Dubai (or any time we manually push), we send a silent APNs push to every registered device; iOS quietly refetches the pass with the new QR.

Prerequisites

  • Apple Developer Program membership for Frontelio (Team ID 55MVF9UKG9).
  • Access to developer.apple.com with sign-in rights to create Pass Type IDs and certificates.
  • A Mac with Keychain Access for the CSR + .p12 export step.
  • SSH access to the production API droplet to set env vars.

Provisioning walkthrough

Step 1 — Create a Pass Type ID

  1. Go to developer.apple.com · Identifiers · Pass Type IDs.
  2. Click the + button.
  3. Description: Frontelio Access.
  4. Identifier: pass.com.missan.frontline.access.
  5. Save.

Step 2 — Generate a CSR in Keychain Access

  1. On the Mac, open Keychain Access.
  2. Menu → Certificate Assistant Request a Certificate From a Certificate Authority…
  3. User Email: support@frontelio.com. Common Name: Frontelio Access — Pass Type. CA Email: leave blank.
  4. Select Saved to disk. Save the .certSigningRequest file somewhere safe.

Step 3 — Sign the Pass Type certificate

  1. Back on developer.apple.com, click the Pass Type ID you just created.
  2. Click Create Certificate.
  3. Upload the .certSigningRequest from step 2.
  4. Download the resulting pass.cer file when prompted.

Step 4 — Export the cert as a password-protected .p12

  1. Double-click the downloaded pass.cer — Keychain Access installs the cert + private key together under your login keychain.
  2. In Keychain Access, find the cert (search pass.com.missan.frontline.access). Right-click → Export…
  3. File format: Personal Information Exchange (.p12). Save as frontelio-pass.p12.
  4. Set a strong password — keep this safe in 1Password as PASS_CERT_PASSWORD.

Step 5 — Download the Apple WWDR intermediate (G4)

The .pkpass signature chain needs Apple's WWDR Certificate Authority. Apple publishes the latest revision (G4) directly:

bash
curl -O https://www.apple.com/certificateauthority/AppleWWDRCAG4.cer

Convert from DER to PEM with openssl:

bash
openssl x509 -inform DER -in AppleWWDRCAG4.cer -out AppleWWDRCAG4.pem

Step 6 — Base64-encode both files

bash
# .p12 (binary) → single-line base64
base64 -i frontelio-pass.p12 -o pass-cert.b64.txt

# WWDR PEM (text already) → base64 to keep the env var clean
base64 -i AppleWWDRCAG4.pem -o wwdr.b64.txt

Step 7 — Generate a wallet auth secret

The pass embeds an authenticationTokenApple uses on every web-service call back to us. It's an HMAC keyed by a per-tenant secret you generate once:

bash
openssl rand -hex 32

Save the output as WALLET_PASS_AUTH_SECRET in 1Password.

Step 8 — Set env vars on the production droplet

SSH into the API droplet, edit /etc/frontelio/api.env (or wherever your env file lives) and add:

bash
PASS_TYPE_ID=pass.com.missan.frontline.access
PASS_CERT_P12_BASE64=<paste contents of pass-cert.b64.txt>
PASS_CERT_PASSWORD=<the password you set in step 4>
WWDR_CERT_PEM_BASE64=<paste contents of wwdr.b64.txt>
APPLE_TEAM_ID=55MVF9UKG9
WALLET_PASS_AUTH_SECRET=<the openssl rand -hex 32 from step 7>

# Optional — defaults are fine for production:
# WALLET_PASS_WEB_SERVICE_URL=https://api.frontelio.com/api/v1/access/wallet/v1/
# APNS_GATEWAY_HOST=gateway.push.apple.com

Then restart the API container:

bash
docker compose restart api

Step 9 — Test from the staff app

  1. Open the Frontelio staff app on an iPhone signed in as any worker with at least one active Access grant.
  2. Tap MoreMy Access.
  3. Tap the black Add to Apple Wallet button below the QR card.
  4. iOS opens the Wallet "Add" sheet. Tap Add in the top-right.
  5. Done — the pass lives in Apple Wallet. Double-click the Side Button to surface it; the QR is the daily credential.

Rotating the cert (every year)

Apple Pass Type certs are valid for 1 year. Track the renewal date when you set it up, and roughly two weeks before expiry:

  1. Repeat steps 2–6 with a fresh CSR.
  2. Set the new PASS_CERT_P12_BASE64 + PASS_CERT_PASSWORD in env.
  3. Restart the API container — the next pass issued uses the new cert. Existing devices auto-refresh on the next push.

Troubleshooting

  • "Apple Wallet pass generation is not configured" (503 from /access/wallet/pass.pkpass) — at least one of the env vars is missing. The error message lists each missing key by name.
  • iOS Wallet rejects the pass — usually a stale WWDR. Apple has rotated through G1 → G2 → G3 → G4; using the wrong version makes every modern iPhone refuse to add the pass. Re-download from the link in step 5.
  • Pass adds but daily refresh doesn't arrive — check the API logs for APNs returned HTTP warnings. Most common cause: the Pass Type cert and the APNs identity cert have to be the SAME .p12 — we re-use it for both. If you used a separate cert for APNs you'll see TLS handshake failures.
  • Verify what the pass looks like — rename the downloaded .pkpass to .zip and unzip; pass.json is human-readable and tells you whether the QR data, fields, and webServiceURL look right.