StoreManager

public class StoreManager : FUIPasscodeValidationDelegate, FUIPasscodeControllerDelegate

StoreManagerStep

StoreManagerStep is responsible to create, open or remove the secure store assigned to an onboarding session. It has several customization options which can be used alone or together to achieve the required functionality.

As a basic behavior the StoreManagerStep creates a new secure in the onboarding flow, opens it in the restoring flow or removes it as part of the reset flow. By default a store is assign to an onboarding session using the onboardingID. For the detailed description of the flows see Onboarding overview.

Customization options

  • Using different secure storage implementations with the step: StoreManagerStep delegates the appropriate kind of store management to an instance of PersistentStoreManaging. This way the same StoreManagerStep class can use different kind of secure stores without the necessity of subclassing or replacing the whole step in the flow. The following store managers are available:
  • No-passcode mode: using the StoreManagerStep in this mode it won’t present any passcode related screens and won’t pass any passcode to the PersistentStoreManaging instance. This mode activated when there is no available FUIPasscodePolicy and the defaultPasscodePolicy is set to nil on the Step instance.
  • Use a custom UUID instead of the onboardingID: the onboardingID is used to differentiate the stores (using in the name of the store) and all related stored information (used in the key). Setting the storeID property on the instance will override the onboardingID. This can be used to share a store among different onboarding sessions (see sharing).
  • Pre-initialized secure store usage during onboarding: in this mode the StoreManagerStep will perform a restore in onboard if the store already exists. It will run onboard if the store doesn’t exists. Use the runRestoreIfStoreExists property to activate this behavior.
  • Alternate onboardingInfoKey usage: as with other onboarding steps it is possible to change the keys which are used to access information in the info field of the OnboardingContext when the automatic mode is used.

Sharing

The StoreManagerStep can be configured to support shared stores. For the description of configuration options see Customization options We can distinguish the stores by the number of users: a ‘private’ store is assigned and used by only on ‘onboarding session’ while a ‘shared’ store used among different ‘onboarding sessions’.

A ‘shared’ store can be ‘locally’ shared so it belongs to a particular application and can be shared among applications. When sharing among applications works only with the KeychainStoreManager which uses ‘keychain sharing’.

It is also possible to use more stores in an ‘onboarding session’. For example when the basic configuration data is stored in a shared store while the user specific information stored in ‘private’ store.

When more stores are used at least the following configuration options should be changed:

  • Custom UUID for the store for the shared store(s)
  • alternate onboardingInfoKey for one of the stores. For example if SAPcpmsSettingsDownloadStep is used you have to decide which store should use the FUIPasscodePolicy downloaded from the server.
  • Pre-initialized mode for the shared store: if the StoreManagerStep should use the already existing shared store during onboarding. For exampel the connection
  • When more StoreManagerSteps are used in an onboarding session wrap the StoreManagerStep (and the steps which have to use that store) into a StoreSelectoreStep.

Handles all the available operations on the application’s credentialstore:

  • create store
  • open store
  • remove store
  • change encryption of store The store instance should be an implementation of the PersistentStoreManaging protocol StoreManager uses multiple screens and passcode/TouchID/FaceID functionalities from SAPFiori.

A StoreManager instance is initialized in StoreManagerStep during onboarding with the required parameters in the StoreManager initializer, which then starts a createStore, which throws FUIPasscodeCreateController from SAPFiori. If the device supports a biometric identifier, such as Touch ID or Face ID and the downloaded passcode policy also allows it, the Touch ID / Face ID screen displays after the passcode creation screens. The user can decide whether or not to use biometrics in the application. When setting the passcode, certain information is stored in the keychain under the application’s default accessGroup. If the developer sets an accessGroup for the StoreManager, the accessGroup must be set, and in every case a storeManager is instantiated later. There is one exception where the passcode create screen is not shown while onboarding: If the developer sets the defaultPasscodepolicy to nil on StoreManagerStep, AND the policies are not assigned to the application on the server. Because of this, the passcode is turned off for the application and does not ask for a passcode when it opens later. This is less secure, and is not recommended. Note: If the defaultPasscodePolicy is set to nil in StoreManager, in every case after initializing an instance from it, the defaultPasscodePolicy must be set to nil. If the defaultPasscodePolicy is not set or is set to the developers own default passcode policy, that becomes the requirement for entering the passcode.

In the restore case, the StoreManagerStep calls the StoreManager’s openStore function which, if a passcode was previously set, presents a FUIPasscodeInputController from SAPFiori. If the user enters an incorrect passcode, the retry limit decrements. If the retry limit reaches zero, the store is locked and all information is lost. The user must onboard again, after resetting the application. If the entered passcode is correct, then the restore flow starts with the previously defined steps.

PasscodePolicyApplyStep is another step that can call changePasscodePolicy on StoreManager: During the restore flow, if the actual settings are downloaded from the server and the passcode policy changes, PasscodePolicyApplyStep calls the changePasscodePolicy(to newPolicy:completionHandler:) on StoreManager, which triggers a passcode change. This change is mandatory and cannot be cancelled. The change is triggered in every case where the server administrator sets a policy that is either weaker or stronger. StoreManager uses a customized FUIFeedbackScreen from SAPFiori to inform the user of any restrictions or additional possibilities regarding setting the passcode policy. The reason for the passcode change is described on that presented screen. The passcode change flow starts after the user taps the ‘Continue’ button.

Possible passcode change flows:

  • No passcode -> passcode ( Turn on passcode, so passcode creation flow without the option to set Face/Touch ID.)
  • No passcode -> passcode with Touch/Face ID (Turn on passcode with biometric ID, so passcode creation flow with the option to enable Face/Touch ID.)
  • Passcode -> Passcode (Passcode change flow, the user has to enter the current passcode again, then set the new passcode and confirm it.)
  • Passcode -> No passcode (Turn off passcode, the user will be notified about the change, has nothing to do. The passcode will be turned off.)
  • Passcode -> Passcode with Touch/Face ID (Starting the automatic change flow will be supported in a later release, currently the Touch/Face ID availability will be added to the ‘availableChangePasscodeOptions’, so manually can be turned on if there is an application screen for setting these options.)
  • Passcode with Touch/Face ID -> Passcode (Turn off Touch/Face ID, the user will be notified about the restriction and can not use the biometric ID from that point to unlock the application.)
  • Passcode with Touch/Face ID -> No passcode (Turn off passcode, the user will be notified about the change, has nothing to do. The passcode and Touch/Face ID will be turned off.)

Developers can provide a screen similar to Settings, where the user can change their own passcode depending on passcode policy and device capabilities: The ‘availablePasscodeActions’ returns an array, which contains the passcode actions which can be performed on StoreManager’s store. This list contains elements depending on passcode policy and device capabilities. After checking the availablePasscodeActions, the developer can call the performPasscodeAction(_ action:completionHandler:) function with the correct PasscodeAction. In this case one of the possible passcode change flows starts, the only difference is that a notification screen does not display by default.

  • FUIPasscodeValidationDelegate used by the FUI passcode screens. For more info @see FUIPasscodeValidationDelegate

    Declaration

    Swift

    public weak var passcodeValidationDelegate: FUIPasscodeValidationDelegate?
  • This prefix will be used to create the store with the onboardingID in the following format: Name-ID

    Declaration

    Swift

    public var secureStoreNamePrefix: String
  • The OnboardingInfoKey associated with an instance of FUIPasscodePolicy in the OnboardingContext info.

    Declaration

    Swift

    public var passcodePolicyInfoKey: OnboardingInfoKey!
  • The keychain access group used to store settings. This property has a default value if the KeychainStoreManager is used as the persistent store manager.

    Declaration

    Swift

    public var accessGroup: String?
  • Default passcode policy for StoreManager. Must be the same as the default policy of StoreManagerStep and PasscodePolicyApplyStep

    Declaration

    Swift

    public var defaultPasscodePolicy: FUIPasscodePolicy?
  • Enable adding additional user-defined passcode policy rules. Must be the same as passcodePolicyRules defined for StoreManagerStep

    Declaration

    Swift

    public var passcodePolicyRules: [FUIPasscodeRule]?
  • If this is true, there will be a Reset Passcode button on the passcode input view when user entered a wrong passcode. The result of the passcode flow will be failed with StoreManagerError.resetPasscode error when user tapped this Reset button. The default value is true.

    Declaration

    Swift

    public var showsResetButton: Bool
  • If this is true, there will be a Cancel button on the passcode input view. The result of this step will be failed with StoreManagerError.cancelPasscodeEntry error when user tapped this Cancel button. The default value is true. In case of passcodeChange which is triggered by policy change on the server, this value is false

    Declaration

    Swift

    public var showsCancelButton: Bool
  • Text of AlertController which is thrown when user taps Cancel during manual passcode change

    Declaration

    Swift

    public var cancelPasscodeChangeAlertTitleText: String
  • Title of the presented FUIFeedbackScreen when the policy changed on the server and passcode change is triggered during restore

    Declaration

    Swift

    public var fuiFeedbackScreenTitleText: String
  • Headline text of the presented FUIFeedbackScreen when the policy changed on the server and passcode change is triggered during restore

    Declaration

    Swift

    public var fuiFeedbackScreenHeadlineDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy changed on the server and passcode change is triggered during restore

    Declaration

    Swift

    public var fuiFeedbackScreenDescription: String
  • Text of button on the presented FUIFeedbackScreen when the policy changed on the server and passcode change is triggered during restore

    Declaration

    Swift

    public var fuiFeedbackScreenButtonText: String
  • Title of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Touch ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableTouchIDTitleText: String
  • Headline text of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Touch ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableTouchIDHeadlineDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Touch ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableTouchIDDetailDescription: String
  • Text of button on the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Touch ID becomes available

    Declaration

    Swift

    public var fuiFeedbackScreenDisableTouchIDButtonText: String
  • Title of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Face ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableFaceIDTitleText: String
  • Headline text of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Face ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableFaceIDHeadlineDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Face ID becomes unavailable

    Declaration

    Swift

    public var fuiFeedbackScreenDisableFaceIDDetailDescription: String
  • Text of button on the presented FUIFeedbackScreen when the policy changed on the server, passcode change is triggered during restore and the Face ID becomes available

    Declaration

    Swift

    public var fuiFeedbackScreenDisableFaceIDButtonText: String
  • Title of the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeTitleText: String
  • Headline text of the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeHeadlineDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeDetailDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode and Touch ID will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeAndTouchIDDetailDescription: String
  • Description text of the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode and Face ID will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeAndFaceIDDetailDescription: String
  • Text of button on the presented FUIFeedbackScreen when the policy has been deleted from the application, turning off passcode is triggered during restore, passcode will be disabled

    Declaration

    Swift

    public var fuiFeedbackScreenTurnOffPasscodeButtonText: String
  • Headline text of FUIFeedbackScreen when the application was updated from an earlier version to rel-2.2 and previously there was only Touch ID or Face ID set. The reason is from rel-2.2 the passcode is mandatory.

    Declaration

    Swift

    public var fuiFeedbackScreenMigrationHeadline: String
  • Description text of FUIFeedbackScreen when the application was updated from an earlier version to rel-2.2 and previously there was only Touch ID or Face ID set. The reason is from rel-2.2 the passcode is mandatory.

    Declaration

    Swift

    public var fuiFeedbackScreenMigrationDescription: String
  • Text of button on FUIFeedbackScreen when the application was updated from an earlier version to rel-2.2 and previously there was only Touch ID or Face ID set. The reason is from rel-2.2 the passcode is mandatory.

    Declaration

    Swift

    public var fuiFeedbackScreenMigrationButtonText: String
  • The actual passcode state of StoreManager

    Declaration

    Swift

    public var passcodeState: PasscodeState { get }
  • Returns the selectable passcode options

    Declaration

    Swift

    public var availablePasscodeActions: [PasscodeAction] { get }
  • Initialize the StoreManager object only for changePasscode

    Declaration

    Swift

    public convenience init(storeID: UUID, credentialStore: CompositeCodableStoring, persistentStoreManager: PersistentStoreManaging = SecureKeyValueStoreManager(), presentationDelegate: FlowPresentationDelegate? = nil, passcodePolicy: FUIPasscodePolicy? = nil)
  • Default initializer

    Declaration

    Swift

    public init()
  • Removes the given store using the persistent store manager.

    Declaration

    Swift

    public func removeStore() throws

    Parameters

    store

    the store to remove

  • presentationDelegate which handles the UIViewController presentations

    Declaration

    Swift

    public var presentationDelegate: FlowPresentationDelegate!
  • Starts a creatStore flow Presents UI to enter passcode, then the credentialStore will be created and encrypted using the given passcode

    Declaration

    Swift

    public func createStore(completionHandler: @escaping (_ error: Error?) -> Void)

    Parameters

    completionHandler

    will be called after the store creation flow ends

  • Starts an openStore flow Presents UI to enter the passcode which will open the store

    Declaration

    Swift

    public func openStore(completionHandler: @escaping (_ error: Error?) -> Void)

    Parameters

    completionHandler

    will be called after the opening the store is finished

  • Depending on available passcode actions, the user can select an action (.createPasscode, turnOffPasscode, turnOffBiometric, etc.) to execute on store Will present UIViewControllers to go through the flow triggered by the given action

    Declaration

    Swift

    public func performPasscodeAction( _ action: PasscodeAction, completionHandler: @escaping (Error?) -> Void )

    Parameters

    action

    a PasscodeAction

    completionHandler

    will be called after the action was performed on the store

  • When the passcodePolicy changes on the server, this function need to be called with the new policy This will trigger an automatic passcode change if it’s necessary

    Declaration

    Swift

    public func changePasscodePolicy(to newPolicy: FUIPasscodePolicy?, completionHandler: @escaping (Error?) -> Void)

    Parameters

    newPolicy

    the new FUIPasscodePolicy object which was downloaded from the server

    completionHandler

    will be called after the flow ends

  • Reset the storeManager

    Declaration

    Swift

    public func reset(storeID: UUID, credentialStore: CompositeCodableStoring, completionHandler: @escaping () -> Void)

    Parameters

    storeID

    storeID of the store

    credentialStore

    CompositeCodableStoring object which has the persistentStore

    completionHandler

    will be called when the process finishes

  • The FUIPasscodePolicy for this app. When run in no-passcode mode, this method is not called.

    Declaration

    Swift

    public func passcodePolicy() -> SAPFiori.FUIPasscodePolicy

    Return Value

    The FUIPasscodePolicy for this app.

  • validate function of FUIPasscodeValidationDelegate Called when the entered passcode has to be validated against the passcodePolicy restrictions. Can be overriden to provide custom implementation

    Throws

    FUIPasscodeControllerError when validation fails.

    Declaration

    Swift

    public func validate(passcode: String) throws

    Parameters

    passcode

    String value, the passcode itself given by the user to be validated

  • Implementation of FUIPasscodeControllerDelegate shouldTryPasscode function Regarding the FUIPasscodeControllerDelegate description, The implementation should try the passcode entered by the user either open the secure store or compare with saved passcode If passcode has not been setup previously, the implementation should accept this passcode and store it as the effective passcode. If passcode was already setup, the implementation should try to match the passcode with saved passcode.

    Throws

    FUIPasscodeControllerError when try passcode failed

    Declaration

    Swift

    public func shouldTryPasscode(_ passcode: String, forInputMode inputMode: FUIPasscodeInputMode, fromController passcodeController: FUIPasscodeController) throws

    Parameters

    passcode

    The passcode entered by the user.

    inputMode

    The purpose of the passcode entered

    passcodeController

    The FUIPasscodeController

  • User has chosen to cancel the passcode setup or enter passcode process. For app to dismiss the Passcode View when appropriate.

    Declaration

    Swift

    public func didCancelPasscodeEntry(fromController passcodeController: FUIPasscodeController)

    Parameters

    passcodeController

    The FUIPasscodeController.

  • User has chosen to skip the passcode setup process. For app to dismiss the Passcode View when appropriate.

    Declaration

    Swift

    public func didSkipPasscodeSetup(fromController passcodeController: SAPFiori.FUIPasscodeController)

    Parameters

    passcodeController

    The FUIPasscodeController.

  • User has chosen to reset the passcode. For application to dismiss the Passcode View when appropriate.

    Declaration

    Swift

    public func shouldResetPasscode(fromController passcodeController: FUIPasscodeController)

    Parameters

    passcodeController

    The FUIPasscodeController.

  • Changed biometric ID

    – Parameter enabled: Bool, wheter it is enabled or not – Parameter passcodeController: the presenter FUIPasscodeController

    Declaration

    Swift

    public func didSetBiometricIDOption(to enabled: Bool, fromController passcodeController: FUIPasscodeController)