OTPAuthenticator
public class OTPAuthenticator : AppDelegateObserving
OTPAuthenticator
The OTPAuthenticator
component provides two factor authentication by accepting a one-time-pin code from the client.
It is always paired with another type of authentication method.
Note: It is rare for a developer to access the OTPAuthenticator
directly — you typically use the OTPObserver
. Using the authenticator prior to receiving an OTP challenge from a SAPcpms endpoint results in an HTTP 404 response code on the server-side.
OTP is based on session cookies, the OTPAuthenticator
uses a seperate web view to present a login page. The OTP in the SAP CP SDK for iOS supports WKWebView for authentication.
Default web view presenter is provided by the SDK: WKWebViewPresenter
.
Custom web view presenter implementation is also possible with the use of WKWebViewPresenting
protocol.
Important: WKWebView based OTP only works with SAPHTTPCookieStorage
! Make sure you have your SAPURLSession
instance configured with the right HTTP cookie store!
Links:
Setting up an OTPAuthenticator
Using SAPcpms
- Create or obtain the
SAPcpmsSettingsParameters
. - Create
OTPAuthenticator
with the settings parameters. - (recommended) If you want to use the authenticator automatically on requests, then create an
OTPObserver
instance with the authenticator and register it to theSAPURLSession
using theSAPURLSession
‘sfunc register(_ observer: SAPURLSessionObserving )
method.
This sample code demonstrates how to set up the authenticator for custom usage:
let settingsParameters = SAPcpmsSettingsParameters( ... )
let authenticator = OTPAuthenticator(settingsParameters: settingsParameters, webViewPresenter: WKWebViewPresenter())
Using advanced
- Create the
OTPParameters
with the required configuration. - Create
OTPAuthenticator
with the authentication parameters. - (recommended) If you want to use the authenticator automatically on requests, then create an
OTPObserver
instance with the authenticator and register it to theSAPURLSession
using theSAPURLSession
’sfunc register(_ observer: SAPURLSessionObserving )
method.
This sample code demonstrates how to set up the authenticator for custom usage:
let otpParameters = OTPParameters(authorizationEndpointURL: <#your authorizationEndpointURL#>, finishEndpointURL: <#your finishEndpointURL#>)
let authenticator = OTPAuthenticator(otpParameters: otpParameters, webViewPresenter: WKWebViewPresenter()))
// recommended step (3.)
let observer = OTPObserver(authenticator: authenticator)
// obtain urlSession
urlSession.register(observer)
Authorization endpoint URL
The authorizationEndpointURL
is the URL which will be loaded into the web view.
The required behaviour for this URL is to load the login page where the user can enter their credentials (pin code).
Finish endpoint URL
The finishEndpointURL
is the URL which (when encountered in the web view) signals the end of the successful authentication flow.
This means that the mechanism implemented on the authorizationEndpointURL
must make a redirect to the finishEndpointURL
upon successful authentication.
When encountered with this URL in the web view, the web view disappears and the authenticate method’s completionHandler is called.
Usage
Starting the authentication flow
Calling the OTPAuthenticator
’s func authenticate(session:completionHandler:)
method authenticates the user at the given server. If there is an error during the process it is received in the completionHandler. If there is no error (the error property is nil
) then the authentication was successful.
The authenticator displays a web view (using the default or custom-set web view presenter) on top of the view hierarchy on the main queue to show the login page.
authenticator.authenticate(session: session) { error in
if let error = error {
// If there was an error during the authentication process (web view presentation, or network related), it can be handled here.
return
}
// If there was no error (error is `nil`) then the authentication was successful and the following requests to this endpoint should not encounter OTP challenges.
}
Note:
- The first parameter must be an instance of
SAPURLSession
. The authentication process will put the acquired credentials (cookies) into this session’s cookie store. - There can be only one ongoing authentication process, which is guarded internally by the OTPAuthenticator. Simultaneous calls to the authenticate method results in a
OTPError.authenticationInProgress
error which is received in the completionHandler.
Automatic flow (SAPcpms)
When the OTP Form is presented, users have the option to open the SAP Authenticator application by tapping the link presented below the input field. This will open the authenticator application and if it will automatically reopen the host application with the OTP passcode (if configured properly). Using this method requires no user interaction beside the initial tap on the link.
To make your application trusted in the SAP Authenticator, you have to add it under your account. You can add applications via QR code or by entering the following URL in the correct section: your-application-id.xcallbackurl://x-callback-url/setCredential?x-source=com.sap.authenticator&username_paramname=j_username&username_paramvalue=[username]&passcode_paramname=j_passcode&passcode_paramvalue=[passcode]
The SAP Authenticator application will invoke the host application’s AppDelegate’s application(app:open:options:)
method. The application developer must forward the parameters to the OTP component the following way:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return AppDelegateDispatcher.application(app, open: url, options: options)
}
You have to list the following URL Type in your Info.plist file to make possible for the SAP Authenticator to open your application. You can do it in the project settings: (project settings -> Info -> URL Types -> URL Schemes).
URL Type to list: your-application-id.xcallbackurl
In the Info.plist file it should look like this:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>your-application-id.xcallbackurl</string>
<key>CFBundleURLSchemes</key>
<array>
<string>your-application-id.xcallbackurl</string>
</array>
</dict>
</array>
Cancelling an ongoing authentication
You can cancel an ongoing authentication flow. The ongoing authentication receives a OTPError.cancelled
error through the completionHandler and the web view disappears. This method does nothing if there was no ongoing authentication.
authenticator.cancelAuthentication()
Using your own web view presenter implementation
The OTP authentication requires a web view to present the login page. For this the authenticator needs to put a web view on the top of the current view hierarchy.
The authenticator uses the WKWebViewPresenting
protocol to achieve this which is implemented by default (WKWebViewPresenter
).
If there is a custom requirement for presenting and designing a web view then you can use your own implementation of WKWebViewPresenting
:
class MyWebViewPresenter: WKWebViewPresenting {
weak var delegate: WebViewPresenterDelegate?
weak var webViewDelegate: SAPWKNavigationDelegate?
public func presentWebView(completionHandler: @escaping (WKWebView?, Error?) -> Void) {
// TODO:
// - acquire reference to `UIViewController`
// - present the view controller which contains a `WKWebView`
// - pass the `WKWebView` instance to the completionHandler
// - pass an `Error` instance to the completionHandler if there was an error during presentation
}
func dismissWebView() {
// TODO:
// - acquire reference to presented `UIViewController` (or the presenting view controller)
// - dismiss the presented view controller
}
}
let presenter: WKWebViewPresenting = MyWebViewPresenter()
// Use the initializer which accepts custom web view presenters
let authenticator = OTPAuthenticator(otpParameters: <#OTPParameters#>, webViewPresenter: presenter)
From this point forward, the authenticator uses the newly set presenter to load the web view login page.
WKWebView based OTP only works with
SAPHTTPCookieStorage
. Make sure you have yourSAPURLSession
instance configured with it!All calls to the web view presenter inside the authenticator happen on the main thread. You must call the completionHandler of your web view presenter implementation on the main thread!
Important: Be sure you call the completionHandler
with the applicable objects when finished with the presentation.
The OTPAuthenticator
component provides an API to conduct OTP authentication using a web view.
By default the OTPAuthenticator
will present a default ViewController which contains a web view to perform authentication.
This can be replaced by a custom implementation of the WKWebViewPresenting protocol.
## This class is for advanced usage only!
The SDK preferred way of implementing OTP authentication is the use of the OTPObserver
. The direct usage or instantiation of this class is required only when:
- the authentication is not against SAPcpms, therefore a custom authorization endpoint and finish endpoint URL is given
- the authentication and network request has to be handled seperatly
Example of instantiating OTPAuthenticator with custom URLs:
let otpParameters = OTPParameters(authorizationEndpointURL: <#your authorizationEndpointURL#>, finishEndpointURL: <#your finishEndpointURL#>)
let authenticator = OTPAuthenticator(otpParameters: otpParameters)
Example of authenticating with custom OTPAuthenticator:
authenticator.authenticate { error in
if let error = error {
// If there was an error during the authentication process (web view presentation, or network related), it can be handled here.
return
}
// If there was no error (error is `nil`) then the authentication was successful and the following requests to this endpoint should not encounter OTP challenges.
}
-
The external authenticator application’s identifier. This is the
sourceApplication
option in theAppDelegate
‘sapplication(app:open:options)
method.Declaration
Swift
public var externalAuthenticatorApplicationID: String
-
Creates an OTPAuthenticator instance.
Declaration
Swift
convenience public init(otpParameters: OTPParameters, webViewPresenter: WKWebViewPresenting)
Parameters
otpParameters
The necessary parameters to set up OTP authentication. Parameters contain server related information, see
OTPParameters
.webViewPresenter
The
WKWebViewPresenting
instance to be used for presenting the login page. -
Creates an OTPAuthenticator instance based on the SAPcpms settings parameters.
Declaration
Swift
convenience public init(settingsParameters: SAPcpmsSettingsParameters, webViewPresenter: WKWebViewPresenting)
Parameters
settingsParameters
The
SAPcpmsSettingsParameters
instance required to create the authentication parameters for the SAML authenticator. The required parameter is thebackendURL
.webViewPresenter
The
WKWebViewPresenting
instance to be used for presenting the login page.
-
Starts the OTP authentication process. This method will present a web view on the main thread.
Declaration
Swift
public func authenticate(session: SAPURLSession, completionHandler: @escaping (_ error: Error?) -> Void = OTPAuthenticator.defaultCompletionHandler)
Parameters
completionHandler
The completion handler that gets invoked at the end of the authentication process. The default handler will log the error if there was any.
error
The
Error
happened during the process if there was any, otherwisenil
. SeeOTPError
for the list of possible OTP related errors. -
Cancels the ongoing authentication process. The authenticate method’s
completionHandler
will be invoked withOTPError.cancelled
error. Does nothing if there was no ongoing authentication.Declaration
Swift
public func cancelAuthentication()
-
Declaration
Swift
public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool
-
Used in the autonomous OTP flow, this method creates the validation endpoint URL from the URLQueryItems obtained from the external application open URL. It is mapping the following query items: ‘username_paramvalue’, ‘passcode_paramvalue’ to ‘username’, ‘passcode’. The created validation endpoint URL will be loaded into the web view that is presenting the OTP form and waiting for the passcode.
Declaration
Swift
public func validationEndpointURL(from queryItems: [URLQueryItem]) -> URL?
Parameters
queryItems
query items obtained from the external application open URL
Return Value
the validation endpoint URL that will be loaded into the web view
-
The default completion handler for authentication. Logs the error with the root logger if there is any.
Declaration
Swift
public static func defaultCompletionHandler(error: Error?)