SenseCrypt Docs
SDKs & appsMobile SDK

Push notifications

Register a device push token with the SenseCrypt Mobile SDK so CIBA backchannel sign-in requests can reach it.

Push is what makes CIBA backchannel sign-in work: a relying party initiates authentication server-side, and the user's device is notified to approve it. Without a registered push token, a device is unreachable for CIBA and the user must start the sign-in from the app.

Push is optional. If you only support QR-initiated sign-in, you can skip this page entirely.

The two calls

authn.updatePushToken(token: fcmToken, platform: .ios)
authn.syncPushToken()
authn.updatePushToken(fcmToken, PushPlatform.ANDROID)
authn.syncPushToken()

They do different things, and you almost always want both:

updatePushToken(token:platform:) stages the change. It does not make a network call. The next signed request the SDK makes for any reason — registration, signup, key rotation, session completion — folds fcm_token and push_platform into that request body. There is no dedicated push endpoint.

syncPushToken() uploads it now. A standalone signed call, instead of waiting for the next flow to carry it. This is what makes a freshly registered device reachable by CIBA without waiting for its next sign-in.

Calling only updatePushToken means a device that just enrolled stays unreachable until the user's next flow. Follow it with syncPushToken() whenever the token becomes available or changes outside a flow.

Both are fire-and-forget: no return value, no completion handler, no observable result. Outcomes are logged (when enableLogging is on).

syncPushToken() no-ops harmlessly when there is nothing staged, when the staged value already synced this session, or when no registered key exists yet to sign with — in that last case the update stays staged and rides along with the next flow instead.

Wiring it up

The token typically arrives from the platform push SDK before you have a SenseCryptAuthenticator handle, or before any key exists to sign with. Handle both.

func messaging(_ messaging: Messaging,
               didReceiveRegistrationToken fcmToken: String?) {
    guard let fcmToken else { return }

    if let authn = self.authn {
        authn.updatePushToken(token: fcmToken, platform: .ios)
        authn.syncPushToken()
    } else {
        // No handle yet — stash it and replay once the SDK is open.
        Keychain.set("pendingFcmToken", fcmToken)
    }
}
override fun onNewToken(token: String) {
    val authn = SenseCryptApp.authenticatorOrNull()
    if (authn != null) {
        authn.updatePushToken(token, PushPlatform.ANDROID)
        authn.syncPushToken()
    } else {
        // No handle yet — stash it and replay once the SDK is open.
        prefs.edit().putString("pendingFcmToken", token).apply()
    }
}

If the SDK isn't open when the token callback fires, stash the token in the Keychain or shared preferences and replay both calls once open() has returned. The SDK has no queue that survives process death.

Call syncPushToken() again after these events, since each can change reachability:

  • The user grants notification permission (the token may only become available then).
  • The platform rotates the token.
  • A registration flow completes — the device now has a key to sign the upload with.

Clearing the token

On logout or a push opt-out, clear it:

authn.updatePushToken(token: nil, platform: .ios)
authn.syncPushToken()
authn.updatePushToken(null, PushPlatform.ANDROID)
authn.syncPushToken()

Passing nil (or an empty string) sends an explicit null so the server clears the stored row. Don't just stop calling updatePushToken — that leaves a stale token registered, and the portal will keep pushing to a device that no longer wants it.

PushPlatform

CaseUse for
iosApple devices.
androidAndroid devices.

Platform setup

The SDK does not configure your push transport — that's your app's job:

  • Android — add Firebase Cloud Messaging and a google-services.json, and implement a FirebaseMessagingService.
  • iOS — enable the Push Notifications capability, configure APNs, and add Firebase Messaging with a GoogleService-Info.plist if you route through FCM.

On this page