Back to top

Knox Webhook Notification for Knox E-FOTA

Last updated January 15th, 2024

The following tutorials will help you get started on using the Knox Webhook Notification API for Knox E-FOTA.

Currently, the Knox Webhook Notification API supports the following Knox E-FOTA events:

Event Action Description
KE_DEVICE_BULK_CREATE Bulk upload Allows bulk upload of devices.
KE_DEVICE_BULK_REFRESH Bulk refresh Forces the Knox E-FOTA client app to refresh on multiple devices.
KE_DEVICE_BULK_DELETE Bulk deletion Allows bulk deletion of devices.
KE_CAMPAIGN_DELETE Campaign deletion Deletes an existing Knox E-FOTA campaign.
KE_DEVICE_STATUS_CHANGE Device status change Change in device status (operation or client status).
KE_DEVICE_BULK_LICENSE_UNENROLL Bulk license unenrolling Bulk license unerolling of devices.

Prerequisites

Registration

To successfully make calls to the Knox Guard APIs, register as a developer on developer.samsungknox.com and download the latest Knox SDK.

Authentication

To start using Knox E-FOTA APIs, you need an authentication token. The way to obtain a token depends on whether you are a Knox customer or an EMM provider. For more information, see:

Certificate

Download your Samsung Knox validation certificate. You’ll need this to validate the response you’ll receive from Knox Webhook Notification.

DOWNLOAD CERTIFICATE

Use the Knox Webhook Notification API

Upload devices

This tutorial demonstrates how you can use Knox Webhook Notification to call the Knox E-FOTA upload devices event to bulk upload 10,000 devices, and register the event with Knox Webhook Notification to receive change notifications when the upload is complete.

Step 1: Subscribe an event

  1. Subscribe a particular event to Knox Webhook Notification through the Create Subscription operation — POST /kwn/v1/subscriptions.

  2. Provide a subscription URL — known as a “callback” — that you’ll register to receive asynchronous API operation results once the event is complete.

  3. Register the KE_DEVICE_BULK_CREATE event to asynchronously receive the API operation result on the device upload API operation once it’s complete.

Step 2: Upload a device

Upload the devices. The upload operation makes an API call to the Knox E-FOTA upload devices operation.

Step 3: Handle response message

After Knox E-FOTA finishes executing the requested operation — uploading of 10,000 devices — you’ll receive the following message in the body of the subscribed URL call as the response payload:

{
    "event": "KE_DEVICE_BULK_CREATE",
    "subscriptionId": "63689d7e4ee2721f7b50d2b1",
    "payload": {
        "successCount": 1,
        "failureCount": 1,
        "successfulDevices": [
            {
                "imei": "354721981931820",
                "serialNumber": null,
                "deviceId": null
            }
        ],
        "failedDevices": [
            {
                "imei": "355745090079329",
                "serialNumber": null,
                "error": "This IMEI [355745090079329] already exists for different reseller and customer"
            }
        ]
    }
}

Multiple upload events

You can use the same Knox Webhook Notification subscription with multiple bulk device upload events, as follows:

  • You must set the X-WSM-TXID header when you call the Knox E-FOTA bulk device upload API operation.
  • Once the API operation is complete, Knox E-FOTA will pass the value of X-WSM-TXID to Knox Webhook Notification.
  • Then, Knox Webhook Notification will assign the value of X-WSM-TXID to the X-WSM-TRACEID header when calling the Knox Webhook Notification callback URL.

Note

Currently, you must use the Knox E-FOTA X-WSM-TXID header from the Knox E-FOTA API, and the Knox Webhook Notification X-WSM-TRACEID header.

Verify the response

To verify the Knox Webhook Notification callback response:

  1. Get the String value of HttpRequestPayload

    byte[] inputStreamBytes = StreamUtils.copyToByteArray(request.getInputStream());
    Map jsonBody = objectMapper.readValue(inputStreamBytes, HashMap.class);
    String requestBody = objectMapper.writeValueAsString(jsonBody);
    
  2. Parse the encoded JoseHeader and signature from X-WSM-SIGNATURE

    String[] jwsParts = jwsSignature.split("\\.");
    if (jwsParts.length != 3) {
        // Invalid JWS signature,              
        return new ResponseEntity<>("Invalid JWS signature: X-WSM-SIGNATURE=" + jwsSignature, HttpStatus.BAD_REQUEST);
    }
    
    String encodedHeaders = jwsParts[0];
    String encodedRequestBody =  Base64.getUrlEncoder().encodeToString(requestBody.getBytes(StandardCharsets.UTF_8));
    String signature = jwsParts[2];
    
  3. Prepare the data to verify: DataToVerify = encodedJoseHeader.Base64UrlEncode(HttpRequestPayload)

    String dataToVerify = encodedHeaders + "." + encodedRequestBody;
    
  4. Decode the signature with Base64Url decoder and verify the data above by using SHA256withRSA

    verify(DataToVerify, Base64UrlDecode(Signature))

    byte[] signatureByte = Base64.getUrlDecoder().decode(signature);
    
    Signature rsaSignature = Signature.getInstance("SHA256withRSA");
    
    // Pre-download Samsung certificate and store it locally with your application. Load public key from locallyed stored cert file.
    
    rsaSignature.initVerify(publicKey);  
    rsaSignature.update(dataToVerify.getBytes(StandardCharsets.UTF_8));
    boolean verified = rsaSignature.verify(signatureByte);
    
    if (verified) {
    
    // Process the result
    // DO YOUR BUSINESS LOGIC, returns OK
        return new ResponseEntity<> ("Result is processed successfully", HttpStatus.OK);
    } else {
        return new ResponseEntity<>("Signature validation failed: X-WSM-SIGNATURE=" + jwsSignature, HttpStatus.INTERNAL_SERVER_ERROR);
    }
    

Complete code

public ResponseEntity receiveResult(HttpServletRequest request,
@Valid @NotBlank @RequestHeader(value="X-WSM-SIGNATURE") String jwsSignature,
@Valid @NotBlank @RequestHeader(value="X-WSM-TRACEID") String transId) {
    try {
        // 1. Get the request body
        byte[] inputStreamBytes = StreamUtils.copyToByteArray(request.getInputStream());
        Map jsonBody = objectMapper.readValue(inputStreamBytes, HashMap.class);
        String requestBody = objectMapper.writeValueAsString(jsonBody);

        // 2. Verify the data and signature
        String[] jwsParts = jwsSignature.split("\\.");
        if (jwsParts.length != 3) {
            // Invalid JWS signature
            return new ResponseEntity<>("Invalid JWS signature: X-WSM-SIGNATURE=" + jwsSignature, HttpStatus.BAD_REQUEST);
        }

        String encodedHeaders = jwsParts[0];
        String encodedRequestBody =  Base64.getUrlEncoder().encodeToString(requestBody.getBytes(StandardCharsets.UTF_8));
        String signature = jwsParts[2];

        String dataToVerify = encodedHeaders + "." + encodedRequestBody;
        byte[] signatureByte = Base64.getUrlDecoder().decode(signature);

        Signature rsaSignature = Signature.getInstance("SHA256withRSA");

        // Pre-download Samsung certificate and store it locally with your application. Load public key from locally stored cert file.

        rsaSignature.initVerify(publicKey);  
        rsaSignature.update(dataToVerify.getBytes(StandardCharsets.UTF_8));
        boolean verified = rsaSignature.verify(signatureByte);
        if (verified) {
            // 3. Process the result
            // ADD YOUR BUSINESS LOGIC, return OK
            return new ResponseEntity<> ("Result is processed successfully", HttpStatus.OK);
        } else {
            return new ResponseEntity<>("Signature validation failed: X-WSM-SIGNATURE=" + jwsSignature, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    } catch (Exception e) {
        log.error("receiveResult: failed to verify or parse request body", e);
        return new ResponseEntity<>("Internal error: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

One URL for multiple subscriptions

You can also configure one URL across multiple subscriptions by following the steps mentioned below. However, you must meet the following conditions:

  • No API calls are made to the same event more than once, that is, the events must be unique across all your subscriptions.

  • The number of subscriptions you can create can at most be equal to the number of unique events you can call using Knox Webhook Notification.

Note

As a customer, the maximum number of subscriptions you create should be equal to the number of unique events you can call using Knox Webhook Notification. Check out What’s New for a list of all the events that Knox Webhook Notification currently supports.

For EMMs with multiple customers

Knox Webhook Notification also supports EMMs that will make API calls to the Knox E-FOTA API on behalf of customers. You can make multiple subscriptions either by configuring a separate URL for each subscription or using the same URL across all subscriptions.

One URL per subscription

You can configure one URL while creating a subscription, as follows:

  1. Use companyA to create the subscription using the Knox Webhook Notification Subscription API.
  2. Configure example.com/kwn_result/companyA as the callback URL.
  3. Make a call to one of the supported events using the same callback URL.

Once you successfully complete these steps, the configured URL example.com/kwn_result/companyA will receive the operation result.

Similarly, after repeating all the aforementioned steps for companyB, example.com/kwn_result/companyB will receive the operation result for a different subscription associated with companyB.

Is this page helpful?