Performing Operations

  • The generic protocol representing an operation returned by Operations.

    See more

    Declaration

    Swift

    public protocol Operation
  • An operation that requires sending HTTP requests to the backend.

    You can provide HTTP request headers that can be sent in the HTTP request. This additional headers can be used for example to correlate the operation executed by the SDK with a more general operation. For instance if you want to correlate all the operations involving the enrollment of a user (which includes registration of an authenticator), you can use this feature.

    See more

    Declaration

    Swift

    public protocol HttpOperation : Operation
  • The protocol returned by the MobileAuthenticationClient that can be used to execute operations.

    See more

    Declaration

    Swift

    public protocol Operations
  • The object that can be used to trigger a registration operation from the response of the Cloud HTTP API to the enroll (https://$instance.mauth.nevis.cloud/api/v1/users/enroll) endpoint.

    Usage example:

    class AuthenticatorSelectorImpl: AuthenticatorSelector {
        func selectAuthenticator(context: AuthenticatorSelectionContext, handler: AuthenticatorSelectionHandler) {
            handler.aaid(aaid)
        }
    }
    
    class BiometricUserVerifierImpl: BiometricUserVerifier {
        func verifyBiometric(context: BiometricUserVerificationContext, handler: BiometricUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class DevicePasscodeUserVerifierImpl: DevicePasscodeUserVerifier {
        func verifyDevicePasscode(context: DevicePasscodeUserVerificationContext, handler: DevicePasscodeUserVerificationHandler) {
            handler.verify()
        }
    }
    
    let deviceInformation = DeviceInformation(name: "<Device name>", fcmRegistrationToken: "<FCM token>")
    
    client.operations.authCloudApiRegistration
        .deviceInformation(deviceInformation)
        .enrollResponse(enrollResponse)
        .authenticatorSelector(AuthenticatorSelectorImpl(...))
        .biometricUserVerifier(BiometricUserVerifierImpl(...))
        .devicePasscodeUserVerifier(DevicePasscodeUserVerifierImpl(...))
        .pinEnroller(PinEnrollerImpl(...))
        .onError { error in
            ...
        }
        .onSuccess { authorizationProvider in
            ...
        }
        .execute()
    

    The biometric and device Passcode authenticators are enrolled at the OS level. That is why, if one of them must be registered, the user must authenticate through BiometricUserVerifier or DevicePasscodeUserVerifier. In the case of the PIN, the PIN is enrolled during registration, so no verification is needed.

    See more

    Declaration

    Swift

    public protocol AuthCloudApiRegistration : HttpOperation
  • The object that can be used to trigger a registration operation.

    Usage example:

    class AuthenticatorSelectorImpl: AuthenticatorSelector {
        func selectAuthenticator(context: AuthenticatorSelectionContext, handler: AuthenticatorSelectionHandler) {
            handler.aaid(aaid)
        }
    }
    
    class BiometricUserVerifierImpl: BiometricUserVerifier {
        func verifyBiometric(context: BiometricUserVerificationContext, handler: BiometricUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class DevicePasscodeUserVerifierImpl: DevicePasscodeUserVerifier {
        func verifyDevicePasscode(context: DevicePasscodeUserVerificationContext, handler: DevicePasscodeUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class PinEnrollerImp: PinEnroller {
        func enrollPin(context: PinEnrollmentContext, handler: PinEnrollmentHandler) {
            handler.pin(pin)
        }
    }
    
    client.operations.registration
        .username(username)
        .serverBaseUrl(URL(string: "https://server/path")!)
        .authenticatorSelector(AuthenticatorSelectorImpl(...))
        .biometricUserVerifier(BiometricUserVerifierImpl(...))
        .devicePasscodeUserVerifier(DevicePasscodeUserVerifierImpl(...))
        .pinEnroller(PinEnrollerImp(...))
        .onError { error in
            ...
        }
        .onSuccess {
            ...
        }
        .execute()
    

    The biometric and device Passcode authenticators are enrolled at the OS level. That is why, if one of them must be registered, the user must authenticate through BiometricUserVerifier or DevicePasscodeUserVerifier. In the case of the PIN, the PIN is enrolled during registration, so no verification is needed.

    See more

    Declaration

    Swift

    public protocol Registration : HttpOperation
  • The object that can be used to trigger an authentication operation.

    Usage example:

    class AuthenticatorSelectorImpl: AuthenticatorSelector {
        func selectAuthenticator(context: AuthenticatorSelectionContext, handler: AuthenticatorSelectionHandler) {
            handler.aaid(aaid)
        }
    }
    
    class BiometricUserVerifierImpl: BiometricUserVerifier {
        func verifyBiometric(context: BiometricUserVerificationContext, handler: BiometricUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class DevicePasscodeUserVerifierImpl: DevicePasscodeUserVerifier {
        func verifyDevicePasscode(context: DevicePasscodeUserVerificationContext, handler: DevicePasscodeUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class PinUserVerifierImpl: PinUserVerifier {
        func verifyPin(context: PinUserVerificationContext, handler: PinUserVerificationHandler) {
            handler.verify(pin: pin)
        }
    }
    
    client.operations.authentication
        .username(username)
        .authenticatorSelector(AuthenticatorSelectorImpl(...))
        .biometricUserVerifier(BiometricUserVerifierImpl(...))
        .devicePasscodeUserVerifier(DevicePasscodeUserVerifierImpl(...))
        .pinUserVerifier(PinUserVerifierImpl(...))
        .onError { error in
            ...
        }
        .onSuccess { authorizationProvider in
            ...
        }
        .execute()
    
    See more

    Declaration

    Swift

    public protocol Authentication : HttpOperation
  • The object that can be used to trigger an deregistration operation.

    Usage example:

    client.operations.deregistration
        .username(username)
        .aaid(aaid)
        .authorizationProvider(authorizationProvider)
        .onError { error in
            ...
        }
        .onSuccess {
            ...
        }
        .execute()
    
    See more

    Declaration

    Swift

    public protocol Deregistration : HttpOperation
  • The object that decodes an OutOfBandPayload from a String in JSON format or a Base64 URL encoded {@code String} representing the JSON. The OutOfBandPayload can be used to trigger an out-of-band operation OutOfBandOperation.

    Usage example:

    client.operations.outOfBandPayloadDecode
        .json(jsonPayload)
        .onSuccess { outOfBandPayload in
            ...
        }
        .onError { error in
            ...
        }
        .execute()
    

    The JSON is obtained from a push notification, or as a Base64 URL encoded JSON in QR codes generated by the server. JSON example:

    {
        "nma_data" : {
            "token" : "b4b07559-f934-4597-a1c5-44d89f691e8f",
            "redeem_url" : "https://fido.siven.ch/nevisfido/token/redeem/authentication",
            "attributeName" : "some additional data to be included in the QR code"
        },
        "nma_data_content_type" : "application/json",
        "nma_data_version" : "1"
    }
    
    See more

    Declaration

    Swift

    public protocol OutOfBandPayloadDecode : Operation
  • The operation managing an OutOfBandPayload. An OutOfBandPayload can be provided through different means: a push notification, a QR code or an application link. This operation will process the payload, decrypt it if needed and send it to the server. If the payload is successfully handled by the server, then the SDK will identify whether the operation associated with the payload is a registration or an authentication. Depending on that the onRegistration(_:) or the onAuthentication(_:) will be invoked.

    Usage example:

    client.operations.outOfBandOperation
        .payload(payload)
        .onRegistration { oobRegistration in
            ...
        }
        .onAuthentication { oobAuthentication in
            ...
        }
        .onError { error in
            ...
        }
        .execute()
    
    See more

    Declaration

    Swift

    public protocol OutOfBandOperation : HttpOperation
  • The operation handling an out-of-band registration. This is the object returned by the SDK, when an OutOfBandPayload was processed and the OutOfBandPayload corresponds to a registration operation.

    Usage example:

    class AuthenticatorSelectorImpl: AuthenticatorSelector {
        func selectAuthenticator(context: AuthenticatorSelectionContext, handler: AuthenticatorSelectionHandler) {
            handler.aaid(aaid)
        }
    }
    
    class BiometricUserVerifierImpl: BiometricUserVerifier {
        func verifyBiometric(context: BiometricUserVerificationContext, handler: BiometricUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class DevicePasscodeUserVerifierImpl: DevicePasscodeUserVerifier {
        func verifyDevicePasscode(context: DevicePasscodeUserVerificationContext, handler: DevicePasscodeUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class PinEnrollerImp: PinEnroller {
        func enrollPin(context: PinEnrollmentContext, handler: PinEnrollmentHandler) {
            handler.pin(pin)
        }
    }
    
    client.operations.outOfBandOperation
        .payload(payload)
        .onRegistration { oobRegistration in
            oobRegistration
                .deviceInformation(.init(name: "<name>", fcmRegistrationToken: "<target>"))
                .authenticatorSelector(AuthenticatorSelectorImpl(...))
                .biometricUserVerifier(BiometricUserVerifierImpl(...))
                .devicePasscodeUserVerifier(DevicePasscodeUserVerifierImpl(...))
                .pinEnroller(PinEnrollerImp(...))
                .onError { error in
                    ...
                }
                .onSuccess {
                    ...
                }
                .execute()
        }
        .onAuthentication { oobAuthentication in
            ...
        }
        .execute()
    

    The biometric and device Passcode authenticators are enrolled at the OS level. That is why, if one of them must be registered, the user must authenticate through BiometricUserVerifier or DevicePasscodeUserVerifier. In the case of the PIN, the PIN is enrolled during registration, so no verification is needed.

    See more

    Declaration

    Swift

    public protocol OutOfBandRegistration : HttpOperation
  • The operation handling an out-of-band authentication. This is the object returned by the SDK, when an OutOfBandPayload was processed and the OutOfBandPayload corresponds to an authentication operation.

    Usage example:

    class AccountSelectorImpl: AccountSelector {
        func selectAccount(context: AccountSelectionContext, handler: AccountSelectionHandler) {
            handler.username(username)
        }
    }
    
    class AuthenticatorSelectorImpl: AuthenticatorSelector {
        func selectAuthenticator(context: AuthenticatorSelectionContext, handler: AuthenticatorSelectionHandler) {
            handler.aaid(aaid)
        }
    }
    
    class BiometricUserVerifierImpl: BiometricUserVerifier {
        func verifyBiometric(context: BiometricUserVerificationContext, handler: BiometricUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class DevicePasscodeUserVerifierImpl: DevicePasscodeUserVerifier {
        func verifyDevicePasscode(context: DevicePasscodeUserVerificationContext, handler: DevicePasscodeUserVerificationHandler) {
            handler.verify()
        }
    }
    
    class PinUserVerifierImpl: PinUserVerifier {
        func verifyPin(context: PinUserVerificationContext, handler: PinUserVerificationHandler) {
            handler.verify(pin: pin)
        }
    }
    
    client.operations.outOfBandOperation
        .payload(payload)
        .onRegistration { oobRegistration in
            ...
        }
        .onAuthentication { oobAuthentication in
            oobAuthentication
                .accountSelector(AccountSelectorImpl(...))
                .authenticatorSelector(AuthenticatorSelectorImpl(...))
                .biometricUserVerifier(BiometricUserVerifierImpl(...))
                .devicePasscodeUserVerifier(DevicePasscodeUserVerifierImpl(...))
                .pinUserVerifier(PinUserVerifierImpl(...))
                .onError { error in
                    ...
                }
                .onSuccess {
                    ...
                }
                .execute()
        }
        .onError { error in
            ...
        }
        .execute()
    
    See more

    Declaration

    Swift

    public protocol OutOfBandAuthentication : HttpOperation
  • The object that can be used to change the PIN.

    Usage example:

    class PinChangerImpl: PinChanger {
        func changePin(context: PinChangeContext, handler: PinChangeHandler) {
            handler.pins(oldPin, newPin)
        }
    }
    
    client.operations.pinChange
        .username(username)
        .pinChanger(PinChangerImpl(...))
        .onSuccess { in
            ...
        }
        .onError { error in
            ...
        }
        .execute()
    
    See more

    Declaration

    Swift

    public protocol PinChange : Operation
  • The object containing information of the device where the SDK is running.

    For nevisFIDO to be able to generate encrypted out-of-band payloads that can only be decrypted by your application, a DeviceInformation must be provided during registration. During registration you must provide the name and optionally the fcmRegistrationToken. The other information exposed by the DeviceInformation (deviceId and idUsernamePairs) are generated by the SDK and are not required during registration.

    For nevisFIDO to be able to dispatch tokens using the Firebase Cloud Messaging infrastructure, the device information fcmRegistrationToken must be filled with the token (as defined by Firebase). This registration token is associated with the mobile device receiving the push notifications.

    There is a single DeviceInformation for all accounts. It is created when the first successful registration is completed, and it is deleted when the last authenticator (and thus the last account) is removed (using the Deregistration or deleteAuthenticator(username:aaid:). When a DeviceInformation is provided in a registration operation, and a DeviceInformation is already defined (that is, there is already a registered authenticator), the provided DeviceInformation will be ignored. The device information contents (name and FCM registration token) can be changed using a DeviceInformationChange.

    The DeviceInformation data is stored in nevisIDM as generic credentials. For each account registered, a generic credential will be created in nevisIDM containing the device information. These generic credentials are named dispatch targets in the nevisFIDO terminology.

    The following example creates a DeviceInformation using a phone description (that can be provided by the end user, since this is used for the end user to identify the mobile device) and a Firebase registration token:

    func createDeviceInformation(phoneDescription: String,
                                 firebaseRegistrationToken: String) -> DeviceInformation {
        DeviceInformation(name: phoneDescription,
                          fcmRegistrationToken: firebaseRegistrationToken)
    }
    
    See more

    Declaration

    Swift

    public struct DeviceInformation : Codable
  • The object that updates a device information. The device information change can be used

    • to modify the name of the device and/or
    • to change the Firebase registration token or to disable push notifications.

      Warning

      If neither name(_:) or fcmRegistrationToken(_:) are provided, the provided onSuccess(_:) object will be called when DeviceInformationChange.execute() is invoked.

    Usage example:

    client.operations.deviceInformationChange
        .name(newName)
        .fcmRegistrationToken(fcmToken)
        .onSuccess { in
            ...
        }
        .onError { error in
            ...
        }
        .execute()
    
    client.operations.deviceInformationChange
        .name(newName)
        .disablePushNotifications()
        .onSuccess { in
            ...
        }
        .onError { error in
            ...
        }
        .execute()
    

    Synchronization with retry strategy

    The retry strategy can be useful when updating the Firebase Cloud Messaging token. But since it is not known when the token will be updated, synchronization is necessary and should be done by the caller. Below a sample code is provided that solves the synchronization using dispatch queues and groups.

    import Firebase
    
    class SampleAppMessagingService {
        let queue = DispatchQueue(label: "com.sample.fcm.update.serial")
    }
    
    extension SampleAppMessagingService: MessagingDelegate {
        func messaging(_: Messaging, didReceiveRegistrationToken fcmToken: String?) {
            guard let fcmToken else { return }
            processNewToken(fcmToken, client)
        }
    
        private func processNewToken(_ firebaseRegistrationToken: String, _ client: MobileAuthenticationClient) {
            queue.async {
                let group = DispatchGroup()
                group.enter()
                DispatchQueue.global().async {
                    client.operations.deviceInformationChange
                        .fcmRegistrationToken(firebaseRegistrationToken)
                        .retryPolicy(.constant(maxRetries: 3, delayInSeconds: 30))
                        .onSuccess {
                            defer { group.leave() }
                            // Firebase registration token successfully updated
                        }
                        .onError { _ in
                            defer { group.leave() }
                            // handle unsuccessful update
                        }
                        .execute()
                }
                group.wait()
            }
        }
    }
    
    See more

    Declaration

    Swift

    public protocol DeviceInformationChange : HttpOperation