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
- Authenticate a user with your backend.
- Call
startSSO
function and getcodeA
. - Send the
codeA
and all needed information to your backend system in order to getcodeB
. - Call
completeSSO
with thecodeB
. - Check
success
anderror
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
- Authenticate a user with your backend
- 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:
- Let the user signup/login into the app
- 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.
Method | Description |
---|---|
func shouldDisplayLoginPromptForGuests() -> Bool | This 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 Status | Description |
---|---|
Guest | Unregistered guest user You should call startSSO / sso("<SECRET_JWT>") if your own login status is 'user is logged in'. |
LoggedIn | Registered 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)")
}
}
Updated 11 months ago