Try the iOS Sample App
The SDK repository ships a sample app in
Samples/Quickstart that
exercises the full authentication lifecycle end to end: sign-in, sign-up, and sign-out via the
SDK's app-native Flow Execution.
Prerequisites
- Xcode 15+
- A running ThunderID instance
Prepare the iOS Sample
cd Samples/Quickstart
cp Config.plist.example Sources/Config.plist
# Edit Sources/Config.plist with your ThunderID base URL and application ID
This sample uses app-native authentication (Flow Execution API), so only the base URL and application ID are required, no OAuth2 client ID or redirect URIs.
| Variable | Description |
|---|---|
THUNDERID_BASE_URL | Base URL of your ThunderID server (HTTPS) |
THUNDERID_APP_ID | Application UUID from ThunderID console |
Sources/Config.plist is gitignored. Never commit real credentials.
Attestation via Apple App Attest (optional)
If the application enforces platform attestation, set THUNDERID_ATTESTATION_ENABLED to true in
Sources/Config.plist, then rebuild. When enabled, the sample mints a token via
AppAttestTokenProvider (Apple App Attest) and sends it with every native flow-initiate request.
Testing this end-to-end requires:
- A physical device, App Attest is unavailable in the simulator.
- A signing team and the App Attest capability enabled on the target, so Xcode adds the
com.apple.developer.devicecheck.appattest-environmententitlement. - The Team ID and Bundle ID registered on the ThunderID application's attestation settings
to match the ones the app is signed with. ThunderID derives the expected App ID from
<TeamID>.<BundleID>and rejects a token whose attested App ID differs.
The Attestation-Token header carries the base64-encoded App Attest attestation object exactly as
DCAppAttestService.attestKey returns it, do not wrap it in a JSON envelope. The challenge should
come from the server in production; this sample generates it locally to exercise the SDK hook.
Passkeys (WebAuthn)
Passkey registration/authentication via ASAuthorizationPlatformPublicKeyCredentialProvider
requires the app's relying party ID to be backed by a real Associated Domain, not localhost.
Without this, ASAuthorizationController fails immediately with
Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1004.
This sample ships Sources/Quickstart.entitlements with a placeholder
webcredentials:your-thunderid-domain.example entry. To exercise passkeys end-to-end:
- Replace the placeholder domain in
Sources/Quickstart.entitlementswith the domain your ThunderID server is actually reachable at (it must serve valid HTTPS, self-signed certs andlocalhostwill not work). - Host an
apple-app-site-associationfile athttps://<that-domain>/.well-known/apple-app-site-associationdeclaring this app's Team ID andPRODUCT_BUNDLE_IDENTIFIER(dev.thunderid.Quickstart) underwebcredentials.apps. - Make sure the server's passkey
rp.idmatches that same domain, the SDK (PasskeyAuthSession) passes whateverrp.idthe server returns straight through toASAuthorizationPlatformPublicKeyCredentialProvider. - Set a
DEVELOPMENT_TEAMand enable the Associated Domains capability for the target in Xcode (Signing & Capabilities) so the entitlement is actually applied to the build.
Exposing a local ThunderID instance under a real, HTTPS-reachable domain (e.g. via a tunnel) is left to you, this sample only wires up the entitlement/documentation, not the tunnel itself.
Run
Open in Xcode via Package.swift and run on an iOS 16+ simulator or device.
Next Steps
- Accessing Protected APIs: Make authenticated API requests from an iOS application using bearer tokens from the ThunderID SDK