Secure your custom App : SFMC Code Resource

Secure your custom App : SFMC Code Resource
Home Page

Secure your custom App : SFMC Code Resource

Building a Custom Endpoint in Marketing Cloud

  1. Access Code Resources: Log in to Marketing Cloud and navigate to the Code Resources section.
  2. Create a New JSON Code Resource: Create a new JSON code resource that will define your custom endpoint. This JSON code resource will contain the necessary configuration, logic, and security measures for handling requests.
  3. Define the Endpoint Configuration: Within the JSON code resource, define the configuration for your custom endpoint, including the URL path, request method, and any other relevant details.
  4. Implement SSJS Logic: Inside the JSON code resource, write SSJS code to handle incoming requests. You can use SSJS functions to access request parameters, headers, and payload data, interact with Marketing Cloud APIs, and perform marketing-related tasks.
  5. Secure the Endpoint: Implement security measures to restrict access to the custom endpoint:
    1. Authentication: Require clients to include an authentication token, API key, or OAuth token in their requests. Validate the provided credentials before allowing access to the endpoint.
    2. IP Whitelisting: Restrict access to the endpoint by whitelisting specific IP addresses or ranges. Only requests originating from the whitelisted IPs will be allowed.
    3. User Authentication: If the endpoint is intended for authenticated users, integrate user authentication mechanisms such as username/password or SSO. Users must authenticate before accessing the endpoint.
    4. Rate Limiting: Implement rate limiting to control the number of requests allowed within a specific time frame to prevent abuse or excessive usage.
  6. Generate JSON Response: After performing the necessary marketing operations, generate a JSON response object to be sent back to the client, including any relevant data or error messages.
  7. Test and Deploy: Test the custom endpoint by accessing the URL associated with the JSON code resource. Verify its functionality and security. Once confident, deploy the code resource to make it accessible in the production environment.

Remember to refer to the Marketing Cloud documentation and SSJS function reference for more detailed examples and information on building custom endpoints using SSJS and JSON code resources, as well as implementing security measures to protect your custom endpoint.

Securing Code Resources for Custom Endpoints

Step 1: Input Validation and Sanitization

Ensure that all input parameters and data received by the endpoint are properly validated and sanitized to prevent common security issues such as SQL injection, cross-site scripting (XSS), and remote code execution. Validate and sanitize user input using appropriate techniques and frameworks specific to your programming language or framework.

Step 2: Authentication

Implement a robust authentication mechanism to verify the identity of users accessing the endpoint. This can involve using username/password combinations, API keys, or tokens like JSON Web Tokens (JWT). Choose an appropriate authentication method based on your application's requirements and use industry best practices for securely storing and transmitting authentication credentials.

Step 3: Authorization

Once the user is authenticated, it's important to implement authorization checks to ensure they have the necessary permissions to access the requested resources. Define roles and permissions for different user types and enforce authorization rules at the endpoint level. This can be done using access control lists (ACLs), role-based access control (RBAC), or other authorization mechanisms provided by your framework or libraries.

Step 4: Protect Sensitive Data

Identify and protect any sensitive data that is being transmitted or stored by the endpoint. Use encryption mechanisms, such as Transport Layer Security (TLS) for secure communication over the network, and encrypt any sensitive data stored in databases or other persistent storage. Follow best practices for key management and ensure that any encryption keys are securely stored and managed.

Step 5: Rate Limiting

Implement rate limiting to prevent abuse or attacks on your endpoint. Limit the number of requests allowed from a particular IP address or user within a certain time frame. This can help protect against brute-force attacks and denial-of-service (DoS) attacks.

Step 6: Logging and Monitoring

Implement logging and monitoring mechanisms to track and monitor the activity on your endpoint. Log important events, errors, and exceptions for auditing purposes and to identify potential security breaches. Monitor system and application logs regularly to detect any suspicious activity and take appropriate action.

Step 7: Regular Updates and Patching

Keep your code resources up to date by regularly applying security patches and updates provided by your programming language, framework, and libraries. Stay informed about any security vulnerabilities or patches related to your dependencies and address them promptly.

Step 8: Security Testing

Perform regular security testing, including vulnerability scanning and penetration testing, to identify any potential security weaknesses in your endpoint. Use automated tools and manual testing techniques to identify vulnerabilities and address them before they can be exploited.

Step 9: Security Best Practices

Follow security best practices throughout the development process. This includes principles like the principle of least privilege, secure coding practices, secure configuration management, and secure deployment practices.

Step 10: Continuous Improvement

Security is an ongoing process, so continuously evaluate and improve the security of your endpoint. Stay updated with the latest security trends, attend security conferences, and engage with the security community to learn about emerging threats and best practices.

Secure Custom Endpoint Guide

Step-by-Step Guide: Secure Custom Endpoint via v2/token in Marketing Cloud

Step 1: Create an Installed Package

Step 2: Generate Client ID and Client Secret

Step 3: Generate a Bearer Token

  1. Construct the authorization URL: The authorization URL should be in the following format:
    https://YOUR_SUBDOMAIN.auth.marketingcloudapis.com/v2/token
  2. Make a POST request to the authorization URL with the following parameters:
    • Content-Type: application/json
    • Request body:
      { "grant_type": "client_credentials", "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET" }
      Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with the actual credentials generated in Step 2.
  3. Parse the response: The response will contain an access token, which is the bearer token you need. Extract the access token from the response.

Step 4: Authorize Access to Custom Endpoint via Code Resource

  1. In your custom endpoint code, implement a mechanism to receive the bearer token as a request header or a request parameter.
  2. For each incoming request, validate the bearer token by comparing it with the one generated in Step 3.
  3. If the token is valid, allow access to the custom endpoint and process the request. Otherwise, return an appropriate error response.

By following these steps, you can secure your custom endpoint in Marketing Cloud using the v2/token authentication method. Make sure to properly store and manage your client ID, client secret, and bearer tokens to maintain security.

Securing Custom Endpoints via SSJS (Server-Side JavaScript)


JavaScript Function: DefineResponse

  
    /**
    This function takes in the accessTokenResult and errorLogDEInit as parameters and returns an object with access token information
    @param {Object} accessTokenResult - The response object containing access token information.
    @param {DataExtension} errorLogDEInit - The Data Extension used to log API exceptions.
    @returns {Object} - An object containing access token, token type, expiration time, and the REST instance URL.
    @throws {Error} - If an exception occurs during execution, it is logged in the errorLogDEInit Data Extension and re-thrown.
    **/
    function DefineResponse(accessTokenResult,errorLogDEInit){
      try{
          // Retrieve access token information from the response object
          var response = accessTokenResult["Response"][0];
          var access_token=Platform.Function.ParseJSON(response).access_token;
          var token_type=Platform.Function.ParseJSON(response).token_type;
          var expires_in=Platform.Function.ParseJSON(response).expires_in;
          var rest_instance_url="https://example.com/shashi";

          // Return the access token information as an object
          return {
            "access_token":access_token,
            "token_type":token_type,
            "expires_in":expires_in,
            "rest_instance_url":rest_instance_url
          };
      }
      catch(ex)
      {
        var APIExceptionDE = DataExtension.Init(errorLogDEInit);
        APIExceptionDE.Rows.Add(
                                  {
                                     Message:ex.message
                                    ,Description:ex.description
                                    ,InnerException:ex.jintException
                                    ,FunctionName:"DefineResponse"
                                  });
         throw ex;
      }
    }
  

Explanation

This JavaScript function named DefineResponse takes in two parameters: accessTokenResult and errorLogDEInit. It is responsible for extracting access token information from the accessTokenResult object and returning an object that contains relevant details.

The function starts with a try-catch block to handle any exceptions that may occur during execution. Inside the try block:

  • The access token information is retrieved from the accessTokenResult object by accessing its Response property. The response variable stores this value.
  • The access token, token type, and expiration time are extracted from the response object using the Platform.Function.ParseJSON() function.
  • A static URL value, rest_instance_url, is assigned.
  • The function constructs an object with the access token information and returns it. The object has properties named access_token, token_type, expires_in, and rest_instance_url.

If an exception occurs during execution, the catch block is executed. It logs the exception details into a Data Extension named errorLogDEInit using the DataExtension.Init() function. Then, it adds a new row to the Data Extension with information about the exception, including the error message, description, inner exception, and the name of the function where the exception occurred. Finally, the catch block re-throws the exception to allow the caller of the function to handle it further if desired.

JavaScript Function: RetrieveAccessToken

              
                /**
                This function retrieves the access token from a Data Extension based on a specific filter condition.
                @param {DataExtension} tokenRequestInit - The Data Extension used to retrieve the access token.
                @returns {Object[]} - An array of objects representing the retrieved data from the Data Extension.
                */
                function RetrieveAccessToken(tokenRequestInit)
                {
                  var requestTokeDE = DataExtension.Init(tokenRequestInit);
                  var filter = {Property:"AppName",SimpleOperator:"equals",Value:"Akamai"};
                  // Retrieve data from the Data Extension based on the filter
                  var data = requestTokeDE.Rows.Retrieve(filter);
                  return data;
                }
              
            

Explanation

This JavaScript function named RetrieveAccessToken takes in one parameter: tokenRequestInit. It retrieves the access token from a Data Extension based on a specific filter condition and returns an array of objects representing the retrieved data.

Inside the function:

  • A new instance of the Data Extension is created using the DataExtension.Init() function. The tokenRequestInit parameter is used to initialize the Data Extension.
  • A filter object is defined with properties: Property (the field to filter on), SimpleOperator (the operator to apply), and Value (the value to filter by).
  • The Retrieve() function is called on the Rows property of the Data Extension instance, passing the filter object as an argument. This function retrieves the data from the Data Extension based on the specified filter.
  • The retrieved data is stored in the data variable.
  • Finally, the function returns the data array.

JavaScript Function: AddAccessToken

              
                /**
                This function adds the access token information to a Data Extension and returns the modified Data Extension.
                @param {Object} accessTokenResult - The response object containing the access token information.
                @param {DataExtension} tokenRequestInit - The Data Extension used to store the access token.
                @param {DataExtension} errorLogDEInit - The Data Extension used to log API exceptions.
                @returns {DataExtension} - The modified Data Extension containing the added access token information.
                @throws {Error} - If an exception occurs during execution, it is logged in the errorLogDEInit Data Extension and re-thrown.
                */
                function AddAccessToken(accessTokenResult,tokenRequestInit,errorLogDEInit)
                {
                  try{
                      var duration=15;// Duration of the access token validity in minutes
                      var currentDate=new Date();
                      var expirationDate=new Date(currentDate.getTime()+duration*60000);//Calculate the expiration date based on the duration
                      var requestTokeDE = DataExtension.Init(tokenRequestInit);
                      var response = accessTokenResult["Response"][0];
                      // Add the access token information to the Data Extension
                      requestTokeDE.Rows.Add(
                                              {
                                                 StatusCode:accessTokenResult["StatusCode"]
                                                ,access_token:Platform.Function.ParseJSON(response).access_token
                                                ,token_type:Platform.Function.ParseJSON(response).token_type
                                                ,expires_in:Platform.Function.ParseJSON(response).expires_in
                                                ,scope:Platform.Function.ParseJSON(response).scope
                                                ,soap_instance_url:Platform.Function.ParseJSON(response).soap_instance_url
                                                ,rest_instance_url:Platform.Function.ParseJSON(response).rest_instance_url
                                                ,AppName:"Akamai"
                                                ,RequestedTime:currentDate
                                                ,ExpirationDate:expirationDate
                                              }
                                              );
                      return requestTokeDE;
                  }
                  catch(ex)
                  {
                      // Log the exception in the errorLogDEInit Data Extension
                    var APIExceptionDE = DataExtension.Init(errorLogDEInit);
                    APIExceptionDE.Rows.Add(
                                              {
                                                 Message:ex.message
                                                ,Description:ex.description
                                                ,InnerException:ex.jintException
                                                ,FunctionName:"AddAccessToken"
                                              });
                     throw ex;
                  }
                }
              
            

Explanation

This JavaScript function named AddAccessToken takes in three parameters: accessTokenResult, tokenRequestInit, and errorLogDEInit. It adds the access token information to a Data Extension and returns the modified Data Extension.

Inside the function:

  • The variable duration represents the duration of the access token's validity in minutes.
  • The current date is obtained using new Date(), and the expiration date is calculated by adding the duration to the current date.
  • A new instance of the Data Extension is created using the DataExtension.Init() function. The tokenRequestInit parameter is used to initialize the Data Extension.
  • The access token information is extracted from the accessTokenResult object, assuming it has a property named Response. The response variable stores this value.
  • The access token information is added to the Data Extension using the Rows.Add() function. The information includes the access token, token type, expiration time, scope, SOAP instance URL, REST instance URL, app name, requested time, and expiration date.
  • Finally, the function returns the modified Data Extension instance, requestTokeDE.

If an exception occurs during execution, the catch block is executed. It logs the exception details into a Data Extension named errorLogDEInit using the DataExtension.Init() function. Then, it adds a new row to the Data Extension with information about the exception, including the error message, description, inner exception, and the name of the function where the exception occurred. Finally, the catch block re-throws the exception to allow the caller of the function to handle it further if desired.

JavaScript Function: UpdateAccessToken

    
      /**
      This function updates the access token information in a Data Extension and returns the modified Data Extension.
      @param {Object} accessTokenResult - The response object containing the updated access token information.
      @param {DataExtension} tokenRequestInit - The Data Extension used to store the access token.
      @returns {DataExtension} - The modified Data Extension containing the updated access token information.
      @throws {Error} - If an exception occurs during execution, it is logged in the "Akamai_Error_Log" Data Extension and re-thrown.
      */
      function UpdateAccessToken(accessTokenResult,tokenRequestInit)
      {
        try{
            var duration=15;// Duration of the access token validity in minutes
            var currentDate=new Date();
            var expirationDate=new Date(currentDate.getTime()+duration*60000); // Calculate the expiration date based on the duration
            var requestTokeDE = DataExtension.Init(tokenRequestInit);
            var response = accessTokenResult["Response"][0];
            // Update the access token information in the Data Extension
            requestTokeDE.Rows.Update(
                                    {
                                       StatusCode:accessTokenResult["StatusCode"]
                                      ,access_token:Platform.Function.ParseJSON(response).access_token
                                      ,token_type:Platform.Function.ParseJSON(response).token_type
                                      ,expires_in:Platform.Function.ParseJSON(response).expires_in
                                      ,scope:Platform.Function.ParseJSON(response).scope
                                      ,soap_instance_url:Platform.Function.ParseJSON(response).soap_instance_url
                                      ,rest_instance_url:Platform.Function.ParseJSON(response).rest_instance_url
                                      ,ExpirationDate:expirationDate
                                      ,RequestedTime:currentDate
                                    }
                                    ,
                                    ["AppName"],["Akamai"]
                                    );
            return requestTokeDE;
        }
        catch(ex)
        {
          // Log the exception in the "Akamai_Error_Log" Data Extension
          var APIExceptionDE = DataExtension.Init("Akamai_Error_Log");
          APIExceptionDE.Rows.Add(
                                    {
                                       Message:ex.message
                                      ,Description:ex.description
                                      ,InnerException:ex.jintException
                                      ,FunctionName:"UpdateAccessToken"
                                    });
           throw ex;
        }
      }
    
  

Explanation

This JavaScript function named UpdateAccessToken takes in two parameters: accessTokenResult and tokenRequestInit. It updates the access token information in a Data Extension and returns the modified Data Extension.

Inside the function:

  • The variable duration represents the duration of the access token's validity in minutes.
  • The current date is obtained using new Date(), and the expiration date is calculated by adding the duration to the current date.
  • A new instance of the Data Extension is created using the DataExtension.Init() function. The tokenRequestInit parameter is used to initialize the Data Extension.
  • The access token information is extracted from the accessTokenResult object, assuming it has a property named Response. The response variable stores this value.
  • The access token information is updated in the Data Extension using the Rows.Update() function. The updated fields include the access token, token type, expiration time, scope, SOAP instance URL, REST instance URL, expiration date, and requested time. The update is performed based on a condition where the "AppName" field equals "Akamai".
  • Finally, the function returns the modified Data Extension instance, requestTokeDE.

If an exception occurs during execution, the catch block is executed. It logs the exception details into a Data Extension named "Akamai_Error_Log" using the DataExtension.Init() function. Then, it adds a new row to the Data Extension with information about the exception, including the error message, description, inner exception, and the name of the function where the exception occurred. Finally, the catch block re-throws the exception to allow the caller of the function to handle it further if desired.

JavaScript Function: ComplexFilter

    
      /**
      This function creates a complex filter object with a left operand, logical operator, and right operand.
      @param {string} leftOperand - The left operand of the complex filter.
      @param {string} simpleOperator - The logical operator used in the complex filter.
      @param {string} rightOperand - The right operand of the complex filter.
      @returns {Object} - A complex filter object containing the left operand, logical operator, and right operand.
      */
      function ComplexFilter(leftOperand, simpleOperator, rightOperand)
      {
        return {
            LeftOperand: leftOperand,
            LogicalOperator: simpleOperator,
            RightOperand: rightOperand
        };
      }
    
  

Explanation

This JavaScript function named ComplexFilter takes in three parameters: leftOperand, simpleOperator, and rightOperand. It creates a complex filter object with a left operand, logical operator, and right operand, and returns this object.

Inside the function:

  • A new object is created with properties named LeftOperand, LogicalOperator, and RightOperand.
  • The leftOperand parameter is assigned to the LeftOperand property of the object.
  • The simpleOperator parameter is assigned to the LogicalOperator property of the object.
  • The rightOperand parameter is assigned to the RightOperand property of the object.
  • Finally, the function returns the complex filter object.

JavaScript Function: SimpleFilter

    
      /**
      This function creates a simple filter object with a property name, simple operator, and property value.
      @param {string} propertyName - The name of the property used in the simple filter.
      @param {string} simpleOperator - The simple operator used in the filter.
      @param {string} propertyValue - The value of the property used in the filter.
      @returns {Object} - A simple filter object containing the property name, simple operator, and property value.
      */
      function SimpleFilter(propertyName, simpleOperator, propertyValue)
      {
        return {
            Property: propertyName,
            SimpleOperator: simpleOperator,
            Value: propertyValue
        };
      }
    
  

Explanation

This JavaScript function named SimpleFilter takes in three parameters: propertyName, simpleOperator, and propertyValue. It creates a simple filter object with a property name, simple operator, and property value, and returns this object.

Inside the function:

  • A new object is created with properties named Property, SimpleOperator, and Value.
  • The propertyName parameter is assigned to the Property property of the object.
  • The simpleOperator parameter is assigned to the SimpleOperator property of the object.
  • The propertyValue parameter is assigned to the Value property of the object.
  • Finally, the function returns the simple filter object.

JavaScript Function: DataExtensionRowsRetrieve

    
      /**
      This function retrieves rows from a Data Extension based on the provided DataExtensionProps.
      @param {Object} dataExtensionProps - An object containing the Data Extension initialization and filter details.
      @param {Object} dataExtensionProps.Init - The initialization properties for the Data Extension.
      @param {Object} dataExtensionProps.filter - The filter criteria used to retrieve the rows.
      @param {DataExtension} errorLogDEInit - The Data Extension used to log API exceptions.
      @returns {Object[]} - An array of objects representing the retrieved rows from the Data Extension.
      @throws {Error} - If an exception occurs during execution, it is logged in the errorLogDEInit Data Extension and re-thrown.
      */
      function DataExtensionRowsRetrieve(dataExtensionProps, errorLogDEInit)
      {
        try {
          var dataExtension = DataExtension.Init(dataExtensionProps.Init);
          var dataSet = dataExtension.Rows.Retrieve(dataExtensionProps.filter);
          return dataSet;
        }
        catch (ex) {
          var APIExceptionDE = DataExtension.Init(errorLogDEInit);
          APIExceptionDE.Rows.Add(
            {
              Message: ex.message,
              Description: ex.description,
              InnerException: ex.jintException,
              FunctionName: "DataExtensionRowsRetrieve"
            });
          throw ex;
        }
      }
    
  

Explanation

This JavaScript function named DataExtensionRowsRetrieve takes in two parameters: dataExtensionProps and errorLogDEInit. It retrieves rows from a Data Extension based on the provided DataExtensionProps and returns an array of objects representing the retrieved rows.

Inside the function:

  • The dataExtensionProps parameter is an object containing the Data Extension initialization and filter details.
  • The dataExtensionProps.Init property is used to initialize the Data Extension instance using the DataExtension.Init() function.
  • The dataExtensionProps.filter property contains the filter criteria used to retrieve the rows.
  • A new instance of the Data Extension is created using the initialized properties.
  • The Retrieve() function is called on the Rows property of the Data Extension instance, passing the filter criteria as an argument. This function retrieves the rows from the Data Extension based on the specified filter.
  • The retrieved rows are stored in the dataSet variable.
  • Finally, the function returns the dataSet array.

If an exception occurs during execution, the catch block is executed. It logs the exception details into a Data Extension named errorLogDEInit using the DataExtension.Init() function. Then, it adds a new row to the Data Extension with information about the exception, including the error message, description, inner exception, and the name of the function where the exception occurred. Finally, the catch block re-throws the exception to allow the caller of the function to handle it further if desired.

JavaScript Function: GetAccessToken

    
      /**
       * This function retrieves the access token based on the provided credentials.
       * @param {Object} credentials - An object containing the authentication credentials.
       * @param {string} credentials.grant_type - The grant type for authentication.
       * @param {string} credentials.client_id - The client ID for authentication.
       * @param {string} credentials.client_secret - The client secret for authentication.
       * @param {DataExtension} errorLogDEInit - The Data Extension used to log API exceptions.
       * @returns {Object} - An object containing the access token and related information.
       * @throws {Error} - If an exception occurs during execution, it is logged in the errorLogDEInit Data Extension and re-thrown.
       */
      function GetAccessToken(credentials, errorLogDEInit) {
    try {
      if (!credentials.grant_type || !credentials.client_id || !credentials.client_secret) {
        return {
          "errorcode": 0,
          "message": "Not Authorized"
        };
      }
  
      var leftOperand = SimpleFilter("ClientID", "equals", credentials.client_id);
      var rightOperand = SimpleFilter("ClientSecret", "equals", credentials.client_secret);
      var filter = ComplexFilter(leftOperand, "AND", rightOperand);
  
      var init = "Akamai_API_Integration";
      var dataExtensionProps = {
        "Init": init,
        "filter": filter
      };
  
      var dataSet = DataExtensionRowsRetrieve(dataExtensionProps, errorLogDEInit);
      if (!dataSet) {
        return {
          "errorcode": 0,
          "message": "Not Authorized"
        };
      }
  
      var memberID = Platform.Recipient.GetAttributeValue('memberid');
      var authAPI = dataSet[0]["AuthAPI"];
      var contentType = "application/json;charset=UTF-8";
      var headers = {
        "client_id": credentials.client_id,
        "client_secret": credentials.client_secret,
        "grant_type": credentials.grant_type,
        "account_id": memberID
      };
      var tokenRequestInit = "TokenRequests";
      var retrieveToken = RetrieveAccessToken(tokenRequestInit);
  
      var accessTokenResult = HTTP.Post(authAPI, contentType, Stringify(headers));
      var response;
      if (retrieveToken) {
        response = UpdateAccessToken(accessTokenResult, tokenRequestInit, errorLogDEInit);
      } else {
        response = AddAccessToken(accessTokenResult, tokenRequestInit, errorLogDEInit);
      }
      
      response = DefineResponse(accessTokenResult, errorLogDEInit);
      return response;
    } catch (ex) {
      var APIExceptionDE = DataExtension.Init(errorLogDEInit);
      APIExceptionDE.Rows.Add({
        Message: ex.message,
        Description: ex.description,
        InnerException: ex.jintException,
        FunctionName: "GetAccessToken"
      });
      throw ex;
    }
  }
    
  

Explanation

This JavaScript function named GetAccessToken takes in two parameters: credentials and errorLogDEInit. It retrieves the access token based on the provided credentials and returns an object containing the access token and related information.

Inside the function:

  • The credentials parameter is an object containing the authentication credentials.
  • The credentials.grant_type, credentials.client_id, and credentials.client_secret properties are used to check if the required authentication credentials are present.
  • If the required authentication credentials are present, a filter is created using the SimpleFilter and ComplexFilter functions to retrieve the authentication credentials from the Data Extension.
  • The init variable is set to the Data Extension name used for retrieving the authentication credentials.
  • A dataExtensionProps object is created with properties Init and filter to pass to the DataExtensionRowsRetrieve function for retrieving the authentication credentials.
  • The DataExtensionRowsRetrieve function is called with the dataExtensionProps object and errorLogDEInit parameter to retrieve the authentication credentials.
  • If the authentication credentials are retrieved successfully, the member ID is obtained from the Platform's recipient attribute.
  • The required headers for authentication are defined.
  • A token request is made by calling either the RetrieveAccessToken or AddAccessToken function based on whether a token is already present.
  • An access token is obtained by making an HTTP POST request to the authAPI URL with the defined headers.
  • The access token information is updated or added to the Data Extension using the UpdateAccessToken or AddAccessToken function.
  • The final access token response is defined using the DefineResponse function.
  • Depending on the flow of the code, the access token response or an error message is returned.
  • If an exception occurs during execution, the catch block is executed. It logs the exception details into a Data Extension named errorLogDEInit using the DataExtension.Init() function. Then, it adds a new row to the Data Extension with information about the exception, including the error message, description, inner exception, and the name of the function where the exception occurred. Finally, the catch block re-throws the exception to allow the caller of the function to handle it further if desired.

Server-Side JavaScript Block

              
                <script runat="server" language="javascript">
                  Platform.Load("core", "1");
                  var response;
                  var errorLogDEInit = "Akamai_Error_Log";
                  
                  /**
                   * This is the main block of code that utilizes the GetAccessToken function.
                   * It retrieves the JSON post data, parses it, and based on the operation specified, calls the appropriate function.
                   * The response is then written as a JSON string.
                   * If an exception occurs, it is logged in the Akamai_Error_Log Data Extension, and the error message is returned as a response.
                   */
                  try {
                    var jsonPost = Platform.Request.GetPostData();
                    var json = Platform.Function.ParseJSON(jsonPost);
              
                    switch (json.operation) {
                      case "RequestToken":
                        response = GetAccessToken(json, errorLogDEInit);
                        break;
                      default:
                        response = { "Error": "Invalid operation specified." };
                    }
                    
                    Write(Stringify(response));
                  } catch (ex) {
                    var APIExceptionDE = DataExtension.Init(errorLogDEInit);
                    APIExceptionDE.Rows.Add({
                      Message: ex.message,
                      Description: ex.description,
                      InnerException: ex.jintException,
                      FunctionName: "Main Block"
                    });
                    
                     response={ "errorcode":500,"message":"Internal Server Error"};
                    Write(Stringify(response));
                  }
                </script>
              
            

Explanation

This code snippet represents a server-side JavaScript block that executes within a server-side context.

Inside the code block:

  • The Platform.Load() function is called to load the Core library version 1.
  • A variable named response is declared to store the response data.
  • The errorLogDEInit variable is set to the name of the Data Extension used to log API exceptions.
  • A try-catch block is used to handle exceptions that may occur during execution.
  • Within the try block:
    • The Platform.Request.GetPostData() function is called to retrieve the JSON data sent in the HTTP POST request.
    • The retrieved JSON data is parsed using the Platform.Function.ParseJSON() function and stored in the json variable.
    • A switch statement is used to perform different actions based on the value of the json.operation property.
    • If the operation property is equal to "RequestToken", the GetAccessToken function is called with the json object and errorLogDEInit parameter, and the result is assigned to the response variable.
    • If the operation property is not recognized, an error response is assigned to the response variable.
    • The response object is serialized into a JSON string using the Stringify() function.
    • The JSON response is written to the output using the Write() function.
  • If an exception occurs within the try block, the catch block is executed:
    • An APIExceptionDE Data Extension object is initialized with the errorLogDEInit parameter.
    • The exception details, including the error message, description, inner exception, and function name, are added as a new row to the APIExceptionDE Data Extension.
    • An error response object is created with the error message.
    • The error response object is serialized into a JSON string using the Stringify() function.
    • The JSON error response is written to the output using the Write() function.


Comments


Knowledge Article

Most Viewed

CLOUD PAGE ENABLEMENT - PART 1

EMAIL NOT SENT IN JOURNEY BUILDER

CONSIDERATIONS FOR JOURNEY BUILDER

Journey Builder REST API Documentation

Preference Center Demystified

Popular Posts

CLOUD PAGE ENABLEMENT - PART 1

EMAIL NOT SENT IN JOURNEY BUILDER

CONSIDERATIONS FOR JOURNEY BUILDER

Journey Builder REST API Documentation

Preference Center Demystified

SEND LOG EANBLEMENT

Share with Friends

Disclaimer:

The information provided on this technical blog is for general informational purposes only. As a SFMC (Salesforce Marketing Cloud) Technical Architect, I strive to offer accurate and up-to-date content related to SFMC and its associated technologies. However, please note that technology is constantly evolving, and the information provided may become outdated or inaccurate over time.

The content published on this blog represents my personal views and experiences as a SFMC Technical Architect and does not necessarily reflect the official views or opinions of any organization or employer I may be affiliated with.

While I make every effort to ensure the accuracy and reliability of the information presented, I cannot guarantee its completeness, suitability, or applicability to your specific circumstances. Therefore, it is essential to verify any information provided and make your own independent assessments or seek professional advice if needed.

Furthermore, any actions taken based on the information provided on this blog are at your own risk. I shall not be held liable for any damages, losses, or inconveniences arising from the use of the information presented here.

Please keep in mind that SFMC and its associated technologies are complex and require technical expertise for proper implementation and management. It is recommended to consult with qualified professionals or official SFMC documentation for comprehensive guidance.

Finally, please note that any product or company names mentioned on this blog are trademarks or registered trademarks of their respective owners. The mention of these trademarks or registered trademarks does not imply any endorsement or affiliation with the blog.

By accessing and using this blog, you agree to the terms of this disclaimer. If you do not agree with any part of this disclaimer, please refrain from using this blog.