Onboarding - basics

There are repeating tasks when an application starts first or restarted later. The network communication has to be set up properly with the appropriate authentication, a secure store should be created which stores the user specific credentials and information. This store should be protected with proper passcode matching a passcode policy, etc. This initialization process is called onboarding, and the components in SAPFioriFlows prefixed with Onboarding are dedicated to help this process. Onboarding related components help the initialization of an application initially or upon app restart. Onboarding binds together the SAPFiori UI components with the SAPFoundation components providing default configurable implementations for the most common tasks. It contains a set of components which provide the most convenient solution. As with other components in the SAPFoundation and the SAPFioriFlows frameworks, any components can be configured or even replaced with a custom implementation if it is necessary.

The initialization/onboarding process in general:

  • Retrieves the configuration from different sources. See Onboarding Configuration.
  • Sets up an SAPURLSession with all the necessary observers and authenticators.
  • Authenticates the user using the selected authentication method to the application endpoint.
  • Creates a store with the appropriate security to store all the credentials and sensitive information gathered during the onboarding flow.

From application lifecycle point of view, there are three main use cases:

  • onboard: when the application is initialized for the first time; general configuration collected and the user onboards to the backend system,
  • restore: the application is restarted after a successful ‘onboard’. Instead of restarting the ‘onboard’, the application ‘restores’, providing users a convenient application start where their information is also persisted and available,
  • reset: the user data is removed and the application is set back to its original state.

The Onboarding solution provided by the SAPFioriFlows framework includes customizable components that can be used together to meet the application’s specific requirements. SAPFioriFlows also provides classes to ease the usage of these components. The recommended way is to use OnboardingSessionManager to create and access an OnboardingSession. It uses an OnboardingController to perform onboard/restore with the appropriate OnboardingFlow. In more details, see Managing the application lifecycle...

To understand the different components and concepts, please read the following chapters:

  1. Onboarding Step
  2. Onboarding Flow
  3. Onboarding Session

Other useful topics:

  1. Predefined OnboardingSteps in the SDK
  2. About cookies and web based authentications
  3. Modes of running the flows directly
  4. Presenting screens
  5. Running the flow: an example
  6. Offline Support

Onboarding Step

The tasks necessary to achieve the onboarded state of the application are encapsulated in different classes called steps. Each step has a well defined dedicated task. Getting the initial configuration, configuring the SAPURLSession, performing authentication, downloading settings and configuration from SAPcpms, applying different policies from the settings, creating the secure store, etc. The series of steps bound together in a pre-defined order is called the onboarding flow. Each step has three main use cases:

  • onboard: called when the application is being initialized. Each step is responsible for persisting the gathered data, so steps should be able to restore themselves later. Steps use the secure store for this purpose.
  • restore: called when the application is restarted and restores its state. Each step is responsible to be able to perform their dedicated tasks and/or load the data which was gathered during onboard. When they populate data for other steps, it is also mandatory to provide this data.
  • reset: called when the application gets reset. Steps should reset what they have modified during onboard or restore and remove data which had been persisted.

SAPFioriFlows includes several steps, each of them with different functionality. See Predefined OnboardingSteps in the SDK. You can implement your own OnboardingSteps, or use OnboardingSteps included in the SAPFioriFlows framework.

Pass data among steps using OnboardingContext: info is a flat dictionary with given keys (OnboardingInfoKey). Each step defines properties containing an OnboardingInfoKey, which they use to access the required information in the info field. The values of these keys can be configured if necessary.

If a step gathers any data that might be needed in the future, for example in case of a restart, it should be persisted physically in the store by the step itself. The step that requires this data can load it when needed. If that data is used by other steps as well (for example, a configuration) the step must load it back to the info field.

Onboarding Flow

A flow is a set of steps in a given order associated with the ‘context’ used by the steps. The steps use this ‘context’ to look for data as well as to add data. The context can have initial data what the steps use. The steps also modify the context during the flow updating existing values or adding new ones. The recommended way is to create an OnboardingFlow when it is required - see later.
There are three types of flows based on the state of the application:

  • onboarding flow – The application starts from an initial state (the first run or after a reset).
  • restoring flow – The application starts, but a persisted state already exists.
  • resetting flow – called to ‘reset’ the application, cleaning up all stored information, invalidating any applied configuration.

A flow can contain any number of steps appropriate for the application. The steps used in a flow can be in any order that makes sense for the application, and it is not controlled by the SDK. It is up to the application developer to configure and set up the flows properly. Each step has its own set of arguments which are needed to perform its tasks.

A general “onboarding flow” consists of:

  • the WelcomeScreenStep which also gathers configuration and stores it in the store,
  • an authentication step, which configures the SAPURLSession with the appropriate observer and authenticator, performs the authentication,
  • the default settings download steps, which gathers the settings (for example PasswordPolicy) from the SAPcpms,
  • the default apply steps for onboaring,
  • StoreManagerStep, which creates the store.

A general “restoring flow” contains the same steps but starts with the StoreManagerStep which opens the existing SecureStore:

  • StoreManagerStep: opens the SecureStore,
  • WelcomeScreenStep reloads the configuration from the store,
  • an authentication step,
  • the default settings download steps, which gather the settings, for example PasswordPolicy,
  • the default apply steps for restoring.

Onboarding Session

After the onboard or restore flow has finished successfully, the application usually gets an SAPURLSession, a secure store and information in the info field of the OnboardingContext. This state is called ‘onboarding session’. Your application can be implemented to use these objects directly but the recommended way to use OnboardingSession, which can be used and referenced by the application during runtime. Please refer the Managing the application lifecycle... documentation for more detail.

Predefined OnboardingSteps in the SDK

Steps can be grouped based on their functionality:

About cookies and web based authentications

The SDK’s default behavior is to provide a secure environment for the application. The different onboarding sessions are separated properly so different users are not able to access sensitive data of other users, even in the same application. This should be considered as each onboarding session lives in its own bundle. Another important requirement is that removing an onboarding session should remove all related data and no data should remain on the device which can be bound to a user.

Note

the Onboarding component controls only the data that was created by onboarding using the given protocols. Other data stored by the application that relates to the onboarding session should be cleared up by the application code.

When onboarding is used with OnboardingContext and the context is created with the default initializer, then the cookie storage of the SAPURLSession is configured to use the secure store in the same context. In addition, when authentication observers are used with an SAPURLSession configured such way that the authentication uses WKWebView, then the following steps will be performed:

  • cookies are copied to the cookie store of the WebView from the secure storage when the web view is presented,
  • authentication is performed using the web view,
  • cookies are copied from the cookie store of the web view to the secure storage,
  • finally, the cookie store of the web view will be cleared: all the cookies modified by the authentication will be removed.

Some web based authentication provides functionality to persist settings regarding the authentication as a cookie using the cookie store of the networking component. For example ‘remember me’ during OAuth or SAML or other similar options. These are implemented usually by setting a persistent cookie on the client side. According to the behavior described above, these cookies are saved in the secure storage of the given onboarding session and cannot be accessed besides by the owner of the onboarding session. When the onboarding session gets deleted all the data will be deleted as well - so these cookies as well.

There are different Web views provided by Apple - and each has different characteristics and functionality. UIWebView is the oldest one and it is removed. WKWebView is better and newer, but since the application can still access information in there, it is not considered to be as secure as SF*/AS* classes. SFSafariViewController and ASWebAuthenticationSession use their own separate data store. Apple provides these specialized WebViews intentionally to exclude developers – not to be able to access any user related data, even cookies. Application code cannot access or modify the cookies/cached data in this case. So any ‘persistent’ cookie stored there - remains there. This, however can lead to security questions if the web site stores information in cookies. At that level, there is no distinction of users. It is only the application owner who can decide to trust in the sites and users to support this ‘shared cookie’ scenario. The SDK, by default separates the cookie storage using WKWebView - but cannot separate using SF*/AS* web views. WKWebView provides the ability that the caller can track the changes in the web view. The SDK checks the URL changes and stops the web view when it reaches the ‘redirect url’. SF*/AS* web views are ‘sandboxed’ so this is not possible. It is possible to use, for example OAuth by assigning the application with a URLScheme and then the server must be adjusted to set the redirect url to a url using this url scheme. This is documented in the SDK at OAuth2Authenticator On server side, the application can be configured in the ‘Mobile Service for Development and Operations’ / ‘Assigned features’ / ‘Security’ / ‘Configuration’. Note, that SF*/AS* web views are different from WK web view, as they are not so customizable. So you cannot hide the title, for example, as it is intentionally designed by Apple, so users can see it is a trusted web view - so they can provide their credentials without the risk of the application stealing it.

Modes of running the flow directly

In general, the recommended way to perform onboarding is to use OnboardingSessionManager. Please refer to Managing the application lifecycle... documentation for more details.

However, it is poissible to manage the execution of the onboarding flow directly.

There are two ways to use the OnboardingSteps:

Usually the steps are implemented in a way where the “automatic” methods call the “manual” method internally so the methods behavior is guaranteed to be the same.

See OAuth2AuthenticationStep for an example. It declares a low-level onboard method and a higher-level onboard method (which conforms to OnboardingStep protocol supporting automatic flow management):

// 'automatic' flow management method conforming to `OnboardingStep`
public func onboard(context: OnboardingContext, completionHandler: @escaping (OnboardingResult) -> Void)

// 'manual' flow management method: lists the properties the step needs
open func onboard(authenticationURL: URL, authenticationParameters: OAuth2AuthenticationParameters, sapURLSession: SAPURLSession, credentialStore: CodableStoring, presentationDelegate: FlowPresentationDelegate, completionHandler: @escaping (Error?) -> Void)

Presenting screens

The application can present a splash screen when the onboarding flow starts. This screen hides the application screen between the steps and also provides a consistent background for the onboarding flow. There are more splash screen use-cases. In every case, the developer must handle when to present the screen before the onboarding flow starts and dismiss the screen when the flow finishes.

  1. There is no splash screen set to PresentationDelegate The application screen is observable for a moment every time it moves between onboarding steps. If the app presents its splash screen before the onboarding flow starts, it will be visible. That screen can be replaced by the appropriate application screen at the end of the onboarding flow.

  2. The application starts with InfoViewController as a root view controller: this can be set as a splash screen to the ModalUIViewControllerPresenter (when it is used as PresentationDelegate - default) and will be visible instead of the application screen when moving between steps. The information text on the screen will be updated by the steps automatically. The developer must replace it with the application view controllers at the end of the onboarding flow:

    // instantiate the splashScreen, set it to `presentationDelegate` then start the flow
    let splashScreen = FUIInfoViewController.createSplashScreenInstanceFromStoryboard()
    <# Set it as the rootViewController #>
    // set as splash for onboarding
    presentationDelegate.setSplashScreen(splashScreen)
    
    <# run the onboarding or restoring flow #>
    
    // when the onboarding flow was successful, clear the splash screen
    (context.presentationDelegate as! ModalUIViewControllerPresenter).presentationDelegate.clearSplashScreen()
    

    You can use any custom ViewController as a splash screen if it conforms to the InfoTextSettable protocol, which can be implemented as an extension to any existing ViewController.

  3. When starting the application, the main application screen is visible, then a splash screen must be opened over the application screen using the present method of the FlowPresentationDelegate. This splash screen is visible when switching between steps. The information text on the screen will be updated by the steps automatically. You must add code to close the screen by calling dismiss on the PresentationDelegate after the onboarding flow finishes:

    // instantiate the splashScreen, call present on presentationDelegate, then in callback start the flow
    let splashScreen = FUIInfoViewController.createSplashScreenInstanceFromStoryboard()
    presentationDelegate.present(splashScreen) { _ in
      <# run the onboarding or restoring flow #>
    }
    
    // when the onboarding flow was successful, call dismiss on presentationDelegate
    context.presentationDelegate.dismiss { _ in
    }
    

Note: By default, the ModalUIViewControllerPresenter overrides the modalPresentationStyle property of the presented view controllers to .overFullScreen. This makes it possible to correctly present view controllers on top of everything, including UIAlertController. However when using this presentation style, some of the underlying view controller’s methods (viewWillDisappear, viewWillAppear) will not be called when they are hidden / shown again. You can change the default presentation style any time on ModalUIViewControllerPresenter.

Running the flow directly: an example

As described in Flow and Modes of running the flow sections, the following sample presents a general way of running an onboarding and restoring flow:

let presentationDelegate = ModalUIViewControllerPresenter()
<# Initialize, present and set the splash screen #>
presentationDelegate.setSplashScreen(<# your splash screen instance #>)
onboardOrRestore() // start the proper flow

func onboardOrRestore() {

    // declare the steps: you can use different instances as well for the onboarding/restoring flows
    let welcome = WelcomeScreenStep(providers: [<# list your configuration providers #>]) // welcome and configuration management
    let sessionConf = SAPcpmsSessionConfigurationStep() // SAPcpms compatibility
    let auth = OAuth2AuthenticationStep() // authentication
    let settings = SAPcpmsSettingsDownloadStep() // download and apply the settings
    let store = StoreManagerStep() // store management

    // initialize context
    var context = OnboardingContext(presentationDelegate: presentationDelegate)
    let onboardingFlow: [OnboardingStep] = [welcome, sessionConf, auth, settings, store]
    let restoringFlow: [OnboardingStep] = [store, welcome, sessionConf, auth, settings]

    if let savedUUIDString = UserDefaults.standard.string(forKey: "userOnboardingID"), let uuid = UUID(uuidString: savedUUIDString) {
        context.onboardingID = uuid
        OnboardingFlowController.restore(on: restoringFlow, context: context) { result
        <# handle the result, start the application logic #>
        }
    } else {
        OnboardingFlowController.onboard(on: onboardingFlow, context: context) { result
            <#handle the result and persist the onboardingID in case of success #>

            UserDefaults.standard.set(context.onboardingID.uuidString, forKey:"userOnboardingID")

            <# Save the required properties from the context to your app: SAPURLSession, Store, etc. Never save the whole context! #>

            <# start the application logic #>
        }
    }
}

Note: A production application is more complicated and must properly handle error and success cases. Use the SAP BTP SDK for iOS Assistant to generate a more detailed sample application.

Offline Support

Offline Restore can be useful in scenarios where the application is offline most of the time. Once the user has onboarded, it allows the application to restore data offline, without a network connection. Onboarding steps in the SAPFioriFlows component gracefully handle network conditions when restoring while offline. The user should not view errors related to connectivity when using the offline database.

Using the Offline Restore flow

The following example shows you how to use the offline restore functionality with SAPFoundation‘s ConnectivityObserver to synchronize cloud application state at runtime.

First, let’s define a synching flow which consists of the following OnboardingSteps. You may customize yours.

let synching: [OnboardingStep] = [
    WelcomeScreenStep(), // configure if necessary
    SAPcpmsSettingsDownloadStep(),
    SAPcpmsDestinationsDownloadStep(),
    SAPcpmsLogSettingsApplyStep(),
    SAPcpmsUsagePolicyApplyStep(),
    PasscodePolicyApplyStep(),
    SAPcpmsLockWipePolicyApplyStep()
]

Add the following code snippet to your class’s initializer:

ConnectivityReceiver.registerObserver(self)

Then, let’s conform to the ConnectivityObserver protocol by implementing its methods.

func connectionEstablished() {
    print("Network connection detected.")
}

func connectionChanged(_ previousReachabilityType: ReachabilityType, reachabilityType: ReachabilityType) {
    print("Network connection status changed.")
    if case previousReachabilityType = ReachabilityType.offline {
        do {
            // run your snyhcronizing flow
        } catch {
            print("Could not synchronize after connectionChanged(previousReachabilityType:reachabilityType:)")
        }
    }
}

func connectionLost() {
    print("Network connection lost.")
}
  • Onboarding step implementation of Basic Authentication Used in the onboarding/restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with basic authentication protected resources. Creates and registers the BasicAuthenticationObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    // The customized WelcomeStep can be created like the following code snippet
    func customBasicAuthStep() -> OnboardingStep {
       let basicAuthenticationBundle = Bundle(for: BasicAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("BasicInfoScreenText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Validating Basic credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Cancel", comment: "")
       let localizedInformationLabelText = NSLocalizedString("BasicInformationLabelTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Authentication", comment: "")
       let localizedHeadLineLabelText = NSLocalizedString("BasicHeadLineLabelTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Please enter your credentials", comment: "")
       let localizedSignInButtonText = NSLocalizedString("BasicSignInButtonText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Sign In", comment: "")
       let localizedUsernamePlaceholderText = NSLocalizedString("BasicUsernamePlaceholderTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Username", comment: "")
       let localizedPasswordPlaceholderText = NSLocalizedString("BasicPasswordPlaceholderTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Password", comment: "")
    
       let presenter = FioriBasicCredentialsViewControllerPresenter()
       presenter.basicViewControllerConfigurationHandler = { basicView in
            basicView.headlineLabel.text = localizedHeadLineLabelText
            basicView.informationLabel.text = localizedInformationLabelText
            basicView.signInButton.titleLabel?.text = localizedSignInButtonText
            basicView.usernameTextField.emailTextField.placeholder = localizedUsernamePlaceholderText
            basicView.passwordTextField.emailTextField.placeholder = localizedPasswordPlaceholderText
            basicView.navigationItem.leftBarButtonItem?.title = localizedCancelButtonText
       }
       let step = BasicAuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class BasicAuthenticationStep : OnboardingStep
  • This step collects and executes substeps. The defined queues in SAPcpmsDefaultSteps are available to perform specific operations groupped around a specific behavior:

    • SAPURLSession configuration steps
    • SAPcpms settings and configuration download steps
    • SAPcpms settings and configuration apply steps Example how to initialize a download queue:
    let compositeStep = CompositeStep(steps: SAPcpmsDefaultSteps.settingsDownload)
    

    The compositeStep instance now can be placed in the onboarding flow. The queues are proposals how to run the default flow. The flow is customizable with the available supsteps: SAPcpmsSessionConfigurationStep SAPcpmsCorrelationConfigurationStep LanguageObserverConfigurationStep SAPcpmsSettingsDownloadStep SAPcpmsDestinationsDownloadStep SAPcpmsLogSettingsApplyStep SAPcpmsUsagePolicyApplyStep PasscodePolicyApplyStep SAPcpmsLockWipePolicyApplyStep

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    
    // The localized CompositeStep can be created like the following code snippet
    func customCompositeStep() -> OnboardingStep {
       let step = CompositeStep()
    
       let compositeBundle = Bundle(for: CompositeStep)
       step.infoScreenText = NSLocalizedString("CompositeStepInfoScreenTextKey", tableName: "ExampleTableName", bundle: compositeBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class CompositeStep : OnboardingStep
  • Manages the End User License Agreement (EULA) handling. The EULA version will be stored in the credentialStore of the OnboardingContext which is used to decide if a new EULA screen should be presented on the next run. If the user has not confirmed EULA, or a new EULA content is present, a screen will be displayed to request user confirmation.

    Usage

    let title = "SAP - EULA"
    let text = """
    This is a legally binding agreement (Agreement) between Company and SAP SE which provides the terms of your use of the SAP mobile application (Software). By clicking "Accept" or by installing and/or using the Software, you on behalf of the Company are agreeing to all of the terms and conditions stated in this Agreement. If you do not agree to these terms, do not click "Agree", and do not use the Software. You represent and warrant that you have the authority to bind the Company to the terms of this Agreement.
    """
    let attributes = [NSAttributedStringKey.font: UIFont(name: "Georgia", size: 17.0)!]
    let content = NSAttributedString(string: content, attributes: attributes)
    let eulaContent = EULAContent(title: title, content: content, version: "1.0")
    let eulaStep = EULAStep(eulaContent: eulaContent)
    
    See more

    Declaration

    Swift

    open class EULAStep : OnboardingStep, FUIEULADelegate
  • Instantiates an OnboardingStep capable of registering the LanguageObserver in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    sapURLSession.register(LanguageObserver())
    
    See more

    Declaration

    Swift

    open class LanguageObserverConfigurationStep : SimpleTaskStep
  • OAuth 2.0 onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with OAuth 2.0 protected resources. Creates and registers the OAuth2Observer to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customOauth2AuthStep() -> OnboardingStep {
       let oauth2Bundle = Bundle(for: OAuth2AuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("Oauth2InfoScreenText", tableName: "Example Table name", bundle: oauth2Bundle, value: "Validating OAuth2 credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: oauth2Bundle, value: "Cancel", comment: "")
    
       let presenter = FioriWKWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = OAuth2AuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class OAuth2AuthenticationStep : OnboardingStep
  • OnboardingStep Represents a step in the onboarding/restoring flow.

    See more

    Declaration

    Swift

    public protocol OnboardingStep : AnyObject
  • OTP onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with OTP protected resources. Creates and registers the OTPObserver. This step should be set before the authentication step (can be used with Basic, OAuth 2.0 and SAML 2.0 authentications).

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customOTPAuthStep() -> OnboardingStep {
       let otpBundle = Bundle(for: OTPSessionConfigurationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("OTPInfoScreenText", tableName: "Example Table name", bundle: otpBundle, value: "Validating OTP credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: otpBundle, value: "Cancel", comment: "")
    
       let presenter = FioriWKWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = OTPSessionConfigurationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class OTPSessionConfigurationStep : OnboardingStep
  • Instantiates an OnboardingStep capable of applying the PasscodePolicy parameters in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

           let storeManager = StoreManager()
           storeManager.applyNewPolicy(passcodePolicy)
    
    See more

    Declaration

    Swift

    open class PasscodePolicyApplyStep : OnboardingStep
  • SAML 2.0 onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with SAML 2.0 protected resources. Creates and registers the SAMLObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customSAMLAuthStep() -> OnboardingStep {
       let samlBundle = Bundle(for: SAMLAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("SAMLInfoScreenText", tableName: "Example Table name", bundle: samlBundle, value: "Validating SAML credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: samlBundle, value: "Cancel", comment: "")
    
       let presenter = FioriWKWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = SAMLAuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class SAMLAuthenticationStep : OnboardingStep
  • Class for SAPcpmsClientResources download onboarding step handling

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    
    // The localized SAPcpmsClientResourcesDownloadStep can be created like the following code snippet
    func customClientResourcesDownloadStep() -> OnboardingStep {
       let step = SAPcpmsClientResourcesDownloadStep()
    
       let sapcpmsClientResourcesDownloadStep = Bundle(for: SAPcpmsClientResourcesDownloadStep.self)
       step.infoScreenText = NSLocalizedString("SAPcpmsClientResourcesDownloadInfoScreenTextKey", tableName: "ExampleTableName", bundle: sapcpmsDestinationDownloadBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class SAPcpmsClientResourcesDownloadStep : OnboardingStep
  • Instantiates an OnboardingStep capable of registering the CorrelationObserver observer in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    let sapURLSession = <#SAPURLSession#>
    sapURLSession.register(<#CorrelationObserver#>)
    
    See more

    Declaration

    Swift

    open class SAPcpmsCorrelationConfigurationStep : SimpleTaskStep
  • // Definition of default SAPcpms steps

    See more

    Declaration

    Swift

    public class SAPcpmsDefaultSteps
  • Class for SAPcpmsDestinations download onboarding step handling

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    
    // The localized SAPcpmsDestinationsDownloadStep can be created like the following code snippet
    func customDestinationsDownloadStep() -> OnboardingStep {
       let step = SAPcpmsDestinationsDownloadStep()
    
       let sapcpmsDestinationsDownloadStep = Bundle(for: SAPcpmsDestinationsDownloadStep.self)
       step.infoScreenText = NSLocalizedString("SAPcpmsDestinationsDownloadInfoScreenTextKey", tableName: "ExampleTableName", bundle: sapcpmsDestinationDownloadBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class SAPcpmsDestinationsDownloadStep : OnboardingStep
  • Instantiates an OnboardingStep capable of applying the SAPcpmsLogSettings parameters in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    Logger.root.apply(sapcpmsLogSettings: <#SAPcpmsLogSettings#>)
    
    See more

    Declaration

    Swift

    open class SAPcpmsLogSettingsApplyStep : SimpleTaskStep
  • Instantiates an OnboardingStep capable of registering the SAPcpmsObserver observer in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    let sapURLSession = <#SAPURLSession#>
    sapURLSession.register(<#SAPcpmsObserver#>)
    
    See more

    Declaration

    Swift

    open class SAPcpmsSessionConfigurationStep : SimpleTaskStep
  • Class for SAPcpmsSettings download onboarding step handling

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    
    // The localized SAPcpmsSettingsDownloadStep can be created like the following code snippet
    func customSettingsDownloadStep() -> OnboardingStep {
       let step = SAPcpmsSettingsDownloadStep()
    
       let sapcpmsSettingsDownloadBundle = Bundle(for: SAPcpmsSettingsDownloadStep.self)
       step.infoScreenText = NSLocalizedString("SAPcpmsSettingsDownloadInfoScreenTextKey", tableName: "ExampleTableName", bundle: sapcpmsSettingsDownloadBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class SAPcpmsSettingsDownloadStep : OnboardingStep
  • Class for SAPcpmsUsagePolicy and SAPcpmsSettings onboarding step handling to configure SAPFoundation.UsageBroker Singleton object.

    See more

    Declaration

    Swift

    open class SAPcpmsUsagePolicyApplyStep : OnboardingStep
  • Instantiates an OnboardingStep capable of registering the SAPcpmsUserBlockedObserver observer in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    let sapURLSession = <#SAPURLSession#>
    sapURLSession.register(<#SAPcpmsUserBlockedObserver#>)
    
    See more

    Declaration

    Swift

    open class SAPcpmsUserBlockedConfigurationStep : SimpleTaskStep
  • Onboarding step implementation of SAPcpmsUserIdentityDiscovery Authentication Used in the onboarding/restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with SAPcpmsUserIdentityDiscovery authentication protected resources. Creates and registers the UserIdentityObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    
    //The localized SAPcpmsUserIdentityDiscoveryAuthenticationStep can be created like the following code snippet
    func customSAPcpmsUserIdentityDiscoveryAuthenticationStep() -> OnboardingStep {
       let step = SAPcpmsUserIdentityDiscoveryAuthenticationStep()
    
       let userIdentityDiscoveryAuthenticationBundle = Bundle(for: SAPcpmsUserIdentityDiscoveryAuthenticationStep.self)
       step.infoScreenText = NSLocalizedString("UserIdentityDiscoveryInfoScreenTextKey", tableName: "ExampleTableName", bundle: userIdentityDiscoveryAuthenticationBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class SAPcpmsUserIdentityDiscoveryAuthenticationStep : OnboardingStep
  • This step is capable of integrating a simple functionality into the onboarding flow, without the need to implement the whole OnboardingStep protocol. Provides a convenient way of using the same piece of logic for both onboard and restore processes.

    See more

    Declaration

    Swift

    open class SimpleTaskStep : OnboardingStep
  • Onboarding step implementation of SLS certificate authentication Used in the onboarding/restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with SLS authentication protected resources. Creates and registers the UserIdentityObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    // The customized WelcomeStep can be created like the following code snippet
    func customSLSAuthStep() -> OnboardingStep {
       let slsAuthenticationBundle = Bundle(for: SLSAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("SLSInfoScreenText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Validating credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Cancel", comment: "")
       let localizedInformationLabelText = NSLocalizedString("SLSInformationLabelTextKey", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Please enter your credentials", comment: "")
       let localizedSignInButtonText = NSLocalizedString("SLSSignInButtonText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Sign In", comment: "")
    
       let presenter = SLSLoginInputPresenter()
       presenter.loginViewControllerConfigurationHandler = { viewController in
            viewController.informationLabel.text = localizedInformationLabelText
            viewController.navigationItem.leftBarButtonItem?.title = localizedCancelButtonText
            viewController.navigationItem.rightBarButtonItem?.title = localizedSignInButtonText
       }
       let step = SLSAuthenticationStep(slsLoginInputPresenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class SLSAuthenticationStep : OnboardingStep
  • Manages the User Consent Handling. The version for each user consent form will be stored in the credentialStore of the OnboardingContext which is used to decide if a newer version of the form should be presented in the next run. If a new version for the form is present, the form will be displayed in the next run to request user confirmation.

    Usage

    // Content for the single page form
    let spTitle = "Data Privacy"
    let spText = "Detailed text about how data privacy pertains to this app and why it is important for the user to enable this functionality"
    let spActionTitle = "Learn more about Data Privacy"
    
    var spPageContent = UserConsentPageContent()
    spPageContent.title = spTitle
    spPageContent.body = spText
    spPageContent.actionTitle = spActionTitle
    spPageContent.actionUrl = "http://www.sap.com"
    let spFormContent = UserConsentFormContent( version: "one",isRequired: true,pages: [spPageContent])
    
    //Content for the multi Page form
    let mpTitle1 = "Data Privacy"
    let mpText1 = "Detailed text about how data privacy pertains to this app and why it is important for the user to enable this functionality"
    let mpActionTitle1 = "Learn more about Data Privacy"
    var mpPageContent1 = UserConsentPageContent()
    mpPageContent1.title = mpTitle1
    mpPageContent1.body = mpText1
    mpPageContent1.actionTitle =  mpActionTitle1
    mpPageContent1.actionHandler = { controller in
       let alert = UIAlertController(title: "Data Privacy", message: "Alert for Data Privacy Page", preferredStyle: UIAlertControllerStyle.alert)
       alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
       controller.present(alert, animated: true, completion: nil)
    }
    
    let mpTitle2 = "Security"
    let mpText2 = "Detailed text about how data privacy pertains to this app and why it is important for the user to enable this functionality"
    let mpActionTitle2 = "Learn more about Data Privacy"
    var mpPageContent2 = UserConsentPageContent()
    mpPageContent2.title = mpTitle2
    mpPageContent2.body = mpText2
    mpPageContent2.actionTitle =  mpActionTitle2
    // When both url and action handler are set, the action handler takes precedence.
    mpPageContent2.actionUrl = "http://www.sap.com"
    mpPageContent2.actionHandler = { controller in
       let alert = UIAlertController(title: "Data Privacy", message: "Alert for Data Privacy Page", preferredStyle: UIAlertControllerStyle.alert)
      alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
      controller.present(alert, animated: true, completion: nil)
    }
    
    let mpTitle3 = "Consent"
    let mpText3 = "Detailed text about how data privacy pertains to this app and why it is important for the user to enable this functionality"
    
    let mpActionTitle3 = "Learn more about Data Privacy"
    var mpPageContent3 = UserConsentPageContent()
    mpPageContent3.title = mpTitle3
    
    // It is possible to provide attributed text to enable adding developer defined attributes to the text other than the default.
    // Eg. change the font type to "Georgia" and size to "17.0" for the body. This can be done for the title and actionTitle as well , using the
    // titleAttributedText and actionTitleAttributedText respectively. When both body and bodyAttributedText are provided , the
    // attributedtext version takes precedence.
    //        let mpAttributes3 = [NSAttributedStringKey.font: UIFont(name: "Georgia", size: 17.0)!]
    //        let mpBody3 = NSAttributedString(string: mpText3, attributes: mpAttributes3)
    //        mpPageContent3.bodyAttributedText = mpBody3
    
    mpPageContent3.body = mpText3
    mpPageContent3.actionTitle =  mpActionTitle3
    
    let mpFormContent = UserConsentFormContent( version: "one",isRequired: true,pages: [mpPageContent1, mpPageContent2, mpPageContent3])
    let userConsentStep  =  UserConsentStep(userConsentFormsContent:[spFormContent, mpFormContent])
    
    See more

    Declaration

    Swift

    open class UserConsentStep : OnboardingStep, FUIUserConsentViewControllerDelegate
  • Class for Welcome Screen onboarding step handling UI elements of the Welcome Screen are localizable through the step’s welcomeScreenCustomizationHandler which will be called during the WelcomeStep onboarding process to configure the screen.

    ## Customization

    
     // The customized WelcomeStep can be created like the following code snippet
     func configuredWelcomeScreenStep() -> WelcomeScreenStep {
        let discoveryConfigurationTransformer = DiscoveryServiceConfigurationTransformer(applicationID: "sample.application.id", authenticationPath: "sample.application.id")
        let welcomeScreen = WelcomeScreenStep(transformer: discoveryConfigurationTransformer, providers: [FileConfigurationProvider()])
    
       let welcomeScreenBundle = Bundle(for: WelcomeScreenStep.self)
       let localizedHeadlineLabelText = NSLocalizedString("WelcomeScreenHeadlineLabelKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedDetailLabelText = NSLocalizedString("WelcomeScreenDetailLabelKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedPrimaryActionButtonText = NSLocalizedString("WelcomeScreenPrimaryActionButtonTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedFootnoteActionButtonTitleText = NSLocalizedString("WelcomeScreenFootnoteActionButtonTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedFootnoteLabelText = NSLocalizedString("WelcomeScreenFootnoteLabelTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
    
       welcomeScreen.welcomeScreenCustomizationHandler = { welcomeScreen in
           welcomeScreen.headlineLabel.text = localizedHeadlineLabelText
           welcomeScreen.detailLabel.text = localizedDetailLabelText
           welcomeScreen.primaryActionButton.titleLabel?.text = localizedPrimaryActionButtonText
           welcomeScreen.footnoteActionButton.setTitle(localizedFootnoteActionButtonTitleText, for: .normal)
           welcomeScreen.footnoteLabel.text = localizedFootnoteLabelText
       }
    
       return welcomeScreen
     }
    
    
    See more

    Declaration

    Swift

    open class WelcomeScreenStep : OnboardingStep, FUIWelcomeControllerDelegate
    extension WelcomeScreenStep: ConfigurationLoaderDelegate
    extension WelcomeScreenStep: ConfigurationPersisting
    extension WelcomeScreenStep: FUIOnboardingScanViewControllerDelegate
  • The default implementation for the ASWebAuthenticationSessionPresenting. Presents a ASWebAuthenticationSession on demand, can be configured to show an info screen before the presentation.

    See more

    Declaration

    Swift

    open class FioriASWebAuthenticationSessionPresenter : ASWebAuthenticationSessionPresenting, FlowPresentationDelegateClient
  • Presenter to handle BasicCredentialsViewController presentation

    See more

    Declaration

    Swift

    open class FioriBasicCredentialsViewControllerPresenter : FlowPresentationDelegateClient, BasicCredentialDiscovery, FUIBasicAuthenticationDelegate
  • The default implementation for the SFSafariViewControllerPresenting. Presents a SFSafariViewController on demand, can be configured to show an info screen before the presentation.

    See more

    Declaration

    Swift

    open class FioriSFSafariViewControllerPresenter : NSObject, SFSafariViewControllerPresenting, FlowPresentationDelegateClient
    extension FioriSFSafariViewControllerPresenter: SFSafariViewControllerDelegate
  • The default implementation for the WKWebViewPresenting. Presents a WKWebView on demand, can be configured to show an info screen before the presentation.

    Default WKUIDelegate implementation provided with this presenter handles popups. Using a custom implementation (of WKWebViewPresenting && FlowPresentationDelegateClient) and injecting that custom implementation as presenter in OAuth2AuthenticationStep would have to take care of that.

    See more

    Declaration

    Swift

    open class FioriWKWebViewPresenter : WKWebViewPresenting, FlowPresentationDelegateClient
    extension FioriWKWebViewPresenter: FUIWebViewContainerDelegate
  • This FlowPresentationDelegate implementation handles the screen presentation in such a way, that every present call results in a modal presentation on the top-most view controller.

    Important: This implementation requires that every present call have their own dismiss call pair. Self dismissing view controllers such as UIAlertControllers are not supported.

    See more

    Declaration

    Swift

    open class ModalUIViewControllerPresenter : FlowPresentationDelegate
  • SLSLoginInputDelegate implementation to communicate between the Foundation and the UI implementation

    See more

    Declaration

    Swift

    open class SLSLoginInputPresenter : FlowPresentationDelegateClient, SLSLoginInputDelegate, FUIDynamicAuthenticationDelegate
  • The content of the EULA screen. Contains a title and an NSAttributedString as the content value.

    See more

    Declaration

    Swift

    public struct EULAContent
  • Declaration

    Swift

    extension FUIInfoViewController: InfoTextSettable
  • Declaration

    Swift

    extension FUIOnboardingScanConfirmView: ScanConfirmViewUI
  • Initializes SAPcpms Settings Password Policy from config file

    See more

    Declaration

    Swift

    public extension FUIPasscodePolicy
  • Declaration

    Swift

    extension FUIWelcomeScreen: WelcomeStepUI
  • Set of options that determine when to present info screen.

    See more

    Declaration

    Swift

    public struct InfoScreenPresentationOptions : OptionSet
  • Keys defined to access objects in a dictionary a typed way To extend the available keys define your own key the following way

     public extension OnboardingInfoKey {
         public static let myDeclaredKey = OnboardingInfoKey("myDeclaredKey")
    }
    

    Then you can use this to access information in the Dictionary

     var info = [OnboardingInfoKey: Any]()
     info[.myDeclaredKey] = MyStruct()
    
    See more

    Declaration

    Swift

    public struct OnboardingInfoKey : RawRepresentable, Equatable, Hashable, CustomStringConvertible, CustomDebugStringConvertible
  • The content of User Consent Forms.

    See more

    Declaration

    Swift

    public struct UserConsentFormContent
  • The contents of a user consent page in a form. Each page corresponds to a screen displayed the user. A form can consist of one page or multiple pages that get displayed when the form is presented.

    See more

    Declaration

    Swift

    public struct UserConsentPageContent
  • Enum to handle errors in EULAStep

    See more

    Declaration

    Swift

    public enum EULAError : Error
    extension EULAError: SAPError
  • Enum for presentation errors

    • failed: presentation failed
    • missing: viewcontroller is missing
    • cancelled: presentation cancelled
    See more

    Declaration

    Swift

    public enum FioriPresenterError : Error
    extension FioriPresenterError: SAPError
  • Set of error that could occur in SAPcpmsLockWipePolicyApplyStep

    See more

    Declaration

    Swift

    public enum SAPcpmsLockWipePolicyError : Error
    extension SAPcpmsLockWipePolicyError: SAPError
  • Set of error that describe the SAPcpmsLockWipePolicyError

    See more

    Declaration

    Swift

    public enum SAPcpmsLockWipePolicyInternalError : Error
    extension SAPcpmsLockWipePolicyInternalError: SAPError
  • SLSLoginInputPresenterError represents errors thrown by SLSLoginInputPresenter

    See more

    Declaration

    Swift

    public enum SLSLoginInputPresenterError : Error
    extension SLSLoginInputPresenterError: SAPError
  • Enum to handle errors in UserConsentStep

    See more

    Declaration

    Swift

    public enum UserConsentError : Error
    extension UserConsentError: SAPError
  • WelcomeScreen Error enum if demo mode button selected

    See more

    Declaration

    Swift

    public enum WelcomeScreenError : Error
    extension WelcomeScreenError: SAPError
  • Enable customization of activation screen UI components

    See more

    Declaration

    Swift

    public protocol ActivationStepUI
  • Implementers must present appripriately the ViewControllers provided by the onboarding steps Different implementers can present the ViewControllers differently but must be appropriate for the ViewController design of the used steps. For example if a step uses a ViewController designed to use NavigationController the presenter must put the ViewController into a NavigationController

    See more

    Declaration

    Swift

    public protocol FlowPresentationDelegate : AnyObject
  • Implementers must use the presentationDelegate to present their ViewControllers

    See more

    Declaration

    Swift

    public protocol FlowPresentationDelegateClient : AnyObject
  • Implementers must set the text of the presented infoscreen

    See more

    Declaration

    Swift

    public protocol InfoTextSettable
  • Enable customization of ScanConfirmView UI components

    See more

    Declaration

    Swift

    public protocol ScanConfirmViewUI : AnyObject
  • Enable customization of welcome screen UI components

    See more

    Declaration

    Swift

    public protocol WelcomeStepUI : AnyObject