I am trying to decode base64 encoded string in apigee through below javascript in apigee, but it is giving me an error “Error: “atob” is not defined.”
var jsonstr = context.getVariable("JWTToken");
var str = decoder(jsonstr);
context.setVariable("context.targetResponse",str);
function decoder(base64url) {
try {
//Convert base 64 url to base 64
var base64 = base64url.replace('-', '+').replace('_', '/'); //atob() is a built in JS function that decodes a base-64 encoded string
var utf8 = atob(base64); //Then parse that into JSON
var json = JSON.parse(utf8); //Then make that JSON look pretty
var json_string = JSON.stringify(json, null, 4);
}
catch (err) {
json_string = "Bad Section.\nError: " + err.message;
}
print(json_string);
return json_string;
}
do you have Apigee Edge SaaS? You can do what you want with the DecodeJWT policy. It’s built-in.
If you do not have Apigee Edge SaaS, then you need something like this:
// jwtDecode.js
function base64Decode(input) {
// Takes a base 64 encoded string "input", strips any "=" or
// "==" padding off it and converts its base 64 numerals into
// regular integers (using a string as a lookup table). These
// are then written out as 6-bit binary numbers and concatenated
// together. The result is split into 8-bit sequences and these
// are converted to string characters, which are concatenated
// and output.
// The index/character relationship in the following string acts
// as a lookup table to convert from base 64 numerals to
// Javascript integers
var swaps = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
ob = "",
output = "",
tb = "",
i, L;
input = input.replace("=",""); // strip padding
for (i=0, L = input.length; i < L; i++) {
tb = swaps.indexOf(input.charAt(i)).toString(2);
while (tb.length < 6) {
// Add significant zeroes
tb = "0"+tb;
}
while (tb.length > 6) {
// Remove significant bits
tb = tb.substring(1);
}
ob += tb;
while (ob.length >= 8) {
output += String.fromCharCode(parseInt(ob.substring(0,8),2));
ob = ob.substring(8);
}
}
return output;
}
function decodeJwt(input){
var parts = input.split('.'),
header, payload;
if (parts.length !== 3) {
return null; // not a valid JWT
}
header = base64Decode(parts[0]);
header = header.replace(/\0/g, '');
//header = JSON.parse(header);
payload = base64Decode(parts[1]);
payload = payload.replace(/\0/g, '');
//payload = JSON.parse(payload);
return {
header: header,
payload : payload,
sig : parts[2]
};
}
var jsonstr = context.getVariable("JWTToken");
var result = decodeJwt(jsonstr);
context.setVariable("context.targetResponse",result.payload);
As for why the atob() function is not available - the JavaScript callout does not have the full node runtime, nor does it have the browser runtime. It’s a stripped down Rhino runtime. atob() is not included in that.
This won’t work if the encoded thing represents a byte stream that cannot be decoded into a UTF-8 string. For example, if it’s a base64-encoded image or PDF. For that you need a different approach - a Java callout or…something else.
@dchiesa1 DecodeJWT fails to decode for unsignedJWT. I get the following error “Invalid JWS header: The algorithm “alg” header parameter must be for signatures” from trace