Source: hmac.plugin.js

/**
*
*  Parametri Oggetto irenHmac
*
* @typedef {Object} irenHmac.options         - Parametri di inizializzazione dell'oggetto
*                                     irenHmac
*  @property {string} serviceUrl    - url del servizio di verifica
*  @property {string} method        - metodo di chiamata del servizio
*                                     (GET o POST)
*  @property {string} authPrm       - parametro da considerare
*                                     nell'autenticazione
*  @property {string} reqParams     - Parametri di GET per il calcolo dell'Hash
*  @property {string} invalidParams - Parametri di GET da non considerare
*                                     nella creazione della Hash
*  @property {string} verified      - stato di verifica dell'oggetto HMac
*  @property {string} path          - path della pagina
*  @property {string} cookie        - nome del cookie dove recuperare la secret
*  @property {string} secret        - SECRET
*  @property {string} noValidPage   - pagina di redirect se validazione fallita
*  @property {string} noAuthPage    - pagina di redirect se nessuna
*                                     autenticazione fornita
*/

(function () {
/**
 * Classe irenHmac:
 *
 * @constructs irenHmac
 * @requires js/sha256.js
 * @requires js/jquery.js
 * @param {irenHmac.options} options          - Parametri di inizializzazione dell'oggetto
 *                                    irenHmac
 * @return {Object} irenHmac        - Oggetto irenHmac
 */
    this.irenHmac = function( options ) {

        // This is the easiest way to have default options.
        var invalid = ['hmac'];
        var prms = this.getQueryParams();;
        var pathname = this.getCurrentPath();
        var defaults = {
            serviceUrl : "service.php",
            method : "POST",
            authPrm : "hmac",
            reqParams : prms,
            noAuthPage : "noauth.html",
            noValidPage : "novalid.html",
            verified : 0,
            invalidParams : invalid,
            path : pathname,
            cookie : "___IREN___HMAC",
            secret : "mysecret",
        }
        if (arguments[0] && typeof arguments[0] === "object") {
            this.options = extendDefaults(defaults, arguments[0]);
        }
        else{
            this.options = defaults;
        }
        if (!this.options.reqParams[this.options.authPrm]){
            this.noAuth();
        }

        return this;

    };

    // Recupero i parametri di GET
/**
 * Metodo che data una queryString ne prende i suoi parametri e restituisce
 * un oggetto
 * @return {Object}  - Oggetto con i parametri della query string
 */
    irenHmac.prototype.getQueryParams = function(){
        var params = {};

        if (location.search) {
            var parts = location.search.substring(1).split('&');

            for (var i = 0; i < parts.length; i++) {
                var nv = parts[i].split('=');
                if (!nv[0]) continue;
                params[nv[0]] = decodeURIComponent(nv[1]) || true;
            }
        }
        return params;
    };

    // Creazione della query string prendendo i parametri di GET e riordinandoli
/**
 * Metodo che dati i parametri in options.reqParams li ordina i ordine alfabetico,
 * elimina i parametri in options.inValidParams e restituisce una queryString
 * codificata
 * @return {string} QueryString
 */
    irenHmac.prototype.createQueryString = function(){
        var str = [];
        var unsortedObj = this.options.reqParams;
        obj = getSortedObject(unsortedObj);
        for(var p in obj){
            if (obj.hasOwnProperty(p) && (this.options.invalidParams.indexOf(p)==-1)) {
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                //str.push(p + "=" + obj[p])
            }
        }
        return (this.options.path + '?' + str.join("&"));

    }

    // Restituzione del path della pagina chiamata (Serve nel calcolo del messaggio e della Hash)
/**
 * Metodo che restituisce il path della url corrente
 * @return {string} Path della url corrente
 */
    irenHmac.prototype.getCurrentPath = function(){
        return document.location.pathname;
    };

    //Recupero della secret in prima battuta da Cookie altrimenti da opzioni
/**
 * Metodo che restituisce la secret per creare la hash
 * Se viene passato il parametro cerca nel cookie altrimenti nel cookie di default.
 * Se non trova nulla usa la secret impostata nelle options
 * @param  {string} name nome del cookie dove recuperare la chiave di codifica
 * @return {string}      Chiave di codifica
 */
    irenHmac.prototype.getSecret = function(name) {
        if (!name) name = this.options.cookie;
        match = document.cookie.match(new RegExp(name + '=([^;]+)'));
        if (match) return match[1];
        else
            return this.options.secret;
    }

    // Redirect su pagina di Nessuna Autorizzazione
/**
 * Metodo di redirect sulla pagina di Nessuna Autenticazione passata
 * @return {void}
 */
    irenHmac.prototype.noAuth = function (){
        window.location.href = this.options.noAuthPage;
    }

    // Redirect su pagina di Validazione Fallita
/**
 * Metodo di redirect sulla pagina di Autenticazione Fallita
 * @return {void}
 */
    irenHmac.prototype.noValid = function (){
        window.location.href = this.options.noValidPage;
    }

    //Creazione dell'Hash data password e messaggio
/**
 * Metodo di creazione della Hash
 * @param  {string} message messaggio da criptare
 * @param  {string} secret  Chiave di codifica
 * @return {string}         Hash
 */
    irenHmac.prototype.createHash = function(message,secret){
        // Step 1 Crypt Password
        var crypt = new jsSHA("SHA-256", "TEXT");
        crypt.update(secret);
        var mysecret = crypt.getHash("HEX");
        //Step 2 Calculate HMac
        var shaObj = new jsSHA("SHA-256", "TEXT");
        shaObj.setHMACKey(mysecret, "TEXT");
        shaObj.update(message);
        return shaObj.getHMAC("B64");
    }

    //Metodo di verica dell'HMac dai dati di QueryString in Javascript Con Chiamata Ajax Funziona SU HTML
/**
 * Verifica tramite chiamata AJAX
 * @return {void} Reindirizzamento su pagina di autenticazione fallita
 */
    irenHmac.prototype.verifyAjaxHmac = function(){
        var self = this;
        var d = {action: 'verify',path: this.options.path, params : this.options.reqParams};
        $.ajax({
            async : false,
            url : this.options.serviceUrl,
            method : this.options.method,
            data : d,
            dataType : 'json',
            error : function( jqXHR, textStatus, errorThrown ){
                this.noauth();
            },
            success: function(data, textStatus, jqXHR){
                if (data.success != 1) {
                    self.options.verified = 0;
                    self.noValid();
                }
                else{
                    self.options.verified = 1;
                }
            }
        });
    };
/**
 * Verifica della hash in Pure Javascript
 * @return {void} Reindirizzamento alla pagina di autenticazione fallita
 */
    //Metodo di verica dell'HMac dai dati di QueryString in Javascript Funziona SU HTML
    irenHmac.prototype.verifyJSHmac = function(){
        var string = this.createQueryString();
        var hmac = this.options.reqParams[this.options.authPrm];
        var secret = this.getSecret();
        var hash = this.createHash(string,secret);
        if (hmac==hash){
            this.options.verified = 1;
        }
        else{
            this.options.verified = 0;
            this.noValid();
        }
    }


}());

function extendDefaults(source, properties) {
    var property;
    for (property in properties) {
        if (properties.hasOwnProperty(property)) {
            source[property] = properties[property];
        }
    }
    return source;
}



function getSortedObject(object) {
  var sortedObject = {};

  var keys = Object.keys(object);
  keys.sort();

  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  return sortedObject;
}