Authentication

OpenWeb's single sign on (SSO) enables your registered users to participate in members-only conversations without an extra registration. Learn how to implement iOS authentication.

OpenWeb's single sign on (SSO) enables your registered users to participate in members-only conversations without an extra registration. To provide this user experience, your backend user management system must securely inform OpenWeb that a user is actively logged into your site.


SSO Authentication

SSO Handshake Overview

  1. Initiate an OpenWeb SSO session. The OpenWeb SDK generates an SSO session ID (codeA).
  2. Send the SSO session ID to your backend user management system.
  3. Validate that a user is logged into your system. You must ensure that the current user logged into your site will also be the current user in the OpenWeb user session.
  4. From your backend user management system, make a GET /sso/v1/register-user call to OpenWeb's backend. The API call must include the following information:
    • Your secret access token (access_token)
    • Session ID generated after initiating the SSO session (code_a)
    • Required user details from your backend user management system (primary_key, user_name).
      OpenWeb's backend logs in the user and returns a success response (codeB).
  5. Pass codeB to the OpenWeb SDK. Successfully completing this process results in logging in a user.

Implementation

For the Standard Authentication and Third-party Provider SSO approaches, the OWAuthentication protocol is used.

public protocol OWAuthentication {
    func sso(_ flowType: OWSSOFlowType)

    func userStatus(completion: @escaping OWUserAuthenticationStatusCompletion)
    func userStatus() async throws -> OWUserAuthenticationStatus
  
    func logout(completion: @escaping OWDefaultCompletion)
    func logout() async throws
  
    var renewSSO: OWRenewSSOCallback? { get set }
    var shouldDisplayLoginPrompt: Bool { get set }
}

Standard Authentication

Use the following recipe to implement SSO authentication for known users.

💡

If the user is already known and has saved persistence on the publisher's end, the user can be automatically logged into the publisher system and then logged in through the OWAuthentication SSO methods.

Third-party Provider SSO

Use the following recipe to implement third-party provider SSO.




In some scenarios, you may need to trigger a login interface before a user can perform an action, such as posting or replying to a comment.

In these scenarios, the OWUIAuthentication protocol is used.

public protocol OWUIAuthentication {
    var displayAuthenticationFlow: OWAuthenticationFlowCallback? { get set }
}

Actions Requiring Login

Authentication must be completed in the following way:

  1. The app displays the iOS SDK UI.
  2. The unauthenticated user attempts to perform an action that requires login, such as posting, liking, or disliking a comment.
  3. A closure displayAuthenticationFlowClosure under OWUIAuthentication is triggered to present a login UI.
  4. The user logs in using the app credentials.
  5. The backend for the app logs in the user.
  6. The app initiates the steps described above at OWAuthentication protocol for SSO authentication.
  7. Upon successful SSO authentication, the the app closes the login UI which was shown by displayAuthenticationFlowClosure triggering .

Use combination of the following code AND recipe to implement this authentication scenario.

let manager: OWManagerProtocol = OpenWeb.manager

let authenticationUI: OWUIAuthentication = manager.ui.authenticationUI
let displayAuthenticationFlowClosure: OWAuthenticationFlowCallback = { routeringMode, completion in
  // Implement your custom login flow or use a popup for standalone components.
  // After a successful login, initiate and complete the SSO flow.
  // In flow mode, adjust the UI, such as popping up or dismissing the login view from `navController`.
  // Call `completion()` after your UI adjustments. Since the SDK progresses to the next screen once `completion()` 
  // is called, call `completion()` only after fully dismissing the UI or adding a 250ms delay.
	completion()
	// Login prompt other items inside the SDK will be auto-handled and dismissed. 
} 
authenticationUI.displayAuthenticationFlow = displayAuthenticationFlowClosure

Renew SSO

Regardless of the SSO approach used, you must implement OWRenewSSOCallback.

Renewing SSO ensures uninterrupted user connectivity. It is triggered when the existing authenticator for a previously connected user becomes invalid. This process silently re-establishes the user's connection without requiring any direct action.

// Renew SSO
let renewSSOClosure: OWRenewSSOCallback = { userId, completion in
  // Follow the SSO authentication steps.
  // Remember to invoke `completion()` after the renewal process.
  completion()
} 
authentication.renewSSO = renewSSOClosure

Logout

// Logout
let logoutCompletionClosure: OWDefaultCompletion = { result in
    switch result {
      case .success(_):
        // All good
      case .failure(let error):
        // Handle the error / Show appropriate user UI
        break
    }
} 
authentication.logout(completion: logoutCompletionClosure)
do {
    try await authentication.logout()
} catch {
    // Handle the error / Show appropriate user UI
}

User Status

// User status
let userStatusCompletionClosure: OWUserAuthenticationStatusCompletion = {
    switch result {
      case .success(let status):
        switch status {
          case .guest:
            // Handle guest status
            break
          case .ssoLoggedIn(let userId):
            // Handle logged in status
            break
        }
      case .failure(let error):
        // Handle the error / Show appropriate user UI
        break
    }
}
authentication.userStatus(completion: userStatusCompletionClosure)
// User status
do {
    switch try await authentication.userStatus() {
    case .guest:
        // Handle guest status
        break
    case .ssoLoggedIn(let userId):
        // Handle logged in status
        break
    }
} catch {
    // Handle the error / Show appropriate user UI
}

Start or Complete SSO Process

authentication.sso(OWSSOFlowType)
ArgumentDescription
OWSSOFlowType OWSSOFlowTypeDefines the start or completion of the SSO authentication process

See: OWSSOFlowType

Enumerations, Structs and Type Aliases

OWAuthenticationFlowCallback

typealias OWAuthenticationFlowCallback = (
  OWRouteringMode, 
  completion: @escaping OWBasicCompletion
) -> Void
PropertyDescription
completion OWBasicCompletionTermination of the callback

See: OWBasicCompletion
OWRouteringMode OWRouteringModeDetermines the UI navigation strategy

See: OWRouteringMode

OWBasicCompletion

Termination of the callback

typealias OWBasicCompletion = () -> Void

OWDefaultCompletion

Empty completion that returns an error if one occurs

typealias OWDefaultCompletion = (Result<Void, OWError>) -> Void

OWProviderSSOHandler

public typealias OWProviderSSOHandler = (Result<OWSSOProviderModel, OWError>) -> Void
PropertyDescription
OWSSOProviderModel OWSSOProviderModelStruct containing the third-party user ID. The user ID enables the user to be logged into OpenWeb.

OWRenewSSOCallback

typealias OWRenewSSOCallback = (
  userId: String, 
  completion: @escaping OWBasicCompletion
) -> Void
PropertyDescription
completion OWBasicCompletionTermination of the callback. See: OWBasicCompletion
userId StringOpenWeb-provided user ID

OWRouteringMode

PropertyDescription
OWRouteringMode OWRouteringModeUI navigation strategy. Possible Values: .flow(navigationController: UINavigationController) for flow implementation, .none for view implementation

OWSSOCompletionHandler

typealias OWSSOCompletionHandler = (Result<OWSSOCompletionModel, OWError>) -> Void
PropertyDescription
OWSSOCompletionModel OWSSOCompletionModelStruct containing the user ID. The user ID enables the user to be logged into OpenWeb.

OWSSOFlowType

authentication.sso(OWSSOFlowType)
PropertyDescription
OWSSOFlowType OWSSOFlowTypeSingle sign on flow. Possible Values: .start(completion: OWSSOStartHandler), .complete(codeB: String, completion: OWSSOCompletionHandler), .usingProvider(provider: OWSSOProvider, token: String, completion: OWProviderSSOHandler)

OWSSOProvider

PropertyDescription
OWSSOProvider StringThird-party identity management providers for single sign on. Possible Values: .auth0, .foxid, .gigya, .hearst, .janrain, .piano

OWSSOStartHandler

typealias OWSSOStartHandler = (Result<OWSSOStartModel, OWError>) -> Void
PropertyDescription
OWSSOStartModel OWSSOStartModelStruct containing codeA. The codeA string value is the OpenWeb SSO session ID.

OWUserAuthenticationStatus

PropertyDescription
OWUserAuthenticationStatus OWUserAuthenticationStatusAccess status of the user. Possible Values: .guest, .ssoLoggedIn(userId: String)

OWUserAuthenticationStatusCompletion

typealias OWUserAuthenticationStatusCompletion = (Result<OWUserAuthenticationStatus, OWError>) -> Void
PropertyDescription
OWUserAuthenticationStatus OWUserAuthenticationStatusAccess status of the user. See: OWUserAuthenticationStatus

Next Step