Authentication and Authorization in iOS

Learn more about authentication in our Brand Messenger iOS SDK

Authentication

Prior to sending the first message, the user requires authentication. This is a two-step process.

First, initialize the SDK with the Company Key and App ID as shown below. Contact Khoros Support for your Company Key and App ID if you do not have them.

Even before initializing the SDK, there are a few URLs that can be set by the user. For example:

KBMUserDefaultsHandler.setBASEURL("your-base-url")
KBMUserDefaultsHandler.setCustomAuthHandlerUrl("your-auth-handler")
[KBMUserDefaultsHandler setBASEURL:@"your-base-url"];
[KBMUserDefaultsHandler setCustomAuthHandlerUrl:@"your-auth-handler-url"];

These URLs are region based. A list of URLs depending on regions is listed below:

For US region ->
Base URL: brandmessenger.usw2.khoros.com
Auth-handler URL: messaging-auth.usw2.khoros.com

For Europe region ->
Base URL: brandmessenger.euw1.khoros.com
Auth-handler URL: messaging-auth.euw1.khoros.com

For APAC region ->
Base URL: brandmessenger.apse2.khoros.com
Auth-handler URL: messaging-auth.apse2.khoros.com

The SDK will authenticate with Khoros Auth Handler endpoint during login. Depending on the region, the customer can optionally set the region. Options are KBM_REGION_US, KBM_REGION_EU or KBM_REGION_APAC. Default is KBM_REGION_APAC when not set.

BrandMessengerManager.setRegion(KBM_REGION_US);
[BrandMessengerManager setRegion:KBM_REGION_US];

Then, initialize the SDK with one of the two methods below:

BrandMessengerManager(companyKey: company-key, applicationKey: application-key)

// Or if you do not have the application key or want to use widget configuration in the SDK

BrandMessengerManager(companyKey: company-key, applicationKey: nil, widgetId: widget-id, completion: { response, error in
  if error != nil {
   //init success
  }
   //do something with error 
  })
@import BrandMessengerUI

// Call it only once in your app.
    [[BrandMessengerManager alloc] initWithCompanyKey:@"<COMPANY KEY>" applicationKey:@"<APP ID>"];// Replace this with your Company Key and App ID

// Or if you do not have the application key or want to use widget configuration in the SDK
[[BrandMessengerManager alloc] initWithCompanyKey:@"<COMPANY KEY>" applicationKey:nil widgetId:@"<WIDGET ID>" completion:^(BOOL response, NSError * _Nullable error) {
        if (error != nil) {
            //init success
        }
        // do something with error
    }];

Next, register the user following the example below.
The SDK provides several options for logging in depending on how the integration to the customer login portal has been set up.

Using IDP access token.

BrandMessengerManager.login("accessToken") { response, error in

     if let err = error {
          print("BrandMessenger login failed with an error: ", err.localizedDescription)
          return
     }
     
     print("BrandMessenger login successful")
}
[BrandMessengerManager login:@"accessToken" completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) {
        
    if (error != nil) {
        NSLog(@"BrandMessenger login failed with an error: %@", error.localizedDescription);
        return;
    }
        
    NSLog(@"BrandMessenger login successful");
}];

Using JWT token

To generate the jwt-token, customer can request the API_KEY_ID and API_KEY_SECRET from Khoros support. As this requires API_KEY_SECRET, this should be implemented on a server and not within the mobile application itself. The app then should make an API call to fetch the generated jwt-token to use for login.

You can find resources to assist you in generating the token server-side at JWT.io.

Once the token is generated, it can then be used for login:

let jwt = "jwt-token" // 
let userId = "userId"
BrandMessengerManager.loginWithJWT(jwt, userId: userId) { response, error in }
[BrandMessengerManager loginWithJWT:@"jwt" userId:@"userId" completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) {
   if (error != nil) {
     //login success
   }
}];

Logging in as an anonymous user

For some business requirements, users may need access to chat before logging in to the customer's application. The SDK provides anonymous user login, and merging them to authenticated users later on in the flow.

if BrandMessengerManager.isAnonymousUserExpired() { // check if there is a current anonymous user
    BrandMessengerManager.loginAnonymousUser { response, error in  } // login as anonymous user
}
...
/* Logging in to authenticated access-token user from anonymous user */
BrandMessengerManager.login("accessToken") { response, error in } // login as normal and anonymous user's chat history will be merged to the authenticated account.
// or
BrandMessengerManager.login("accessToken", mergeConversations: false) { response, error in } // Customer can opt to not merge chat history from anonymous user into authenticated account.

/* Logging in to authenticated jwt-token user from anonymous user */
BrandMessengerManager.loginWithJWT("jwt", userId: "userId") { response, error in } // login as normal and anonymous user's chat history will be merged to the authenticated account.
// or
BrandMessengerManager.loginWithJWT("jwt", userId: "userId", mergeConversations: false) { response, error in } // Customer can opt to not merge chat history from anonymous user into authenticated account.
if ([BrandMessengerManager isAnonymousUserExpired]){ // check if there is a current anonymous user
  [BrandMessengerManager loginAnonymousUserWithCompletion:^(KBMRegistrationResponse * _Nullable response, 
   NSError * _Nullable error) { // login as anonymous user
            
  }];
}

/* Logging in to authenticated access-token user from anonymous user */
[BrandMessengerManager login:@"accessToken" completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) {
        
}];
// or
 [BrandMessengerManager login:@"accessToken" mergeConversations:false completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) { // Customer can opt to not merge chat history from anonymous user into authenticated account.
        
}];

/* Logging in to authenticated jwt-token user from anonymous user */
[BrandMessengerManager loginWithJWT:@"jwt" userId:@"userId" completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) {  // login as normal and anonymous user's chat history will be merged to the authenticated account.
        if (error != nil) {
            //login success
        }
       }]; 
// or
[BrandMessengerManager loginWithJWT:@"jwt" userId:@"userId" mergeConversations:false completion:^(KBMRegistrationResponse * _Nullable response, NSError * _Nullable error) { // Customer can opt to not merge chat history from anonymous user into authenticated account.
        if (error != nil) {
            //login success
        }
    }];

The logged-in user can then open a conversation with an agent.

[BrandMessengerManager show:viewController];
// or
[BrandMessengerManager show:nil];
BrandMessengerManager.show(viewController)
// or
BrandMessengerManager.show()

This will present the conversation screen from the supplied viewController, or if not provided, will look for the top view controller and present from there.

Verifying that a user is connected

To check if the user is still authenticated. This will check if JWT is valid, and attempt to refresh JWT if it's expired. If KBMAuthenticationDelegate is set, it will call delegate on refresh to fail.

[BrandMessengerManager.isAuthenticated { response in
    if (response) {
        // user is authenticated
    }
}];
[BrandMessengerManager isAuthenticatedWithCompletion:^(BOOL authenticated){
  if (authenticated) {
        // user is authenticated
    }
}];

To set the user attributes, see Set User Attributes in iOS.

Authentication Delegate

When the auth token expires and SDK's refresh/token API fails, the sdk offers a way to re-establish login auth during operation via a delegate object. Access-token login and jwt-login have separate authentication delegates.

// For access-token login implemention
BrandMessengerManager.setAuthenticationDelegate(self)
...
func onRefreshFail(_completion: @escaping (String) -> Void){
completion(<access_token>)
}
[BrandMessengerManager setAuthenticationDelegate:self];
...
- (void)onRefreshFail:(void (^)(NSString * _Nonnull))completion {
    completion("accesstoken")
}
// For jwt-token login implemention
BrandMessengerManager.setJWTAuthenticationDelegate(self)
...
func onRefreshFail(jwt completion: @escaping (String, String) -> Void) {
    // generate new jwt
    completion("jwt", "userId")
}
[BrandMessengerManager setJWTAuthenticationDelegate:self];
...
- (void)onRefreshFailWithJWT:(void (^)(NSString * _Nonnull, NSString * _Nonnull))completion {
    completion("jwt","userId");
}

Get the userId of a currently logged-in BrandMessenger user

Use the below setting to get the currently logged-in user's userId in Brand Messenger.

[KBMUserDefaultsHandler getUserId];
KBMUserDefaultsHandler.getUserId()

Auth flow using Customer's iDP