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_ID
is your API Key IDAPI_KEY_SECRET
is your API Key SecretuserId
is 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
userId
andname
- The app calls the company's API
getJWT
withuserId
andname
- 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
userId
andname
, 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_SECRET
locally 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's
name`
The header should include:
kid
as your API Key IDtyp
asJWT
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 10 months ago