SDK end user authentication

The end user authentication process in CCAI Platform is a secure method to identify the user who is using the host application. The end user is identified by a Universally Unique Identifier (UUID) that is provided by the host application. The CCAI Platform SDK requests a JSON Web Token (JWT) signed by the shared secret key (company_secret) and provided by the host application whenever authentication is required. If the host app provides the JWT, the CCAI Platform SDK begins the authentication process and obtains an auth token.

End user

The end user in this context refers to the user of the host application.

To identify the end user, CCAI Platform uses an identifier that is provided by the host app. This identifier should be a Universally Unique Identifier (UUID) that is unique to each individual user.

The use of a UUID helps to ensure that the end user can be accurately identified and differentiated from other users, even if their email address changes.

Authenticate with CCAI Platform

The JSON Web Token (JWT) is used to securely identify a user or an application making a request to CCAI Platform. The host application is responsible for providing the JWT to the CCAI Platform SDK through a callback. The CCAI Platform SDK asks the host application to provide a JWT using the shared SDK key (sdk_key) whenever authentication is needed.

If the host application provided a JWT to the CCAI Platform SDK through the callback, the CCAI Platform SDK starts to authenticate to CCAI Platform and gets the authentication token.

The payload of the JWT might include information such as the user's identifier, email address, name, and phone number. Google Cloud recommends using the E.164 format for phone numbers. This information is used to either create a new account for the user or to associate the user with an existing account on CCAI Platform.

If the host application provides an identifier in the JWT payload, CCAI Platform uses that identifier to create or associate the user with an account. If an identifier is not provided, CCAI Platform creates an anonymous account for the user.

For more information about JWT signing in to CCAI Platform, see JWT Signing section.

Manage SDK Keys

The sdk_key_name and sdk_key are important authentication elements. They serve to uniquely identify your company and are used to securely access the CCAI Platform API.

To retrieve the SDK keys, follow these steps:

  1. Sign in to CCAI Platform portal as a user that has the administrator role.

  2. Go to Settings > Developer Settings > SDK Keys to manage SDK keys, which are used for generating auth tokens.

It is important to keep these codes secure and only share them with authorized individuals or systems that need access to the CCAI Platform API. Unauthorized access to these codes could compromise the security of your data and systems.

Authentication workflow

Here is the authentication workflow:

  1. CCAI Platform provides an SDK Key Name (sdk_key_name) and an SDK Key (sdk_key) to the host application. These can be found in Settings > Developer Settings > SDK Keys.

  2. When the end user starts using CCAI Platform customer service, the CCAI Platform SDK requests JWT signing from the host application.

  3. CCAI Platform verifies the signed JWT and issues an end-user auth token. This process ensures secure and seamless authentication between the host application and CCAI Platform customer service.

JWT signing

The host application needs to implement a callback method for each platform. The following sections provide instructions for each platform.

To handle the end user's information, the host app needs to fill the JWT payload. A default payload is supplied through the callback method and can already contain some values such as the push token and the default name.

The host application can add more information about the user by using reserved key names such as the following:

  • identifier (optional)

  • name (optional)

  • email (optional)

  • phone number (optional, E.164 format)

For example, for the iOS SDK, the method implementation can look like the following for testing purposes (using JWT):

- (void)signPayload:(NSDictionry *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success ailure:(void (^)(NSError *))failure
{
  if (payloadType == UjetPayloadAuthToken) {
    @try {
        NSString *companySecre = @"COMPANY_SECRET";
        NSMutableDictionary *pyloadData = [payload mutableCopy];
        payloadData[@"identifir"] = @"UNIQUE-IDENTIFIER"; // optional
        payloadData[@"name"] =@"user name";            // optional
        payloadData[@"email"]  @"test@email.com";      // optional
        payloadData[@"phone"]  @"";                    // optional, E.164 format 
        payloadData[@"iss"] = "YOUR_COMPANY_NAME";     // optional
        payloadData[@"iat"] = NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]; // required
        payloadData[@"exp"] = NSNumber numberWithDouble:([[NSDate date] timeIntervalSince1970]+ 600)]; // required

        id<JWTAlgorithm> algorthm = [JWTAlgorithmFactory algorithmByName:@"HS256"];
        NSString *signedToken  [JWTBuilder encodePayload:payload].secret(companySecret).algorithm(algorithm).ecode;
        success(signedToken);
    }
    @catch (NSError *error) {
        failure(error);
    }
  }
}

Example for production

Google Cloud recommends signing the payload on the server side for added security. By doing so, the company secret is not exposed on the client side and can be revoked at any time if it is deemed to be at risk. This approach offers greater security compared to signing the payload on the client side.

The following code snippets provide examples for signing the payload on the server side using the Ruby on Rails framework with the JWT gem and on the client side using the iOS SDK, Android SDK, and Web SDK.

On the server side, the code sets up an API endpoint for signing the payload, using the JWT gem to encode the payload with a company secret and return the encoded token to the client.

On the client side, the code provides examples for making a request to the server API from the iOS SDK, Android SDK, and Web SDK to retrieve the signed token.

In the iOS SDK and Android SDK, the code makes an HTTP POST request to the API and retrieves the token from the response. In the Web SDK, the code implements an authentication handler that makes an AJAX request to the API and passes the retrieved token and user information to the CCAI Platform initialize function.

API example on the server

The code in this section is written in Ruby and uses the Rails framework.

Suppose the base URL of your host application is https://company.com/api/. To sign the payload for CCAI Platform, you can add another API endpoint at https://company.com/api/ccaip/sign.

The code adds a new route to the application's routes file to handle POST requests to the /api/ccaip/sign URL.

The ccaip_controller.rb file defines the CCAIPController class, which has a single endpoint called sign. That endpoint is used to sign a payload for CCAI Platform.

In the code, the COMPANY_SECRET is defined as the secret used to sign the payload. The payload is extracted from the body of the request and then various values are added to it, for example, UNIQUE-IDENTIFIER, username, email, and phone.

The JWT.encode method is used to encode the payload and the ccaip_secret into a JSON Web Token (JWT), which is then returned in the response as a JSON object with the token key.

 # routes.rb
post 'ccaip/sign' => "ccaip#sign"

# ccaip_controller.rb
class CCAIPController
  def sign
    ccaip_secret = "COMPANY_SECRET"

    payload = body["payload"]
    payload["identifier"] = "UNIQUE-IDENTIFIER"  # optional
    payload["name"] = "user name"             # optional
    payload["email"] = "test@email.com"       # optional
    payload["phone"] = ""                     # optional, E.164 format
    payload["iss"] = "YOUR_COMPANY_NAME"
    payload["iat"] = Time.now
    payload["exp"] = Time.now.to_i + 10.minutes # valid for only 10 minutes from now.

    token = JWT.encode(payload, ccaip_secret)

    render json: {token: token}
  end
end

Signing from the iOS SDK

The following is an example of signing a payload from the iOS SDK.

It makes a POST request to the server at the URL https://your.company.com/api/ccaip/sign with the payload as the request body. The server is expected to return a signed token in response, which is then passed to the success callback in the form of the "token" key in a JSON object. If there is an error during the request, it is passed to the failure callback.

- (void)signPayload:(NSDictionary *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure
{
  if (payloadType == UjetPayloadAuthToken) {
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];

    NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] init];
    mutableRequest.URL = [NSURL URLWithString:@"https://your.company.com/api/ccaip/sign"];
    mutableRequest.HTTPMethod = @"POST";
    NSError *error;
    NSDictionary *data = @{@"payload": payload};
    mutableRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:data options:0 error:&error];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:mutableRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if(error) {
            failure(error);
        }
        else {
            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            success(json[@"token"]);
        }
    }];

    [task resume];
  }
}

Signing from the Android SDK

The following is an example of signing a payload from an Android SDK.

It is an implementation of an Android SDK function for signing a payload using Retrofit, an HTTP client for Android. The function takes a payload, a payload type, and a token callback as input. If the payload type is UjetPayloadType.AuthToken, it creates a Retrofit instance and uses it to make a request to the https://company.com/api API endpoint to sign the payload. It returns the signed token in the onToken method of the tokenCallback instance. In case of failure, it displays a toast message "Authentication failed".

public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, final UjetTokenCallback tokenCallback) {
        if (ujetPayloadType == UjetPayloadType.AuthToken) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("https://company.com/api")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            AuthService authService = retrofit.create(AuthService.class);
            Call<AuthToken> authenticate = authService.authenticate(new AuthRequest(payload));
            authenticate.enqueue(new Callback<AuthToken>() {
                @Override
                public void onResponse(Call<AuthToken> call, Response<AuthToken> response) {
                    if (response.isSuccessful()) {
                        AuthToken authToken = response.body();
                        tokenCallback.onToken(authToken.getToken());

                    } else {
                        Toast.makeText(ExampleApplication.this, "Authentication failed", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<AuthToken> call, Throwable t) {
                    Toast.makeText(ExampleApplication.this, "Authentication failed", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

Signing from the Web SDK

The following example demonstrates how to sign the payload in the Web SDK by making an API request to the server with the payload.

The server should be set up to handle the API request and sign the payload using a secure method. The result is then returned to the web page, which passes the signed token back to CCAI Platform using the callback function.

$(function() {
  UJET.initialize({
    ... // other parameters
    handlers: {
      authentication(callback) {
        // YOU SHOULD HAVE THIS KIND OF API ON YOUR SERVER
        $.ajax({
          type: 'POST',
          url: 'http://company.com/api/ccaip/sign',
          data: JSON.stringify({
            payload: {
              identifier: 'UNIQUE-Identifier',
              name: 'Test user'
            }
          }),
          success: function(result) {
            // YOU SHOULD CALL `callback` FUNCTION TO RESPONSE THE AUTHENTICATION REQUEST
            callback({
              token: result.token,
              user: {
                identifier: 'UNIQUE-IDENTIFIER',
                name: 'Test user'
              }
            });
          }
        });
      }
    }
  }).then(function() {
    // successfully initialized
  }).catch(function(error) {
    // HANDLE INITIALIZATION ERROR
    // you can handle an error occurred during initialization
  });
});

Auth token exchanging

In CCAI Platform, the host application uses JWT (JSON Web Token) to sign the end user's authentication token, which is then exchanged for an end user auth token. JWT is an open standard for securely transmitting information as a JSON object.

The end user auth token is used to access the CCAI Platform API. This mechanism helps to secure the authentication process and ensure that only authorized users have access to the API.