Skip to main content

Adding a credential

Adding a push credential generates a private/public key pair, where the private key is secured on the user’s mobile device and the public key is held by Authsignal. This operation must be authorized with a short-lived token, which can be obtained by tracking an action from your backend in an authenticated context.
await authsignal.push.addCredential(token: "eyJhbGciOiJ...")
authsignal.push.addCredential(token = "eyJhbGciOiJ...")
await authsignal.push.addCredential({ token: "eyJhbGciOiJ..." });
await authsignal.push.addCredential("eyJhbGciOiJ...");

Parameters

token
string
A short-lived token obtained by tracking an action.

Response

response
AuthsignalResponse<AppCredential>

Getting a credential

Get information about the push credential stored on the device, if one exists.
let response = await authsignal.push.getCredential()
val response = authsignal.push.getCredential()
const response = await authsignal.push.getCredential();
final response = await authsignal.push.getCredential();

Response

response
AuthsignalResponse<AppCredential>

Updating a credential

Push tokens are not permanent. The OS rotates them - on app reinstall or restore to a new device, after clearing app data, when a token expires, or whenever the push service decides to issue a new one. The token you registered with addCredential eventually goes stale, and a notification sent to a stale token is silently dropped. Use updateCredential to point the existing credential at a fresh device token. Unlike addCredential, it requires no token from your backend and no user session - the device proves possession of its existing credential, so you can call it from a background handler without any user interaction. It also leaves the credential’s keys in place, so the user stays enrolled.
await authsignal.push.updateCredential(pushToken: "<APNs or FCM token>")
authsignal.push.updateCredential(pushToken = "<FCM token>")
await authsignal.push.updateCredential({ pushToken: "<APNs or FCM token>" });

When to call it

Both Apple and Google recommend the same pattern: subscribe to the OS token callback and send the new token to your server as soon as it changes. With Authsignal, “send to your server” means calling updateCredential. Register the latest token whenever it changes so Authsignal always has a deliverable one:
  • On token rotation - the most important trigger. Subscribe to the OS push token callback and update the credential whenever a new token is issued.
  • On app foreground or launch - retrieve the current token, compare it against the one you last registered, and update the credential if it changed. This is a backstop for tokens that rotated while the app was killed, when no rotation callback fires.
Skip the call if no push credential exists yet - the first token is registered by addCredential at enrolment. The token type must match your tenant’s configured provider, the same as for addCredential.

Keeping the credential alive

updateCredential has a second use. If you configure a credential lifetime on the push authenticator, credentials expire unless kept alive. Pass resetExpiry to reset the credential’s lease and keep the device enrolled. Both parameters are optional, so you can rotate the token, reset the expiry, or do both in one call.
// Reset the lease without changing the token
await authsignal.push.updateCredential(resetExpiry: true)

// Rotate the token and reset the lease together
await authsignal.push.updateCredential(pushToken: "<APNs or FCM token>", resetExpiry: true)
// Reset the lease without changing the token
authsignal.push.updateCredential(resetExpiry = true)

// Rotate the token and reset the lease together
authsignal.push.updateCredential(pushToken = "<FCM token>", resetExpiry = true)
// Reset the lease without changing the token
await authsignal.push.updateCredential({ resetExpiry: true });

// Rotate the token and reset the lease together
await authsignal.push.updateCredential({ pushToken: "<APNs or FCM token>", resetExpiry: true });
When no lifetime is configured, credentials never expire and you don’t need resetExpiry. See Keeping credentials alive for where to call this in your app’s lifecycle. Each successful updateCredential call also fires the authenticator.updated webhook, so your backend can track token rotations and expiry extensions without polling.
updateCredential is supported on the iOS SDK from v2.11.0, the Android SDK from v4.1.0, and the React Native SDK from v3.1.0.

Response

response
AuthsignalResponse<UpdatedAppCredential>

Removing a credential

await authsignal.push.removeCredential()
authsignal.push.removeCredential()
await authsignal.push.removeCredential();
await authsignal.push.removeCredential();

Response

response
AuthsignalResponse<boolean>

Getting a challenge

let response = await authsignal.push.getChallenge()

if let error = result.error {
    // The credential stored on the device is invalid
} else if let challenge = result.data {
    // A pending challenge request is available
    // Present the user with a prompt to approve or deny the request
    let challengeId = challenge.challengeId
} else {
    // No pending challenge request
}
val response = authsignal.push.getChallenge()

if (response.error != null) {
    // The credential stored on the device is invalid
} else if (response.data != null) {
    // A pending challenge request is available
    // Present the user with a prompt to approve or deny the request
    val challengeId = response.data.challengeId
} else {
    // No pending challenge request
}
const {data, error} = await authsignal.push.getChallenge();

if (error) {
    // The credential stored on the device is invalid
} else if (data) {
    // A pending challenge request is available
    // Present the user with a prompt to approve or deny the request
    val challengeId = data.challengeId
} else {
    // No pending challenge request
}
final response = await authsignal.push.getChallenge();

if (response.error != null) {
    // The credential stored on the device is invalid
} else if (response.data != null) {
    // A pending challenge request is available
    // Present the user with a prompt to approve or deny the request
    final challengeId = response.data.challengeId;
} else {
    // No pending challenge request
}

Response

response
AuthsignalResponse<DeviceChallenge>

Updating a challenge

After presenting the user with a prompt to approve or reject the request, you should update the challenge with their response.
await authsignal.push.updateChallenge(
    challengeId: challengeId,
    approved: true
)
authsignal.push.updateChallenge(
    challengeId = challengeId,
    approved = true
)
await authsignal.push.updateChallenge({
  challengeId,
  approved: true,
});
await authsignal.push.updateChallenge(
    challengeId,
    true,
);

Response

response
AuthsignalResponse<boolean>

Requiring user authentication

When adding a credential for push verification, it is possible to require that the user authenticate via their OS biometrics or PIN whenever they access the credential (e.g. when approving or rejecting a challenge).

iOS

To require user authentication on iOS, set the userPresenceRequired flag to true when adding the credential.
await authsignal.push.addCredential(
    token: token,
    userPresenceRequired: true
)
This is all that’s needed - iOS will automatically handle displaying the biometrics or PIN prompt when updating a challenge or verifying a device.

Android

To require user authentication on Android, set the userAuthenticationRequired flag to true when adding the credential.
authsignal.push.addCredential(
    token = token,
    userAuthenticationRequired = true
)
It’s also possible to specify additional user authentication parameters.
authsignal.push.addCredential(
    token = token,
    userAuthenticationRequired = true,
    timeout = 60,
    authorizationType = 0
)
The timeout param determines the time (in seconds) that the credential can be accessed after authenticating - or 0 if authentication must occur for every credential use. The authorizationType param determines if authentication is required via biometrics and/or device credential (e.g. pin). If user authentication is required for a credential, you must call updateChallenge in a biometric prompt authentication callback.
  1. Initialize a signature before displaying the biometric prompt
val signature = authsignal.push.startSigning()

val cryptoObject = CryptoObject(signature)

// Initialize biometric prompt and prompt info
val biometricPrompt = ...
val promptInfo = ...

biometricPrompt.authenticate(promptInfo, cryptoObject);
  1. Retrieve the signature from the crypto object in your prompt’s authentication callback
override fun onAuthenticationSucceeded(result: AuthenticationResult) {
    super.onAuthenticationSucceeded(result)

    val cryptoObject = result.cryptoObject
    val signer = cryptoObject.signature

    authsignal.push.updateChallenge(
        challengeId = challengeId,
        approved = true,
        signer = signer
    )
}