Working with a compressed base64 query parameter using NodeJS

I am writing a Node based web service that expects a third party to send a SAML request that is deflated and base64 encoded. After the crash for most of the day, I'm afraid I'm not sure I even know what to ask (I apologize if this is a hoax).

The docs say:

SAMLRequest is first compressed DEFLATE, then Base 64 encoded, then URL encoded. It must be decoded and analyzed.

The Webstorm console log has this query string:

GET / Login? SAMLRequest = fZJRa9swEMff9ymE3m1LipM4InbJ0mwrNCM0bqF9Gap8cQW2lOnksH37ObFbWgZ9lLj76X% 2F30% 2FLqT9uQE3g0zuaUx4wSsNpVxtY5vS% 2B% 2FRRm9Kr4sUbWNOMpVF17sHfzuAANZIYIPfd% 2FaWexa8HvwJ6Ph% 2Fu42py8hHFEmCV% 2BImM% 2BymMWCswRBd96Ev1GrrKrBJ2eueuXokUPJdc83VoVLqDPqA4lPmJwwxpLG1cZScnOd018HJeaLSsNkqhfAqql6nsyyVFQiEweWqnlfhrv% 2BKXOCnB5Ug3C% 2BwQ5uLAZlQ04F42nE5hHPSj6VKZc8jfmcP1Gy8y447Zqvxg6L6byVTqFBaVULKIOW% 2B9X2VoqYyeehCOWPstxFq36yg9LhAjmZCvzPviOn352rGyAbG8AfvUEg% 2B3E3ZDvshpKHVy3irKUXZVEOIj5PcBzj0mLwJi9z% 2BveEzwFvRmgxLr% 2B% 2BxI21axN4i5zUqJIyjTaP23SzftyK9Wwm% 2FnO8TN6HKMbjx79U% 2FAM% 3D

Conclusion

console.log(req.query.SAMLRequest)

shows that URL decoding is done automatically:

fZJRa9swEMff9ymE3m1LipM4InbJ0mwrNCM0bqF9Gap8cQW2lOnksH37ObFbWgZ9lLj76X/30/LqT9uQE3g0zuaUx4wSsNpVxtY5vS +/RRm9Kr4sUbWNOMpVF17sHfzuAANZIYIPfd/aWexa8HvwJ6Ph/u42py8hHFEmCV + + ymMWCswRBd96Ev1GrrKrBJ2eueuXokUPJdc83VoVLqDPqA4lPmJwwxpLG1cZScnOd018HJeaLSsNkqhfAqql6nsyyVFQiEweWqnlfhrv + KXOCnB5Ug3C + wQ5uLAZlQ04F42nE5hHPSj6VKZc8jfmcP1Gy8y447Zqvxg6L6byVTqFBaVULKIOW + 9X2VoqYyeehCOWPstxFq36yg9LhAjmZCvzPviOn352rGyAbG8AfvUEg + 3E3ZDvshpKHVy3irKUXZVEOIj5PcBzj0mLwJi9z + veEzwFvRmgxLr ++ xI21axN4i5zUqJIyjTaP23SzftyK9Wwm/nO8TN6HKMbjx79U/ =

, base64, INFLATE. ( , , , ):

var zlibJS = require('zlibjs');  //I've tried Node own zlib but that only appears to work with call backs
...
var b = new Buffer(samlReq, 'base64');
var decoded = b.toString();
var inflated = zlibJS.inflateSync(decoded); //https://github.com/imaya/zlib.js/blob/master/test/node-test.js
//I get an Unsupported compression method 
...//relooking at the test it appears it wants a buffer so switch the above line for this
var inflated = zlibJS.inflateSync(b); // same 500 error

github, , , , . ( ) base64 (http://www.motobit.com/util/base64-decoder-encoder.asp), url- (http://meyerweb.com/eric/tools/dencoder/) (http://i-tools.org/gzip) ( , ...)

, / ,

+4
3

SO, pako, wikipedia ZLib, , :

var pako = require('pako'); 
...
var b = new Buffer(samlReq, 'base64');
var inflated = pako.inflateRaw(b, {to:'string'}); 
+3

, SAML, , base64 URL ( , URL-)

, async, - :

var async = require('async');
var zlib = require('zlib');
var url = require('url');

var samlRequest = '<?xml version="1.0" encoding="UTF-8"?>'
  + '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">'
  + '...'
  + '</samlp:AuthnRequest>';

var buffer = new Buffer(samlRequest);

async.waterfall(
  [
    function deflate(callback) {
      zlib.deflate(buffer, function deflated(err, resultBuffer) {
        if (err) {
          callback(err);
          return;
        }

        callback(null, resultBuffer);
      });
    },
    function encode(buffer, callback) {
      callback(null, buffer.toString('base64'));
    },
    function urlEncode(request, callback) {
      callback(null, encodeURIComponent(request));
    }
  ], function handleResult(err, urlEncodedRequest) {
    if (err) {
      console.log(err);
      return;
    }

    var baseUrl = 'http:xxx.salesforce.com/idp/endpoint/HttpRedirect?SAMLRequest=';
    console.log(baseUrl + urlEncodedRequest);
  }
);

samlRequest - , , . , , , .

0

JavaScript Node.js, SAML- , Node zlib Buffer . , pako ( ).

saml-encode-decoder-js NPM. :

var saml = require('saml');

saml.decodeSamlRedirect(xml, function(err, xml) {
  if (!err) {
    console.log("Redirect decoded XML", xml);
  }
}

saml.decodeSamlPost(xml, function(err, xml) {
  if (!err) {
    console.log("POST decoded XML", xml);
  }
}

NPM . , saml-encoder-decoder-js SAML:

var zlib = require('zlib');

function decodeSamlRedirect(encoded, cb) {
  if (encoded == null || encoded == "") {
    return cb(new Error('Cannot decode null string'));
  }
  var deflated = new Buffer(decodeURIComponent(encoded), 'base64');

  zlib.inflateRaw(deflated, function (err, inflated) {
    if (!err) {
      return cb(null, inflated.toString('ascii'));
    } else {
      return cb(err);
    }
  });
}

zlib.deflateRaw() zlib.inflateRaw() . deflate() unzip().

If you use SAML POST bindings, then this is really just a shell for using Node Bufferto encode Base64 encoding / decoding, as here:

function decodeSamlPost(encoded, cb) {
  if (encoded == null || encoded == "") {
    return cb(new Error('Cannot decode null string'));
  }
  return cb(null, new Buffer(encoded, 'base64').toString('ascii'));
}
0
source

All Articles