Implement SSO for the OpenWeb iOS SDK

Execute SSO

There are two types of SSO available: Generic SSO and SSO with JWT secret. Please contact your OpenWeb PSMPSM - Partner Success Manager to pick the best option for you.

For more information about SSO authentication, read Implement single sign on.


Generic SSO

  1. Authenticate a user with your backend.
  2. Call startSSO function and get codeA.
  3. Send the codeA and all needed information to your backend system in order to get codeB.
  4. Call completeSSO with the codeB.
  5. Check success and error properties in the callback to ensure everything is okay.
// 1
func login(username: String, password: String) {
    MyAuthenticationProvider.login(
        with: username,
        password: password) { success, error in
            if let error = error {
                handleLoginError()
            } else {
                self.authenticateWithSpotIm()
            }
        }
}
func authenticateWithSpotIm() {
    // 2
    SpotIm.startSSO { [weak self] response, error in
        if let error = error {
            print(error)
        } else {
            self?.getCodeB(codeA: response?.codeA)
        }
    }
}
private func getCodeB(codeA: String?, jwtToken: String?) {
    // 3
    MyAuthenticationProvider.getCodeB(
        with: codeA,
        // Some identification that this user is authenticated to your backend system
        accessTokenNetwork: myUserToken) { [weak self] codeB, error in
            if let error = error {
                print(error)
            } else {
                self.completeSSOWithSpotIm(genericToken: genericToken)
            }
    }
}
private func completeSSOWithSpotIm(codeB: String?, jwtToken: String?) {
    // 4
    SpotIm.completeSSO(with: codeB) { [weak self] success, error in
        // 5
        if let error = error {
            print(error)
        } else if success {
            print(“Authenticated successfully!”)
        }   
    }
}


SSO with JWT secret

  1. Authenticate a user with your backend
  2. Call sso(withJWTSecret) function with a user JWT secret.

If there is no error in the callback and response?.success is true, the authentication process finished successfully.

func authenticate(withJWTSecret: secret) {
    SpotIm.sso(withJwtSecret: secret, completion: { (response, error) in
        if let error = error {
            print(error)
        } else if let success = response?.success, success {
            print(“Authenticated successfully!”)
        }
    })
}


Supporting signup/login flow

To support instantiating signup/login flow from the Spot.IM SDK UI, you can
provide SpotImLoginDelegate when instantiating the SpotImSDKFlowCoordinator.

Only one method in SpotImLoginDelegate will be called, depending on how you decide to present the Conversation (via presentFullConversationViewController() or not).

Also please note, calling the startLoginFlow delegate method should show some UI that will:

  1. Let the user signup/login into the app
  2. Upon successful login will do the full SSO flow using the Spot.IM SDK API, to make sure the user is logged in to the Spot.IM commenting system as well.
extension ArticleViewController: SpotImLoginDelegate {
    func startLoginFlow() {
        // Show your login flow here, pop the login/signup UI once the flow is done and SSO is completed. Not required if only using coordinator.presentFullConversationViewController API
    }
    func presentControllerForSSOFlow(with spotNavController: UIViewController) {
        //present your login flow here, dismiss the the login/signup UI once the flow is done and SSO is completed. Only required when using coordinator.presentFullConversationViewController API
    }
}


Display login prompt in full conversation

To add a customized login prompt above the full Conversation UI, you should implement the following two optional SpotImLoginDelegate methods.

MethodDescription
func shouldDisplayLoginPromptForGuests() -> BoolThis should be overridden and return true.
func customizeLoginPromptTextView(textView: UITextView)This needs to be overridden to set up the TextView for promoting the user login.

The following example shows how to override both of these SpotImLoginDelegate methods.

extension ArticleViewController: SpotImLoginDelegate {
    func startLoginFlow() {
        // Show your login flow here, pop the login/signup UI once the flow is done and SSO is completed. Not required if only using coordinator.presentFullConversationViewController API
    }
    func presentControllerForSSOFlow(with spotNavController: UIViewController) {
        //present your login flow here, dismiss the the login/signup UI once the flow is done and SSO is completed. Only required when using coordinator.presentFullConversationViewController API
    }

    func shouldDisplayLoginPromptForGuests() -> Bool {
        return true
    }

    func customizeLoginPromptTextView(textView: UITextView) {
        var multipleAttributes = [NSAttributedString.Key : Any]()
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .center
    
        multipleAttributes[.underlineStyle] =               NSUnderlineStyle.single.rawValue
        multipleAttributes[.foregroundColor] =      UIColor.red
        multipleAttributes[.font] =                     UIFont.systemFont(ofSize: 18)
        multipleAttributes[.paragraphStyle] =       paragraph

        let attributedString = NSMutableAttributedString(string: "Register or Login to comment.", attributes: multipleAttributes)
        textView.attributedText = attributedString
    }
}


Logout

Call the OpenWeb logout API whenever a user logs out of your system.

func logout(withJWTSecret: secret) {
    SpotIm.logout(completion: { result in
      switch result {
          case .success():
              print("Logout from SpotIm was successful")
          case .failure(let error):
              print(error)
          @unknown default:
              print("Got unknown response")
      }
    })
}


Login status

The OpenWeb login status API enables you to understand the status of the current OpenWeb user.

The status of a current user will be either Guest or LoggedIn.

Login StatusDescription
GuestUnregistered guest user

You should call startSSO / sso("<SECRET_JWT>") if your own login status is 'user is logged in'.
LoggedInRegistered OpenWeb user

You should avoid calling startSSO / sso("<SECRET_JWT>") in this case. If your own status is 'user is logged out', call the OpenWeb logout method.

You can use the following methods to retrieve the status of a user:

  • getUserLoginStatus
  • getUserLoginStatusWithId

Each method is explained in the following sections.


getUserLoginStatus

Retrieve the login status of a current user

func authenticate(withJWTSecret: secret) {
    SpotIm.getUserLoginStatus(completion: { result in
      switch result {
          case .success(let loginStatus):
              print("User is \(loginStatus)")
          case .failure(let error):
              print(error)
          @unknown default:
              print("Got unknown response")
      }
    })
}

getUserLoginStatusWithId

Retrieve the login status of a current user with that user's User ID

When the user is a guest, the userId is nil.

SpotIm.getUserLoginStatusWithId { loginStatus in
      switch loginStatus {
          case .failure(let err):
              print("failure: \(err)")
          case .success((let loginStatus, let userId)):
              print("success: loginStatus: \(loginStatus), userId: \(userId)")
      }
}


Did this page help you?