-1

I have to signature my lastfm api:

  1. Sign your calls

Construct your api method signatures by first ordering all the parameters sent in your call alphabetically by parameter name and concatenating them into one string using a scheme. So for a call to auth.getSession you may have:

api_keyxxxxxxxxmethodauth.getSessiontokenxxxxxxx

Ensure your parameters are utf8 encoded. Now append your secret to this string. Finally, generate an md5 hash of the resulting string. For example, for an account with a secret equal to 'mysecret', your api signature will be:

api signature = md5("api_keyxxxxxxxxmethodauth.getSessiontokenxxxxxxxmysecret")

Where md5() is an md5 hashing operation and its argument is the string to be hashed. The hashing operation should return a 32-character hexadecimal md5 hash.

var myAPI_key="b6720a4ef50c0a1f63419e334fbf9c74";
var myshared_secret="5df5d9e40e9375f043edf1e1fb629236";

var url = window.location.href; // or window.location.href for current url
var captured = /token=([^&]+)/.exec(url)[1]; // Value is in [1] ('384' in our case)
var result = captured ? captured : 'myDefaultValue';
console.log(captured);

function calculateApiSignature(){
  String.prototype.hashCode = function(){

       var hash = 0;

       if (this.length == 0) return hash;

       for (i = 0; i < this.length; i++) {

           char = this.charCodeAt(i);

           hash = ((hash<<5)-hash)+char;

           hash = hash & hash; // Convert to 32bit integer

       }

       return hash;

   };
  var string = "api_key" + "b6720a4ef50c0a1f63419e334fbf9c74"+ "methodauth.getSessiontoken"+captured;
  var textoUtf8 = encodeURI(string);
  textoUtf8 = textoUtf8 + myshared_secret;
  console.log("String a firmar : " + textoUtf8);
  var ApiSignature = textoUtf8.hashCode();
  console.log("Api Signature" + ApiSignature);

}
<!DOCTYPE html>
<html>
 <head>
  <title>Menu principal Last FM</title>
  <meta charset="utf-8">
   <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <!-- <script type="text/javascript" src="./js/constants.js"></script>-->
   <script type="text/javascript" src="./js/main.js"></script>
  </head>
 <body>
  <h1>Im login to</h1>
  <div id="userData">
<!--<img src="https://lastfm-img2.akamaized.net/i/u/34s/cc637716959b4acecaa1a307e300f61f.png" />-->
  </div>
  <div id="success">
      <div id="artistName"></div>
      <div id="artistImage"></div>
      <div id="artistBio"></div>
  </div>
  <div id="error"></div>

  <button type="button" onclick="loadUserInfoXMLDoc()">Get User information</button>
  <br><br>
  <button type="button" onclick="loadChartTopArtistsJSONDoc()">Get Top Artist Chart</button>
  <button type="button" onclick="calculateApiSignature()">Calculate API</button>

  <table id="demo"></table>

  <p id="artist"></p>

 </body>
</html>

Dont know what im missing or doing wrong.... I think i follow the instructions to get the api_signature....

Then once i have the api_signature i think id have to make a call:

    $.ajax({
    type : 'GET',
    url : 'http://ws.audioscrobbler.com/2.0/?',
    data : 'api_key=b6720a4ef50c0a1f63419e334fbf9c74&' +
           'token:xxxx&'+
           'api_sig:apisig from above',            
    dataType : 'json',
    success : function(data) {
           //hooray
       },
    error : function(code, message){
         //upset
    }
});
  • It seems you used your own hash function and not md5. In any case, you should link (and ev. quote) the documentation. So it is difficult to understand what are your text and what come from documentation. You do not print on error, so you will not see the code + message. – Giacomo Catenazzi Mar 22 '19 at 10:09
  • Sorry i copy/paste the relevant thing in my opinion...here is the link....https://www.last.fm/api/webauth and some work around in other stackoverflow... – Eduardo Gutierrez Mar 22 '19 at 10:28
  • Where do you apply md5? What is your hash function? (Do no copy from C, Javascript has different types [and no integer types] – Giacomo Catenazzi Mar 22 '19 at 10:37
  • i have updated my progress, i think i have a result but dont know if its correct: https://jsfiddle.net/pyebz7L2/ and i use to calculate md5 this: https://github.com/blueimp/JavaScript-MD5/blob/master/js/md5.min.js.... I use CalculateApiSigSTack just to do the work and make the call....Thanks – Eduardo Gutierrez Mar 22 '19 at 11:31

2 Answers2

0

A solution i found, and works for me:

/*
Metode: https://www.last.fm/api/show/auth.getSession
Objective: Fetch a session key for a user. The third step in the authentication process. See the authentication how-to for more information.
          ( as we are making a web application...https://www.last.fm/api/webauth)
Params:
token (Required) : A 32-character ASCII hexadecimal MD5 hash returned by step 1 of the authentication process (following the granting of
                  permissions to the application by the user)
api_key (Required) : A Last.fm API key.
api_sig (Required) : A Last.fm method signature. See authentication for more information

Api_sig requereix uns quants canvis ( calculs complicats que he anant fent)...

Result JSON expected:
exit ->
{
  "session": {
    "subscriber": 0,
    "name": "edufissure",
    "key": "fem3L_nnsWNwD_yGL4mtVRPOlblLynx5"
  }
}
error ->
{
  "error": 4,
  "message": "Unauthorized Token - This token has not been issued"
}
*/

function calculateApiSignatureStack()
{

/*note in captured i have a string with the actual token....


You can get it from your url: 

var url = window.location.href; // or window.location.href for current url
var captured = /token=([^&]+)/.exec(url)[1]; // Value is in [1] ('384' in our case)
*/

  // Set elsewhere but hacked into this example:
var last_fm_data = {
    'last_token':captured,
    'user': 'bob',
    'secret': '5df5d9e40e9375f043edf1e1fb629236'
};

// Kick it off.
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']});


// Low level API call, purely builds a POSTable object and calls it.
function last_fm_call(method, data){
    // param data - dictionary.
    last_fm_data[method] = false;
    // Somewhere to put the result after callback.

    // Append some static variables
    data.api_key = "b6720a4ef50c0a1f63419e334fbf9c74";
    //data['format'] = 'json';
    data['method'] = method;

    post_data = last_fm_sign(data);
/*
.*/
    console.log("Post data: Last token " + post_data.token + "ApiKey: "+ post_data.api_key + "ApiSig: " + post_data.api_sig);
    sessionStorage.setItem("myApiSig",post_data.api_sig );

    var last_url="http://ws.audioscrobbler.com/2.0/?";
    $.ajax({
      type: "GET",
      url: last_url,
      data : 'method=auth.getSession' +
             '&token='+
             captured+
             '&api_key=b6720a4ef50c0a1f63419e334fbf9c74' +
             '&api_sig='+
              post_data.api_sig+
             '&format=json',
      //data: post_data,
      dataType: 'json',
      success: function(res){
          last_fm_data[method] = res;
          //var myresposta = JSON.parse(res);
          console.log("Resposta: Name " + res.session.name);// Should return session key.
          console.log("Resposta: Key " + res.session.key);

          //store session key for further authenticate operations...
          sessionStorage.setItem("mySessionKey", res.session.key);
      },
      error : function(code, message){
          console.log("Error en autenticacion");
      }
     });
}

function last_fm_sign(params){
    ss = "";
    st = [];
    so = {};
    so['api_key'] = params['api_key'];
    so['token'] = params['token'];
    Object.keys(params).forEach(function(key){
        st.push(key); // Get list of object keys
    });
    st.sort(); // Alphabetise it
    st.forEach(function(std){
        ss = ss + std + params[std]; // build string
    });
    ss += last_fm_data['secret'];
        // console.log(ss + last_fm_data['secret']);
        // api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386
    //hashed_sec = $.md5(unescape(encodeURIComponent(ss)));
    var hashed_sec = md5(unescape(encodeURIComponent(ss))); // "2063c1608d6e0baf80249c42e2be5804"
    console.log("La apiSig es: " + hashed_sec);
    so['api_sig'] = hashed_sec; // Correct when calculated elsewhere.
    return so; // Returns signed POSTable object
}
}
0
{
  "error": 4,
  "message": "Unauthorized Token - This token has not been issued"
}

In my case, this error was happening because the token is only good for one session.

I had a bug throwing an error but I thought it was in the query or signature builder. Turns out the bug was in reading the response from last.fm, so I successfully created a session (without knowing it) and on subsequent queries received the above error because the token had been invalidated.

displacedtexan
  • 976
  • 8
  • 17