Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Info

To enable External Share functionality within an iframe hosted on a website outside of atlassian.com, external-share.com or your External Share for Jira custom domain, you must add a URL under:
Global Settings → Other → Custom content security policy

Example of java code that generates JWT:

Code Block
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.awt.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;

class Main {
    public static void main(String[] args) throws Exception {
        // input
        var secretHex = "D90B5B3529ECCCDB67EF991E3C8CE079379EAF49803A5A88E257CBD31B8AD03D";
        var shareUuid = "972faf56-7abf-4a15-bd1b-be70f6f8148d";

        // main logic
        var secret = hexStringToByteArray(secretHex);
        var jwt = createJWT(secret, shareUuid);

        // output
        System.out.println(jwt);
        var url = "https://confluence.external-share.com/content/" + shareUuid + "?unlock=" + jwt;
        Desktop.getDesktop().browse(new URI(url));
    }

    private static String createJWT(byte[] secret, String shareUUID) throws Exception {
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        var nbf = Instant.now();
        var exp = nbf.plusSeconds(60);

        Map<String, Object> payload = new HashMap<>();
        payload.put("nbf", nbf.getEpochSecond());
        payload.put("exp", exp.getEpochSecond());
        payload.put("iss", shareUUID);

        var headerBase64 = base64UrlEncode(toJson(header));
        var payloadBase64 = base64UrlEncode(toJson(payload));

        var signature = hmacSha256(secret, headerBase64 + "." + payloadBase64);

        return headerBase64 + "." + payloadBase64 + "." + signature;
    }

    private static String hmacSha256(byte[] secret, String data) throws Exception {
        var mac = Mac.getInstance("HmacSHA256");
        var secretKeySpec = new SecretKeySpec(secret, "HmacSHA256");
        mac.init(secretKeySpec);
        var hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return base64UrlEncode(hash);
    }

    private static byte[] hexStringToByteArray(String s) {
        var len = s.length();
        var data = new byte[len / 2];
        for (var i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                                  + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    private static String toJson(Map<String, Object> map) {
        var joiner = new StringJoiner(",", "{", "}");
        for (var entry : map.entrySet()) {
            joiner.add("\"" + entry.getKey() + "\":\"" + entry.getValue().toString() + "\"");
        }
        return joiner.toString();
    }

    private static String base64UrlEncode(String str) {
        return Base64.getUrlEncoder().withoutPadding().encodeToString(str.getBytes(StandardCharsets.UTF_8));
    }

    private static String base64UrlEncode(byte[] bytes) {
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }

}