End User Authentication
Learn about authentication methods and JWT generation
Authentication is achieved in the Brand Messenger Legacy iOS SDK using a JSON Web Token (JWT) and a unique User ID.
The JWT consists of a header, payload, and signature. It's generated using your App Key ID and App Key Secret. Both of these are obtained by contacting Khoros Support, if you do not already have them, and should be kept completely hidden from your users.
We recommend reviewing your JWT generation method with your IT department to ensure that you are using the most secure option possible.
Generate the JWT
The following example Swift snippet generates a JWT using an open-source library (JSONWebToken) where:
API_KEY_IDis your API Key IDAPI_KEY_SECRETis your API Key SecretuserIdis the user's ID in your system of record
let someDateTime = Date(timeIntervalSince1970: TIME_IN_MILLISECONDS)
var claims = ClaimSet()
claims.issuedAt = someDateTime
claims["userId"] = userID
claims["scope"] = "appUser"
claims["platform"] = "ios"
claims["givenName"] = loginName
var header = [String: String]()
header["kid"] = API_KEY_ID
header["typ"] = "JWT"
let jwtToken = JWT.encode(
claims: claims,
algorithm: .hs256(API_KEY_SECRET.data(using: .utf8)!),
headers: header)
JSONWebToken is available on Cocoapods and can be installed using the following:
pod 'JSONWebToken'
Using an identity provider (IdP)
Companies that opt to use an IdP should be aware of the general authentication flow and how the login process works for accounts using an IdP for authentication. Here is a quick walkthrough of the flow:
- The user logs into the IdP.
- The IdP returns the
userIdandname - The app calls the company's API
getJWTwithuserIdandname - The API generates the JWT in the server and returns it to the app
- The app logs into Brand Messenger using JWT. Since the JWT includes the
userIdandname, the user can be identified between sessions/devices/etc.
Even with the use of an IdP, it's important that the JWT is generated at the server, rather than the app. This prevents any potential security risks that arise from storing the
API_KEY_SECRETlocally within the app's code.
During JWT token generation, include the following information in your claims:
- 'userId' as the userId from your IdP
- 'scope' as 'appUser'
- 'platform' as 'ios'
givenName' as user'sname`
The header should include:
kidas your API Key IDtypasJWT
The token should be signed with the HS256 algorithm using UTF-8 encoding of your API Key Secret.
End User Login
Finally, the login process completes with userID and JWT token.
BrandMessenger.login(userID, jwt: jwtToken) { ( error:Error? , userInfo:[AnyHashable : Any]?) in
}
Once successful, Brand Messenger Legacy SDK is ready to communicate.
Reauthentication
The SDK can set a callback delegate for when an API fails due to authentication errors such as an expired JWT token.
Set KBMSettings's authenticationDelegate during SDK initialization. Eg, when initializing in AppDelegate and setting authenticationDelegate to self:
let settings = KBMSettings(integrationId: smoochIntegrationId)
settings.authenticationDelegate = self
BrandMessenger.initWith(settings) { (error: Error?, userInfo: [AnyHashable : Any]?) in }
Implement KBMAuthenticationDelegate in the class, add the onInvalidToken method and fix the authentication. Eg, when setting AppDelegate as delegate:
extension AppDelegate : KBMAuthenticationDelegate {
func onInvalidToken(_ error: Error, handler completionHandler: @escaping KBMAuthenticationCompletionBlock) {
// get a new jwt token and re-login
let jwtString = getJWT()
completionHandler(jwtString)
}
}
Re-authenticating on Conversation screen
During re-authentication, connections and references to the conversation are recreated. Conversation screen displayed via BrandMessenger.show() needs to be recreated and displayed, or reconnected with BrandMessenger.reloadShownConversationViewController after successful re-authentication, if it is on display during re-authentication.
EG:
if let vc = self.presentedViewController {
BrandMessenger.reloadShownConversationViewController(vc)
}
Updated over 1 year ago