To initialise the SDK, there are some pre-requisites:
- A configured API space.
- An authentication provider that can generate a JWT that matches the auth scheme configured for your API space.
- The generated JWT must include the provided nonce as a claim.
// create a config object with your api-space-id and an object conforming to CMPAuthenticationDelegate protocol;
CMPComapiConfig *config = [[[[CMPComapiConfig builder]
setApiSpaceID:@"<API_SPACE_ID>"]
setAuthDelegate:<CMPAuthenticationDelegate_Conforming_Object>]
<CMPAuthenticationDelegate_Conforming_Object>build];
CMPComapiClient *client = [CMPComapi initialiseWithConfig:config];
// we can use the client object now
// create a config object with your api-space-id and an object conforming to AuthenticationDelegate protocol;
let config = ComapiConfig.builder()
.setAuthDelegate(<CMPAuthenticationDelegate_Conforming_Object>)
.setApiSpaceID("API_SPACE_ID")
.build()
client = Comapi.initialise(with: config)
guard let client = Comapi.initialise(with: config) else {
// initializing error
return
}
// we can use the client object now
In order to be able to start a session, the config's authenticationDelegate object must conform to the protocol's method:
NSString *id = <Portal's authentication tab ID claim value>;
NSString *issuer = <Portal's authentication tab issuer value>;
NSString *audience = <Portal's authentication tab audience value>;
NSString *secret = <Portal's authentication tab secret value>;
- (void)client:(CMPComapiClient *)client didReceiveAuthenticationChallenge:(CMPAuthenticationChallenge *)challenge completion:(void (^)(NSString * _Nullable))continueWithToken {
// request a JWT token from your provider (backend server)
// example call
[YourProviderServer getTokenForNonce:challenge.nonce id:id issuer:issuer audience:audience secret:secret completion:^(NSString * token, NSError * error) {
// call continueWithToken block with generated token
if (token && !error) {
continueWithToken(token);
}
}];
}
let id: String = <Portal's authentication tab ID claim value>
let issuer: String = <Portal's authentication tab issuer value>
let audience: String = <Portal's authentication tab audience value>
let secret: String = <Portal's authentication tab secret value>
func client(_ client: ComapiClient, didReceive challenge: AuthenticationChallenge, completion continueWithToken: @escaping (String?) -> Void) {
// request a JWT token from your provider (backend server)
// example call
YourProviderServer.getToken(nonce: challenge.nonce, id: id, issuer: issuer, audience: audience, completion: { token: String?, error: Error? in
// call continueWithToken block with generated token
if (token != nil && error == nil) {
continueWithToken(token!);
}
})
}
The JWT token must include claims from the authentication panel in the dashboard. To access, so to Channels > Configure and select Authentication in the App Messaging section.
Here's an example implementation of a token generator in Objective-C and Swift using JWT:
#import "CMPAuthenticationManager.h"
#import <JWT/JWT.h>
@implementation CMPAuthenticationManager
+ (NSString *)generateTokenForNonce:(NSString *)nonce profileID:(NSString *)profileID issuer:(NSString *)issuer audience:(NSString *)audience secret:(NSString *)secret {
NSDate *now = [NSDate date];
NSDate *exp = [NSCalendar.currentCalendar dateByAddingUnit:NSCalendarUnitDay value:30 toDate:now options:0];
NSDictionary *headers = @{@"typ" : @"JWT"};
NSDictionary *payload = @{@"nonce" : nonce,
@"sub" : profileID,
@"iss" : issuer,
@"aud" : audience,
@"iat" : [NSNumber numberWithDouble:now.timeIntervalSince1970],
@"exp" : [NSNumber numberWithDouble:exp.timeIntervalSince1970]};
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
id<JWTAlgorithm> algorithm = [JWTAlgorithmFactory algorithmByName:@"HS256"];
NSString *token = [JWTBuilder encodePayload:payload].headers(headers).secretData(secretData).algorithm(algorithm).encode;
return token;
}
@end
/* Note that this should preferably be generated by your backend, the app should only retreive the token through an HTTP call */
import JWT
class JWTokenGenerator {
struct AuthHeaders {
static let HeaderType = "JWT"
}
static func generate(tokenFor nonce: String, profileId: String, issuer: String, audience: String, secret: String) -> String {
let now = Date()
let exp = Calendar.current.date(byAdding: .day, value: 30, to: now)!
let base64SecretKey = secret.data(using: .utf8)!
let headers = ["typ" : NSString.init(string: AuthHeaders.HeaderType)] as [AnyHashable : Any]
let claims = ["nonce" : NSString.init(string: nonce),
"sub" : NSString.init(string: profileId),
"iss" : NSString.init(string: issuer),
"aud" : NSString.init(string: audience),
"iat" : NSNumber(value: now.timeIntervalSince1970),
"exp" : NSNumber(value: exp.timeIntervalSince1970)] as [AnyHashable : Any]
let algorithm = JWTAlgorithmFactory.algorithm(byName: "HS256")
let e = JWTBuilder.encodePayload(claims)!
let h = e.headers(headers)!
let s = h.secretData(base64SecretKey)!
let b = s.algorithm(algorithm)!
let token = b.encode
return token!
}
}
/* Note that this should preferably be generated by your backend, the app should only retreive the token through an HTTP call */
Learn more about JWTs.
Retrieve the client
The client can be retrieved either as a separate object:
CMPComapiClient *client = [CMPComapi initialiseWithConfig:config];
// client instance ready to use
guard let client = Comapi.initialise(with: config) else {
// initialisation error
return
}
// client instance ready to use
or as a singleton:
[CMPComapi initialiseSharedInstanceWithConfig:config];
CMPComapiClient *client = [Comapi shared];
// shared client ready to use
Comapi.initialiseSharedInstance(with: config)
guard let client = Comapi.shared else {
// initialisation error
return
}
// shared client ready to use