Single Sign-on for iOS

Enable your registered users to access members-only functionalities using your app's existing user management system.


There are two types of SSO available: Standard and third-party single sign-on. Please contact your OpenWeb PSM if you are unsure which implementation method applies to you.



Implementation Options

Standard

  1. Authenticate a user with your backend user management system.
func login(username: String, password: String) { [weak self] in
    guard let self = self else { return }                                            
    MyAuthenticationProvider.login(
        with: username,
        password: password) { [weak self] result in
            guard let self = self else { return }                   
            switch result {                   
                case .success(_):
                    self.authenticateWithSpotIm()
                case .failure(let error):
                    handleLoginError()
            }
    }
}

  1. Call startSSO function and get codeA.
func authenticateWithSpotIm() {
    SpotIm.startSSO { [weak self] result in
        guard let self = self else { return }   
        switch result {
            case .success(let ssoResponse):
                guard let codeA = ssoResponse.codeA else {
                    //Handle error
                    return
                }
                self.getCodeB(codeA: response?.codeA)
            case .failure(let error):
                //Handle error
                break
        }
    }
}

  1. Send the codeA and all needed information to your backend system to get codeB:

    • From your backend system, make a GET /sso/v1/register-user call to OpenWeb. The API call must include your secret access token (access_token), the session ID generated after initiating the SSO session (codeA), and required user details from your backend user management system (primary_key, user_name). Each of these parameters is defined in Add user information.

    • From your native app, make a call to the backend endpoint of the same backend system that made the GET /sso/v1/register-user call.
GET https://www.spot.im/api/sso/v1/register-user?code_a={CODE_A}&access_token={ACCESS_TOKEN}&primary_key={PRIMARY_KEY}&user_name={USER_NAME}
private func getCodeB(codeA: String) {
    MyAuthenticationProvider.getCodeB(with: codeA,
        // Some identification that this user is authenticated to your backend system
        ...) { [weak self] result in
            guard let self = self else { return }                                
                switch result {                   
                    case .success(let codeB):
                        self.completeSSOWithSpotIm(codeB: codeB)
                    case .failure(let error):
                        handleError()
                }
        }
}

  1. Call completeSSO with the codeB.
private func completeSSOWithSpotIm(codeB: String) {
    SpotIm.completeSSO(with: codeB) { [weak self] result in
        guard let self = self else { return }                              
        switch result {
            case .success(let userId):
                // You can save the userId in case you support multiple users logged in at the same time in the application side
                // Later on this userId can be checked with `SpotIm.getUserLoginStatus` function
                 break
            case .failure(let error):
                self.handleLoginError()
        }                             
    }
}


Third-party single sign-on

  1. Authenticate a user with your third-party user management vendor.
  2. Call the ssoWithJwt(JWT) function with a user JWT secret.
func authenticate(secret: String) {
    SpotIm.sso(withJwtSecret: secret) { result in
        switch result {
            case .success(let ssoResponse):
                guard ssoResponse.success else {
                    // Handle error
                    return
                }
                // Authenticated successfully
            case .failure(let error):
                // Handle error
                break
        }
    }
}


Supporting signup/login flow

You can support instantiating a signup/login flow from the OpenWeb SDK UI by providing SpotImLoginDelegate when instantiating the SpotImSDKFlowCoordinator.

extension ArticleViewController: SpotImLoginDelegate {
	func startLoginUIFlow(navigationController: UINavigationController) {
		// Show your login UI flow here, you can either `push` or `present` it
		// Once the flow is done and SSO is completed we will dismiss the whole navigation stack
		// You can still dismiss your UI at the end, but we will do it regardless  
	}
  
	func renewSSOAuthentication(userId: String) {
		// Renew SSO - Basically silent SSO again to keep the user connected
		// This function will be called once a token is no longer valid and a user was connected from before
		// Follow the above steps to renew the SSO
	}
}

When the startLoginUIFlow delegate method is called, a UI should appear that allows the user to sign up or log in to the app. Upon successful login, the full SSO flow is performed using the OpenWeb SDK API. This process ensures that the user is logged in to the OpenWeb commenting system as well.

When the renewSSOAuthentication delegate function is called, a silent SSO flow is performed. This re-authentication ensures the user remains logged in. This function is called in two primary situations:

  • An authentication token has expired.
  • An authentication error occurred, and a user was previously logged in.

The userId field tracks which user was previously logged in. This tracking enables multiple logged-in users in the application using the SDK.



Display login prompt in full conversation

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

To customize the login prompt see the section of Custom UI.

FunctionDescription
func shouldDisplayLoginPromptForGuests() -> BoolThis should be overridden and return true.

The following example shows how to override this function in SpotImLoginDelegate.

extension ArticleViewController: SpotImLoginDelegate {
	func shouldDisplayLoginPromptForGuests() -> Bool {
		return true
	}
}


Logout

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

func logoutFromSpotIM() {
    SpotIm.logout { result in
        switch result {
            case .success(_):
                // "Logout from SpotIm was successful"
                break
            case .failure(let error):
                // Handle error
                break
        }
    }
}


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 ssoLoggedIn(userId: String).

Login StatusDescription
guestUnregistered guest user
ssoLoggedIn(userId: String)Registered OpenWeb user

getUserLoginStatus

Retrieve the login status of the current user.

func findUserLoginStatus() {
	SpotIm.getUserLoginStatus { result in
		switch result {
			case .success(let loginStatus):
				// You may login or do something after that
				break
			case .failure(let error):
				// Handle error
				break
		}
	}
}