OTPObserver

open class OTPObserver

OTPObserver


The use of this component is the SDK-suggested way of implementing OTP authentication in the application. The OTPObserver intercepts requests provided by SAPURLSession and looks for OTP challenge indicating HTTP responses. Upon detecting an OTP challenge, it uses its OTPAuthenticator to authenticate and resend the original request when the authentication is successful. The caller does not notice anything from the authentication flow.

OTP implementation is based on session cookies, so no additional values/tokens need to be stored. The OTP observer must be on the same url session as the other requests sent to the OTP protected server.

Usage

SDK-suggested usage

The SDK-suggested way of using the OTPObserver is to use its convenience initializer which takes a SAPcpms settings parameters as parameter. This is most favorable when the authentication happens against SAPcpms.

Example:

// Create the SAPcpms settings parameter.
let settingsParameters: SAPcpmsSettingsParameters = <#Settings parameter#>

// Create the observer with the suitable initializer
let observer = OTPObserver(settingsParameters: settingsParameters)

// Register the observer to an instance of `SAPURLSession`
sapURLSession.register(observer)

A SAPURLSession is required to register the observer. Be aware that an observer instance can be registered to the same SAPURLSession instance only once! Multiple registration will result in application termination!

Customization

There can be scenarios where the SDK supplied convenience implementation is not sufficient. The SDK supports multiple level of customizations. You can find examples at the Authentication section.

Detecting OTP challenges

SAPcpms signals OTP challenges through HTTP response headers. The default OTP challenge implemented by SAPcpms:

  • HTTP response status code 200
  • Custom header name x-smp-authentication with value otp-challenge

The default OTPObserver looks for these conditions on every received response to determine if there was an OTP challenge.

Overriding the default challenge detection logic

If your landscape signals OTP challenges differently then you need to customize the challenge detection logic. The SDK supports this kind of customization through the sub-classing of OTPObserver and the overriding of the dedicated challenge detection method.

class MyOTPObserver: OTPObserver {
    // Override the default challenge detection method
    override func isChallenge(dataTask: SAPURLSessionTask, response: URLResponse) -> Bool {
        // Determine if the response contains an OTP challenge
        // Return a boolean value accordingly.
        // return true - the repsonse is an OTP challenge and authentication must take place
        // return false - the response is not an OTP challenge, continue normally
    }
}

// Create your observer with one of the available initializers
let myOTPObserver = MyOTPObserver(settingsParameter: <#your SAPcpmsSettingsParameters#>)

// Register the created observer to an instance of the SAPURLSession
sapURLSession.register(myOTPObserver)

Note - regarding the main thread

The observer is aware of the application state, and does not allow to run UI-required authentication in background state. It uses the main thread synchronously to read the UIApplication.shared.applicationState property.

Do not use the main thread to wait (block) for a network request which goes through this observer!

The use of this component is the SDK-suggested way of implementing OTP authentication in the application. The OTPObserver intercepts requests provided by SAPURLSession and looks for OTP challenge indicating HTTP responses. Upon detecting an OTP challenge, it uses its OTPAuthenticator to authenticate and resend the original request when the authentication is successful. The caller does not notice anything from the authentication flow.

Example use:

// create or acquire the SAPURLSession instance
let sapURLSession = SAPURLSession()

// perform other steps to initialize the session and the application

// create the SAPcpms settings parameter
let settingsParameters = SAPcpmsSettingsParameters(backendURL: <#your backendURL#>, applicationID: <#your applicationID#>)

// create the OTP observer
let otpObserver = OTPObserver(settingsParameters: settingsParameters)

// register the observer on the URL session
sapURLSession.register(otpObserver)

// start to create requests

  • Determines the header name which indicates an OTP challenge.

    Declaration

    Swift

    public let challengeHeaderName: String
  • Determines the header value which indicates an OTP challenge.

    Declaration

    Swift

    public let challengeHeaderValue: String
  • Instantiates the observer with the given authenticator.

    Declaration

    Swift

    public init(authenticator: OTPAuthenticator, challengeHeaderName: String = OTPChallengeHeaderName, challengeHeaderValue: String = OTPChallengeHeaderValue)

    Parameters

    authenticator

    the OTPAuthenticator instance to be used when encountered with an authentication challenge

  • Instantiates the observer based on the OTP parameters. The OTP authenticator is implicitly created with the default web view presenter.

    Declaration

    Swift

    public convenience init(authenticationParameters: OTPParameters)

    Parameters

    authenticationParameters

    The OTPParameters instance

  • Instantiates the observer based on the SAPcpms settings parameters. The OTP authenticator is implicitly created with the default web view presenter.

    Declaration

    Swift

    public convenience init(settingsParameters: SAPcpmsSettingsParameters)

    Parameters

    settingsParameters

    The SAPcpmsSettingsParameters instance required to create the authentication parameters for the OTP authenticator. The required parameter is the backendURL.

  • External OTP challenge decision logic. The default behaviour checks for authentication headers in the HTTPURLResponse, naming ‘x-smp-authentication: otp-challenge’. When this header is present, the authentication flow will start, otherwise this observer is skipped. The method can be overriden if custom challenge decision logic is needed. The OTP observer will launch the authentication flow if this method returns True.

    Declaration

    Swift

    open func isChallenge(dataTask: SAPURLSessionTask, response: URLResponse) -> Bool

    Parameters

    dataTask

    the resumed SAPURLSessionTask

    response

    the received URLResponse

    Return Value

    True is the response indicates an OTP challenge, False otherwise