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:
Other useful topics:
- Predefined
OnboardingStep
s in the SDK - About cookies and web based authentications
- Modes of running the flows directly
- Presenting screens
- Running the flow: an example
- 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 OnboardingStep
s in the SDK.
You can implement your own OnboardingStep
s, or use OnboardingStep
s 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 thestore
, - an authentication step, which configures the SAPURLSession with the appropriate
observer
andauthenticator
, 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 thestore
.
A general “restoring flow” contains the same steps but starts with the StoreManagerStep
which opens the existing SecureStore:
StoreManagerStep
: opens theSecureStore
,WelcomeScreenStep
reloads the configuration from thestore
,- 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 OnboardingStep
s in the SDK
Steps can be grouped based on their functionality:
Loading configuration and settings: Gather configuration/settings which are used later by other steps or the application itself. The default set of steps can be retrieved using
SAPcpmsDefaultSteps.settingsDownload
and run by aCompositeStep
instance- WelcomeScreenStep provides the base configuration for the application (which endpoint should be used, etc). It gets and saves the configuration during ‘onboard’ and loads it during ‘restore’.
- SAPcpmsSettingsDownloadStep downloads settings configured in the
SAP Mobile Services
. The settings can be automatically applied by theapply steps
- SAPcpmsDestinationsDownloadStep
- SAPcpmsClientResourcesDownloadStep
Configuration steps: configures the Onboarding (usually an
SAPURLSession
). The default set of steps can be received usingSAPcpmsDefaultSteps.configuration
and run by aCompositeStep
instanceSettings Apply steps: apply the settings found in the
OnboardingContext
. The settings can come from a download step or configured by the application developer. The default set of steps can be received usingSAPcpmsDefaultSteps
.applyDuringOnboard
or.applyDuringRestore
and run by aCompositeStep
instanceAuthentication steps: Configure an
SAPURLSession
(networking component of the SDK) with the given authentication mode, and also validate the connection to the authentication endpoint:Store management steps: Creates and controls the persistent secure storage:
- StoreManagerStep the type of the store and other specific parameters can be configured.
Others:
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 OnboardingStep
s:
Automatic mode (recommended way): a convenient way to run an onboarding flow. Use the
OnboardingFlowController
andOnboardingContext
so that theflow
and data transfer ofsteps
is managed automatically in a convenient and simple-to-implement way. In this case thestep
must implement theOnboardingStep
protocol. For more information please refer to the Automatic flow management Other classes to support this mode:- OnboardingStep protocol
- OnboardingContext struct
- OnboardingFlowController class
- OnboardingResult enum
- OnboardingError enum
Manual mode: Use the
steps
and manage the data transfer andflow
manually. As a naming convention, all steps should declare theonboard
,restore
,reset
methods (similarly toOnboardingStep
), with the list of parameters that the step needs for its operation to complete successfully.
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.
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.The application starts with
InfoViewController
as a root view controller: this can be set as a splash screen to theModalUIViewControllerPresenter
(when it is used asPresentationDelegate
- 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.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 theFlowPresentationDelegate
. 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 callingdismiss
on thePresentationDelegate
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 OnboardingStep
s. 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.
See more// 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 }
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.
See more// 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 }
Declaration
Swift
open class CompositeStep : OnboardingStep
-
Manages the End User License Agreement (EULA) handling. The EULA version will be stored in the
credentialStore
of theOnboardingContext
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
See morelet 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)
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:
See moresapURLSession.register(LanguageObserver())
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.
See morefunc 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 }
Declaration
Swift
open class OAuth2AuthenticationStep : OnboardingStep
-
OnboardingStep Represents a step in the onboarding/restoring flow.
See moreDeclaration
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.
See morefunc 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 }
Declaration
Swift
open class OTPSessionConfigurationStep : OnboardingStep
-
Instantiates an
OnboardingStep
capable of applying thePasscodePolicy
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:
See morelet storeManager = StoreManager() storeManager.applyNewPolicy(passcodePolicy)
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.
See morefunc 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 }
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.
See more// 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 }
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:
See morelet sapURLSession = <#SAPURLSession#> sapURLSession.register(<#CorrelationObserver#>)
Declaration
Swift
open class SAPcpmsCorrelationConfigurationStep : SimpleTaskStep
-
// Definition of default SAPcpms steps
See moreDeclaration
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.
See more// 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 }
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:
See moreLogger.root.apply(sapcpmsLogSettings: <#SAPcpmsLogSettings#>)
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:
See morelet sapURLSession = <#SAPURLSession#> sapURLSession.register(<#SAPcpmsObserver#>)
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.
See more// 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 }
Declaration
Swift
open class SAPcpmsSettingsDownloadStep : OnboardingStep
-
Class for SAPcpmsUsagePolicy and SAPcpmsSettings onboarding step handling to configure SAPFoundation.UsageBroker Singleton object.
See moreDeclaration
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:
See morelet sapURLSession = <#SAPURLSession#> sapURLSession.register(<#SAPcpmsUserBlockedObserver#>)
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.
See more//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 }
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 moreDeclaration
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.
See more// 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 }
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 theOnboardingContext
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
See more// 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])
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
See more// 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 }
Declaration
Swift
open class WelcomeScreenStep : OnboardingStep, FUIWelcomeControllerDelegate, FUIOnboardingScanViewControllerDelegate
extension WelcomeScreenStep: ConfigurationLoaderDelegate
extension WelcomeScreenStep: ConfigurationPersisting
-
The default implementation for the ASWebAuthenticationSessionPresenting. Presents a ASWebAuthenticationSession on demand, can be configured to show an info screen before the presentation.
See moreDeclaration
Swift
open class FioriASWebAuthenticationSessionPresenter : ASWebAuthenticationSessionPresenting, FlowPresentationDelegateClient
-
Presenter to handle BasicCredentialsViewController presentation
See moreDeclaration
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 moreDeclaration
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 moreDeclaration
Swift
open class FioriWKWebViewPresenter : WKWebViewPresenting, FlowPresentationDelegateClient
extension FioriWKWebViewPresenter: FUIWebViewContainerDelegate
-
This
FlowPresentationDelegate
implementation handles the screen presentation in such a way, that everypresent
call results in a modal presentation on the top-most view controller.Important: This implementation requires that every
See morepresent
call have their owndismiss
call pair. Self dismissing view controllers such asUIAlertController
s are not supported.Declaration
Swift
open class ModalUIViewControllerPresenter : FlowPresentationDelegate
-
See moreSLSLoginInputDelegate
implementation to communicate between the Foundation and the UI implementationDeclaration
Swift
open class SLSLoginInputPresenter : FlowPresentationDelegateClient, SLSLoginInputDelegate, FUIDynamicAuthenticationDelegate
-
The content of the EULA screen. Contains a title and an
See moreNSAttributedString
as the content value.Declaration
Swift
public struct EULAContent
-
Declaration
Swift
extension FUIInfoViewController: InfoTextSettable
-
Declaration
Swift
extension FUIOnboardingScanConfirmView: ScanConfirmViewUI
-
Initializes SAPcpms Settings Password Policy from config file
See moreDeclaration
Swift
public extension FUIPasscodePolicy
-
Declaration
Swift
extension FUIWelcomeScreen: WelcomeStepUI
-
Set of options that determine when to present info screen.
See moreDeclaration
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
See morevar info = [OnboardingInfoKey: Any]() info[.myDeclaredKey] = MyStruct()
Declaration
Swift
public struct OnboardingInfoKey : RawRepresentable, Equatable, Hashable, CustomStringConvertible, CustomDebugStringConvertible
-
The content of User Consent Forms.
See moreDeclaration
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 moreDeclaration
Swift
public struct UserConsentPageContent
-
Enum to handle errors in EULAStep
See moreDeclaration
Swift
public enum EULAError : Error
extension EULAError: SAPError
-
Enum for presentation errors
- failed: presentation failed
- missing: viewcontroller is missing
- cancelled: presentation cancelled
Declaration
Swift
public enum FioriPresenterError : Error
extension FioriPresenterError: SAPError
-
Set of error that could occur in SAPcpmsLockWipePolicyApplyStep
See moreDeclaration
Swift
public enum SAPcpmsLockWipePolicyError : Error
extension SAPcpmsLockWipePolicyError: SAPError
-
Set of error that describe the SAPcpmsLockWipePolicyError
See moreDeclaration
Swift
public enum SAPcpmsLockWipePolicyInternalError : Error
extension SAPcpmsLockWipePolicyInternalError: SAPError
-
See moreSLSLoginInputPresenterError
represents errors thrown by SLSLoginInputPresenterDeclaration
Swift
public enum SLSLoginInputPresenterError : Error
extension SLSLoginInputPresenterError: SAPError
-
Enum to handle errors in UserConsentStep
See moreDeclaration
Swift
public enum UserConsentError : Error
extension UserConsentError: SAPError
-
WelcomeScreen Error enum if demo mode button selected
See moreDeclaration
Swift
public enum WelcomeScreenError : Error
extension WelcomeScreenError: SAPError
-
Enable customization of activation screen UI components
See moreDeclaration
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 moreDeclaration
Swift
public protocol FlowPresentationDelegate : AnyObject
-
Implementers must use the presentationDelegate to present their ViewControllers
See moreDeclaration
Swift
public protocol FlowPresentationDelegateClient : AnyObject
-
Implementers must set the text of the presented infoscreen
See moreDeclaration
Swift
public protocol InfoTextSettable
-
Enable customization of ScanConfirmView UI components
See moreDeclaration
Swift
public protocol ScanConfirmViewUI : AnyObject
-
Enable customization of welcome screen UI components
See moreDeclaration
Swift
public protocol WelcomeStepUI : AnyObject