Getting Started > Building a Jive Add-On

Version 40

    What Is a Jive Add-on?

     

    A Jive add-on is an archive file, containing configuration settings and other data, that can be installed into your Jive community. Installing an add-on is a secure way of expanding your Jive community with custom apps, tiles, streams, external storage frameworks, and other Jive extension types. Add-ons can be installed by community managers and are managed from the Jive UI using the “Add-Ons” menu option. For a high-level overview on how Jive add-ons are built and deployed, refer to Jive Add-on Deployment.

     

    Jive add-ons are ZIP files that contain some configuration files and folders. The meta.json and definition.json are the most important files in the package.

    • meta.json - A JSON formatted file with several fields, most of which are optional, but any of which may be appropriate to any type of Jive Add-on. The most important field in here is the "type" field.
    • definition.json - A JSON formatted file with a schema specific to the add-on type. see:
      Building a Jive Add-On - definition.json

     

    This package also contains two folders: data and i18n.

    • /data - Contains files relevant to the Jive Add-on. Most add-ons define icons in the meta.json, and those image files are here. Add-ons may also specify a EULA, and that file is also stored in this folder.
    • /i18n - Add-ons support localization through the use of resource bundles. This directory contains files like en.properties and zh_TW.properties -- Java properties formated resource bundles.

     

    How Do I Use an Add-on to Make REST API Calls Using OAuth?

     

    One common use case for building an add-on is in order to acquire the appropriate tokens to make Jive REST API calls using OAuth 2.0. We've created a special tutorial for this particular scenario: How To Use OAuth 2.0 for REST API Calls

     

    How Do I Build an Add-on?

     

    Once you understand what's in the Jive add-on package, you can begin building an add-on for yourself.

     

    You can get started building an add-on either using the Jive Node SDK (jive-sdk) or the file attached to this document. If you use the Jive Node SDK, an add-on package (named extension.zip) is automatically created for you when you start your application. You can take that zip file and use it as a starting point for the submission. You'll want to edit the meta.json and potentially the definition.json so that you can customize your submission.

     

    To build an add-on by hand, start with the file attached to this document. You should have an idea of the following:

    1. Decide which type of add-on you're building.
    2. Create a meta.json  using the Standard fields in meta.json table.
    3. Create definition.json using Building a Jive Add-On - definition.json.
    4. Upload it to your community using the Jive add-ons interface and select: This service is visible only to me.
    5. Create a secret group and experiment with  your add-on functionality before making it available to everyone.

     

    Using Standard Fields to create the meta.json

     

    Many fields in the meta.json are optional, and a few are required. Optional fields may be omitted according to your own company policies. The fields marked as "Required for GRP" should be completed when an add-on is going to be published in the Add-ons Registry. The following table lists all fields available to the meta.json file.

     

    FieldInclusionTypeDescription
    package_versionRequiredStringAlways "1.0"
    idRequiredString<UUID>A unique identifier for this add-on. Initially, a random UUID is assigned. This value can never changed in future releases of the same Jive Add-on.
    jive_technology_partner_idOptionalString <UUID>

    A GUID assigned to each Technology Partner. This is used by Technology Partners to associate their partner listing on the Jive Web site with the detail contained in this add-on entry. In some cases, this can be self generated manually by the partner. This ID MUST be included in every detailed listing you provided.

    typeRequiredString

    Determines the overall type of this Jive Add-on. This value directly drives where this add-on will be listed in the Jive UI, and which ExtensionAdapter implementation will be invoked to install, update and uninstall this add-on.The valid values are listed below.

    • client-app - Standard Add-On Using Tiles, Apps and Standard Calls
    • jab-cartridges-app - All things from client-app, but includes Cartridges
    • mobile - A client-app where the Client ID/Secret are set externally and stored within the add-on > meta.json
    nameRequiredStringThis value is typically is the i18n key that contains the name of this Jive Add-on. If it is not an i18n key, this value will be shown for all locales. This value cannot exceed 255 characters.
    descriptionRequiredStringThis value is typically is the i18n key that contains the description of this Jive Add-on. If it is not an i18n key, this value will be shown for all locales. This value cannot exceed 255 characters.
    versionRequired for GRP*StringThe version string of this Jive Add-on. This string is used only for presentation purposes and is never used for any type of comparison.
    overviewRequired for GRP*StringThe name of an HTML file in /data that will contain a detailed overview of this Jive Add-on.
    install_instructionsRequired for GRP*StringThe name of an HTML file in /data that will contain a detailed explanation of steps required to install this Jive Add-on. This may not always be needed, but if we are expecting the Jive admin to deploy some kinds of companion network service for this Jive Add-on to work, this really needs to be here.
    minimum_versionRequiredString

    A string used to represent Jive version compatibility. It is zero padded to 10 digits.

     

    • For version 7.0.1 and higher (including cloud), use: 0070100000
    • For version 8.0.0 and higher (including cloud), use: 0080000000
    • For version 9.0.0 and higher (including cloud), use: 0090000000
    • For cloud only, use: C000000000
    minimum_editionOptionalString

    This field is used to indicate which version of Jive your add-on is compatible with. For example, this enables your add-on to be installed for on-prem, but not cloud.

    If the minimum_edition is not present in the meta.json, the add-on is available to all Jive instances that enable the global registry.

    More details are available here: Specifying which edition of Jive an add-on is compatible with

    If you are unsure, please contact your Technology Partner Team.

    eula_filenameOptionalStringThe name of an HTML file in /data that will be presented to the user as a legal agreement before they are permitted to install this Jive Add-on.
    privacy_policyOptionalStringThe name of an HTML file in /data that will be presented to the user explaining the privacy policy concerning any information provided to this Jive Add-on or the network services it communicates with.
    service_urlRequiredString<URL>

    The base url used for making register calls and loading lightweight UI. This value is available with the token %serviceURL% in fields that support it.

    register_urlOptionalString<URL>A URL to POST a request when this Jive Add-on is installed or updated. This value may start with the token %serviceURL%.
    unregister_urlOptionalString<URL>A URL to POST a request when this Jive Add-on is uninstalled. This value may start with the token %serviceURL%.
    config_urlOptionalString<URL>A URL to a HTML resource that will be shown as a synthetic app for configuring this Jive Add-on. This value may start with the token %serviceURL%.
    icon_16RequiredString

    The name of an image file in /data that contains a 16x16 PNG image to be used as this Add-ons small icon. The name of the icon should conform to the following pattern:

    {add-on name}-icon16x16.png

    icon_48RequiredString

    The name of an image file in /data that contains a 48x48 PNG image to be used as this Add-ons medium icon.

    {add-on name}-icon48x48.png

    icon_128

    Required for GRP*

    String

    The name of an image file in /data that contains a 128x128 PNG image to be used as this Add-on's medium icon.

    {add-on name}-icon128x128.png

    client_idOptionalStringSee type above, only available for mobile*
    client_secretOptionalStringSee type above, only available for mobile*
    redirect_urlOptionalString<URL>This is the URL the user will be redirected to after the user grants or denies authorization to client in the OAuth authorization code grant flow.
    health_urlOptionalString<URL>A URL that Jive can connect to to determine health and availability of the associated cloud service. See Add-On Health Check Format for detailed information.
    screen_shotsRequired for GRP*String[]

    An array of strings, up to 5. Each value is the name of an image file in /data that contains a 600 x 400 screen shot or preview image.

    {add-on name}-screenshot_{screenshot #}.png

    authorRequired for GRP*StringThe name of the developer who created this Jive Add-on.
    author_affiliationRequired for GRP*StringThe name of the company or organization to which the author is affiliated.
    author_emailRequired for GRP*String<email>The email address of the author of this Jive Add-on. Used for feedback communication or if Jive needs to contact the devloper for any reason. This email address is confidential and not exposed on any website.
    website_urlRequired for GRP*String<URL>The URL of a web site or page presenting information about this Jive Add-on or the company that developed it.
    community_urlOptionalString<URL>The URL of a web site or page where a user could learn more about, discuss, ask a question about, or report a problem with this Jive Add-on.
    support_infoRequired for GRP*StringThis may be either a URL or an email address where a user of this Jive Add-on can request assistance.
    info_emailRequired for GRP*String<email>An email address where a user can request detailed information about this Jive Add-on, prior to using or installing it.
    key_featuresOptionalString[]Up to three strings, presented as bullets when listed on the Jive website.
    target_integrationsOptionalString[]A list of systems or applications this Jive Add-on can integrate with. e.g.: "SalesForce", "Google Drive" or "Microsoft Outlook"
    solution_categoriesRequired for GRP*String[]The set of categories that the integration fits into. These will be defined by Jive and provided to the partner.
    tagsOptionalString[]The set of tags that are associated with the integration. These are defined by the partner.
    global_update_mac

    Required for add-ons listed globally.

    String

    This is used to verify extension updates when publishing an update to the registry. This is NOT used the first time the extension is published to the global registry.

    The value is computed using the following pseudocode:

    var mac = new HMAC(client_secret.getBytes("UTF-8"), "SHA256");
    var digest = mac.digest(client_id.getBytes("UTF-8"));
    meta.global_update_mac = toHexString(digest);
                               

    * Required for GRP - This field is required when the add-on will be published to the global registry.

     

    For HTML files, ONLY the following tags should be used:

    <a>
    <address>
    <blockquote>
    <code>
    <del>
    <dd><dl><dt>
    <em>
    <h3><h4><h5>
    <ol><ul><li>
    <p>
    <pre>
    <sup><sub>
    <small>
    <strong>
    <strike>
    <br>
    <hr>
                              

     

     

    Valid Jive Add-on Types

     

    All Jive Add-ons have a type. The type is used to filter or categorize add-ons in the Jive user interface, which helps manage add-ons. The type is also used to determine which bit of code in Jive will be used to apply the configuration data bundled in the add-on. You need to identify your add-on type when you create the meta.json file for the add-on package. The following table lists the add-on types we currently support.

     

    TypeDescription / Link
    client-appThe standard integration service, typically in the cloud. The Deal Room, StreamOnce and Realtime Chat/Video are examples of a client-app Jive Add-on.
    producteev-appThe custom add-on client app type that also disables Jive tasks on installation and enables them on uninstall
    jab-cartridges-appA proprietary add-on of a client app type that allows the definition of a Jive Anywhere cartridge. Requires the extended apis plugin to be installed.

     

     

     

    Supporting Localization - i18n

     

    Jive Add-ons can take full advantage of Jive's localization mechanisms. Each Jive Add-on is given its own i18n resource repository for localizing text strings presented to the user. While these strings do not support the same Java MessageFormat capabilities offered by the internal Jive mechanism, you can always perform your own string token replacement on the localized string.

     

    The Jive Add-on package can contain a /i18n folder. Files in this folder are in a standard Java Properties format, and are named is a standard manner. A few examples are given:

    • en.properties - Used for the default English translations, not specific to any country
    • en_US.properties - Used for US English translations
    • ja. properties - Used for Japanese translations, not specific to any country
    • root.properties - Used for the root locale, when translation strings are not specific to any country or language

     

    Connecting Back to Jive via the Register Callback URL

     

    When a Jive Add-on is installed, you can add a call to the add-on that passes information about the Jive instance to the cloud service. This call contains information about the Jive URL, the Integration user account, and other useful data. To have your cloud service notified when a Jive Add-on is called, you can add a registerURL value to the meta.json. The registerURL usually starts with the token %serviceURL% to facilitate testing and development. In the Ensure Register Calls are Coming from a Genuine Jive Instance section, you'll use this register call to make sure genuine Jive instances are being used.

    {
    "registerURL": "%serviceURL%/services/extension/lifecycle/register",  
        ...
    
    }
                                               

     

    The following example shows the sample data passed from a Jive instance that just installed add-on to the cloud service.

    {
        "clientId": "i5j15eikcd5u2xntgk5zu4lt93zkgx6z.i",
        "clientSecret": "7wmyigctxbopc22jo7u4xorxsn2m9r04.s",
        "code": "nki1dxrtl3r2q3kkgorwfkrmik234ppw.c",
        "scope": "uri:/api",
        "jiveUrl": "http://ws-z0-120493.jiveland.com:8080",
        "jiveSignature": "dtuW522kpoayRLFkPq6l3MOXxoKwfyNHsgGMlitr9PM=",
        "jiveSignatureURL": "https://market.apps.jivesoftware.com/appsmarket/services/rest/jive/instance/validation/29c38d1a-9c8a-4ec5-9b55-56fc44a5a402",
        "tenantId": "0ee9ae5c-4702-49eb-a716-3d46de4b10d3",
        "timestamp": "2013-07-12T15:28:46.493Z"
    }
                                                                                           

     

    Ensure Register Calls are Coming from a Genuine Jive Instance

     

    Authenticate register calls by getting the raw data, authenticating that data, and then granting permission for the service to access Jive.

     

    Getting the Raw data from Jive

     

    In many cases, your cloud service may need to ensure that the callback has been made by a genuine Jive Instance. This is accomplished by hashing a normalized representation of the data in the call.

    The following steps explain how to get the raw binary data from Jive:

    1. Exclude the jiveSignature entry. See the JavaScript Example  and Java Example sections to see how you can do this.
    2. Perform a SHA256 of the clientSecret value.
    3. Sort keys alphabetically.
    4. Write these keys and their values, one per line, ending with an empty line to a temporary buffer.
    5. Convert the resulting string to bytes using LF ('\n' - ASCII 10, not CRLF or CR) end-of-line characters and UTF-8 encoding.
    6. After completing these steps in the scripting language of your choice, complete the 4 steps in Validating Raw Data from Jive

    These steps produce the following raw data.

    clientId:i5j15eikcd5u2xntgk5zu4lt93zkgx6z.i
    clientSecret:67988da9f1378acbff239942f39a4eecb8684e82a8a7c17abc7c333a5623580e
    code:nki1dxrtl3r2q3kkgorwfkrmik234ppw.c
    jiveSignatureURL:https://market.apps.jivesoftware.com/appsmarket/services/rest/jive/instance/validation/29c38d1a-9c8a-4ec5-9b55-56fc44a5a402
    jiveUrl:http://ws-z0-120493.jiveland.com:8080
    scope:uri:/api
    tenantId:0ee9ae5c-4702-49eb-a716-3d46de4b10d3
    timestamp:2013-07-12T15:28:46.493Z
                                                                                           

     

    JavaScript Example

     

    Use the following examples to get an idea how you can produce the raw binary data (steps 1-5 above) in JavaScript.

    function buildValidationPayload(registerPayload) {  
    
    var validationBlock = JSON.parse( JSON.stringify(registerPayload) );  
    delete validationBlock['jiveSignature'];  
    
    var clientSecret = validationBlock['clientSecret'];  
    if (clientSecret != null) {  
    var crypto = require("crypto");  
    var sha256 = crypto.createHash("sha256");  
            sha256.update(clientSecret, "utf8");  
            validationBlock['clientSecret'] = sha256.digest("hex");  
        }
    
    var buffer = [];  
    var keys = Object.keys(validationBlock);  
        keys.sort();
    for (var i = 0, l = keys.length; i < l; i++) {  
    var key = keys[i];  
    if (validationBlock.hasOwnProperty(key)) {  
    var value = validationBlock[key];  
                buffer.push(key + ':' + value + '\n');  
            }
        }
    
    return buffer.join('');  
    }
    
    

    Java Example

     

    Use the following example to get an idea how you can produce the raw binary data (steps 1-5 above) in Java.

    public byte[] buildValidationPayload(Map<String, String> registerPayload) throws NoSuchAlgorithmException {  
            StringBuilder payload = new StringBuilder(1024);  
            List<String> keys = new ArrayList<String>(registerPayload.keySet());  
            keys.remove("jiveSignature"); // skip this one  
            Collections.sort(keys);
    for (String key : keys) {  
                payload.append(key);
                payload.append(':');  
    if ("clientSecret".equals(key)) {  
                    MessageDigest digest = MessageDigest.getInstance("SHA-256");  
                    digest.update(registerPayload.get("clientSecret").getBytes(Charset.forName("UTF-8")));  
    for (byte b : digest.digest()) {  
                        payload.append(String.format("%02x", b));  
                    }
                } else {  
                    payload.append(registerPayload.get(key));
                }
                payload.append("\n");  
            }
    return payload.toString().getBytes(Charset.forName("UTF-8"));  
        }
    
    

    Validating Raw Data from Jive

     

    Once you have the raw data you need to authenticate the jiveSignature using the following steps:

    1. Validate that the jiveSignatureURL starts with https://
    2. Execute a POST to the jiveSignatureURL, include a header X-Jive-MAC with the value of the jiveSignature
    3. Verify the server certificate normally and further check that is is issued to "Jive Software, Inc."
    4. The server response should be 204 No Content if the HMAC is valid, otherwise it will return 403.

     

    For more examples/details, see: How to Validate Signed Requests from an App Bundled in an Add-On

     

    Granting Authentication for Service to Access Jive

     

    To grant a service access to Jive, we use the standard Oauth protocol.

    • refresh token
    • access token

    See https://community.jivesoftware.com/docs/DOC-97348

     

    How Do I Install an Add-on into My Community?

     

    Refer to Installing and Updating an Add-on into Your Community for details.

     

    How Do I Validate My Jive Add-on?

     

    We provide a tool you can use to test if your add-on is valid: Validating Your Add-on Package

     

    Show Me an Example!

     

    Please see the attached .ZIP file for an example add-on.

     

    Publishing to the Add-ons Registry

     

    We're evaluating a process that allows you to get your add-on published to the Add-ons Registry so all Jive communities may have access to it.  If you're interested, the first step to getting engaged with us on this topic is to  become a Technology Partner.