none
How to get Access Token for Microsoft translator using javascript

    Question

  • I want to use Microsoft translation API using javascript. As first step I am trying to get access token, however I am getting  following error

    {"error":"invalid_request","error_description":"ACS90004: The request contains 1 tokens separated by \u0027=\u0027 instead of a single key value pair. \r\nTrace ID: 27f1b7e9-3bcc-4a57-aa28-c5902aa4f27f\r\nTimestamp: 2012-01-11 10:20:58Z"}
    not sure how to fix this. Following is the code snippet.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> Translator</TITLE>

    <script language="javascript">


    function getAccessToken(){
        try{
            // Opera 8.0+, Firefox, Safari
            ajaxRequest = new XMLHttpRequest();
        } catch (e){
            // Internet Explorer Browsers
            try{
                ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try{
                    ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){
                    // Something went wrong
                    alert("Your browser broke!");
                    return false;
                }
            }
        }
        // Create a function that will receive data sent from the server
        ajaxRequest.onreadystatechange = function(){
            if(ajaxRequest.readyState == 4){
                var ajaxDisplay = document.getElementById('tokenDiv');
                ajaxDisplay.innerHTML = ajaxRequest.responseText;
            }
        }
        var client_id = encodeURIComponent(document.getElementById('client_id').value);
        var client_secret = encodeURIComponent(document.getElementById('client_secret').value);
        var grant_type = encodeURIComponent(document.getElementById('grant_type').value);
        var scope = encodeURIComponent(document.getElementById('scope').value);
        var queryString = "?client_id=" + client_id + "&client_secret=" + client_secret + "&grant_type=" + grant_type + "&scope="+scope;
        var url="https://datamarket.accesscontrol.windows.net/v2/OAuth2-13" + queryString;

        ajaxRequest.open("POST", url, true);
        ajaxRequest.send(null);


    }






    </script>
    </HEAD>

    <BODY>
    <BR>
    <input type="button" name="b2" value="GetToken" onclick="javascript:getAccessToken();">
    <BR>
    <input type="hidden" name="client_id" id="client_id"  value="client_id_value" ><!-- This value is dummy -->
    <input type="hidden" name="client_secret" id="client_secret" value="client_secret_value" ><!-- This value is dummy -->
    <input type="hidden" name="grant_type" id="grant_type" value="client_credentials">
    <input type="hidden" name="scope" id="scope" value="http://api.microsofttranslator.com" >

    <BR>
    <div name="tokenDiv" id="tokenDiv">

    </div>
    </BODY>
    </HTML>

     

    Has anybody tried this before?

     

    Wednesday, January 11, 2012 10:26 AM

All replies

  • Can somebody help me out with this?
    Thursday, January 12, 2012 5:40 AM
  • Hello Rakesh,

    doing this in Javascript is not a good idea, because Javascript doesn't provide a good method to protect your secret, and doesn't allow you to easily set the http headers. Our recommendation is to obtain the access token on your server via SSL (using C#, PHP, or other server scripting language) and only transmit the access token embedded in the Javascript to the client. The client then uses the access token in its calls to Microsoft Translator. The access token is valid for 10 minutes.

    Let us know if this makes sense,
    Chris Wendt
    Microsoft Translator

    Friday, January 13, 2012 6:18 AM
  • Hey Chris, thanks  for the reply!

    Yes it makes perfect sense not to do it from client side script.

    I am working in java and have written sample program to get access token, once it works I will be running this on server side.

    Following is the java code which sets required request parameters and does post request to "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/". Currently it is resulting in "HTTP/1.1 400 Bad Request". I am not sure what needs to be done apart from setting the request parameters using post request.

    Any clue? Appreciate your help!

     

    package smp;

    import java.io.IOException;
    import java.net.URLEncoder;

    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.DefaultHttpClient;

    public class TranslatorUsingApache {
        public static void main(String[] args) throws ClientProtocolException, IOException {
            HttpClient httpclient=new DefaultHttpClient();
           
            String urlStr="https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/";       
            HttpPost httpPost=new HttpPost(urlStr);
            httpPost.getParams().setParameter("client_id", "client_id");// dummy
            httpPost.getParams().setParameter("client_secret", URLEncoder.encode("client_secret"));//dummy
            httpPost.getParams().setParameter("grant_type", "client_credentials");
            httpPost.getParams().setParameter("scope", "http://api.microsofttranslator.com");
            HttpResponse response = httpclient.execute(httpPost);
            System.out.println(response.getStatusLine());
        }
    }

    Tuesday, January 17, 2012 6:20 AM
  • Guys, You should put the parameters which is encoded by URLencorder or something else.


    Thursday, February 09, 2012 11:48 AM
  • Try this...

        try
        {
          // Construct content
          String content = "grant_type=" + grantType;
          content += "&client_id=" + clientID;
          content += "&client_secret=" + URLEncoder.encode(clientSecret);
          content += "&scope=" + scopeUrl;

          // Send data
          URL url = new URL(authUrl);
          URLConnection conn = url.openConnection();

          // Let the run-time system (RTS) know that we want input.
          conn.setDoInput (true);
          // Let the RTS know that we want to do output.
          conn.setDoOutput (true);
          // No caching, we want the real thing.
          conn.setUseCaches (false);
          // Specify the content type.
          conn.setRequestProperty
          ("Content-Type", "application/x-www-form-urlencoded");

       // Send POST output.
          DataOutputStream    printout = new DataOutputStream (conn.getOutputStream ());
          printout.writeBytes (content);
          printout.flush ();
          printout.close ();
          // Get response data.
          DataInputStream     input = new DataInputStream (conn.getInputStream ());
          String str;
          while (null != ((str = input.readLine())))
          {
          System.out.println (str);
          }
          input.close ();

                      
    Monday, April 02, 2012 2:51 AM
  • Buenos días desde el Masnou (Barcelona - España).

    No soy capaz de obtener el Token de acceso desde Lotusscript -similar a VB- , únicamente obtengo el error: The request contains 1 tokens separated by \u0027=\u0027 instead of a single key value pair....

    El código es similar al que vosotros habeis propuesto en diferentes foros. Se agradace cualquier sugerencia....

    Function MicrosoftTranslate(sLanguageFrom As String, sLanguageTo As String, sText As String) As String
        
        On Error Goto err_catch
       
        Dim ID As String
        Dim sURL As String
        Dim oH As Variant
        Dim sToken As String
        
        ID = ""
        sURL = "http://api.microsofttranslator.com/V2/Ajax.svc/Translate?oncomplete=&appId=" & ID _
        & "&from=" & sLanguageFrom & "&to=" & sLanguageTo & "&text=" & sText
        sToken = GetAccessToken()
        Set oH = CreateObject("MSXML2.XMLHTTP")
        oH.Open "POST", sURL, False
        oH.setRequestHeader "Authorization", "Bearer " & sToken
        oH.send
        MicrosoftTranslate = oH.responseText
        Set oH = Nothing
        
    exit_sub:
        Exit Function
        
    err_catch:
        Print Err & Error & Erl

        Resume exit_sub      
    End Function

    Function GetAccessToken() As String
        
        On Error Goto err_catch
       
        Dim webRequest As Variant
        Dim mtToken As String
        Set webRequest = CreateObject("MSXML2.ServerXMLHTTP")
        Dim URI As String
        Dim txtToken As String
        
        URI = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
        
        'Client ID from https://datamarket.azure.com/developer/applications
        Dim clientId As String
        clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        
        'Client secret from https://datamarket.azure.com/developer/applications
        Dim clientSecret As String
        clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxx"
        
        Dim sRequest As String
        sRequest = "grant_type=client_credentials" & _
        "client_id=" & clientId & _
        "client_secret=" & URLEncode(clientSecret, False) & _
        "scope=http://api.microsofttranslator.com"
        
        webRequest.Open "POST", URI, False
        webRequest.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        Call webRequest.send (sRequest)
         mtToken = webRequest.responseText
        Set webRequest = Nothing
     

       Dim arr As Variant, header As String
        header = "{""access_token"":"""
        arr = Split(mtToken, ",")
        txtToken = Mid$(arr(0), Len(header) + 1, Len(arr(0)) - Len(header) - 1)
         
        If txtToken = "_request" Then Resume err_catch:
       
        GetAccessToken = txtToken
        
        
    exit_sub:
         Exit Function
        
    err_catch:
        Print Err & Error & Erl

        Resume exit_sub    
        
    End Function

    Public Function URLEncode(StringToEncode As String, UsePlusRatherThanHexForSpace As Boolean ) As String
        
        On Error Goto err_catch   
        
        Dim TempAns As String
        Dim CurChr As Integer
        
        CurChr = 1

        Do Until CurChr - 1 = Len(StringToEncode)
            
            Select Case Asc(Mid(StringToEncode, CurChr, 1))
            Case 48 To 57, 65 To 90, 97 To 122
                TempAns = TempAns & Mid(StringToEncode, CurChr, 1)
            Case 32
                If UsePlusRatherThanHexForSpace = True Then
                    TempAns = TempAns & "+"
                Else
                    TempAns = TempAns & "%" & Hex(32)
                End If
            Case Else
                TempAns = TempAns & "%" & _
                Right("0" & Hex(Asc(Mid(StringToEncode, _
                CurChr, 1))), 2)
            End Select
            
            CurChr = CurChr + 1
        Loop

        URLEncode = TempAns
        
        
    exit_sub:
        Exit Function
        
    err_catch:
        Print Err & Error & Erl
        Resume exit_sub   
        
    End Function

    Sunday, April 15, 2012 10:55 AM
  • Hola!!!! hay alguien????

    Hi! anyone??


    Ernest

    Wednesday, April 18, 2012 8:41 PM
  • Hi Ernest -- check your email, but I think the issue is here:

    Dim sRequest As String
        sRequest = "grant_type=client_credentials" & _
        "client_id=" & clientId & _
        "client_secret=" & URLEncode(clientSecret, False) & _
        "scope=http://api.microsofttranslator.com"

    You don't have delimiters in the string...it should read something like

    Dim sRequest As String
        sRequest = "grant_type=client_credentials" & _
        "&client_id=" & clientId & _
        "&client_secret=" & URLEncode(clientSecret, False) & _
        "&scope=http://api.microsofttranslator.com"

    Let me know if this fixes the issue....


    //Laurence Moroney: www.netnavi.tv // Author of 'Introducing Silverlight' series and much more // @lmoroney

    Sunday, April 22, 2012 7:56 PM
  • Hi.

    I have a similar problem:
    How can I convert my old page ( http://www.weygandt.de/test/test.html ) to use the Access Token for Microsoft translator using AJAX / javascript without having a web space that allows PHP, ASP or any other server side script?
    I only can change the .htaccess file if that helps.

    Thanks in advance
    Andreas

    <!DOCTYPE html>
    <html>
    <head>
    
    <meta charset="utf-8">
    
    <title>TEST 16</title>
    
    </head>
    
    <body>
    
    <!-- Übersetzung Bing API Start -->
    
    <form method="post">
      <select id="langFrom">
        <option label="Deutsch" value="de" selected="selected">Deutsch</option>
        <option label="English" value="en">English</option>
        <option label="Thai" value="th">Thai</option>
      </select>
    
    
      <select id="langTo">
        <option label="Deutsch" value="de">Deutsch</option>
        <option label="English" value="en">English</option>
        <option label="Thai" value="th" selected="selected">Thai</option>
      </select>
    
      <textarea id="inputText" required="required">Hier bitte den original Text eingeben.</textarea>
    
      <input type="button" id="convert" value="Übersetzen" onClick="translate();" title="Zum Übersetzen hier klicken">
    
      <textarea name="Uebersetzung" readonly="readonly" id="resultMessage">Hier erscheint der übersetzte Text.</textarea>
    
    </form>
    
    
    <script type="text/javascript">
    /* <![CDATA[ */
        function translate() {
            window.mycallback = function(response) { document.getElementById("resultMessage").innerHTML = response; };
            var text = encodeURIComponent(document.getElementById("inputText").value);
            var languageFrom = document.getElementById("langFrom").options[document.getElementById("langFrom").selectedIndex].value;
            var languageTo = document.getElementById("langTo").options[document.getElementById("langTo").selectedIndex].value;
            var s = document.createElement("script");
            s.src = "http://api.microsofttranslator.com/V2/Ajax.svc/Translate?oncomplete=mycallback&appId=MyAppID&from=" + languageFrom + "&to=" + languageTo + "&text=" + text + "&contentType=text/plain";
            document.getElementsByTagName("head")[0].appendChild(s);
        }
    /* ]]> */	
    </script>
    
    <!-- Übersetzung Bing API Ende -->
    
    
    
    </body>
    
    </html>
    

    Sunday, March 24, 2013 4:49 PM
  • Hi,

    It's not a good idea to ask for a token on client-side but if you're using server-side javascript (Node.js) you can use the code below.

    If you don't have a client_id or secret than please read this article : http://msdn.microsoft.com/en-us/library/hh454950.aspx

    function gettoken() {

    var request = require('request');
    request.post(
        'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/',
        { form: {
           client_id : '@umitsunar',
           client_secret  : 'secret',
           scope  : 'http://api.microsofttranslator.com',
           grant_type  : 'client_credentials'
        } },
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                var jsBody = JSON.parse(body);
                console.log(jsBody.access_token);
            }
            else
            {
                console.log('error in request');           
            }
        }
    );
    }

    Sunday, March 24, 2013 11:18 PM
  • Thanks for your help.


    I followed your advice and upgraded my web space to ASP.NET 4.5.

    Today Searched and tested the whole evening but couldn’t find a straightforward solution how to add a code snippet to my old page to use the new Azure authorization without installing Visual Studio (I use Dreamweaver) + having a MasterPageFile, test.aspx.vb, AdmAuthentication class, C#... and many 500 errors.


    No paper chase, just a plain runat="server" in the same page would be perfect.


    Thanks in advance

    Andreas

    Saturday, March 30, 2013 9:58 PM
  • OH GOD THANK YOU FOR SHEDDING SOME SANITY.

    Really though the docs for this api are CRAP. That datamarket url isn't even freaking on the docs page!!!! Thank you again. I just spent 2 hours trying to get this dumb endpoint working.

    Where they explain how to send the parameters "The parameters for the token request are URL-encoded and passed in the HTTP request body." is very poorly worded and confusing. 

    It could mean you add the url encoded string to the url AND put it in the body. Which is dumb. But it's also dumb to url encode data into the body, so you can't really assume it's not the intended meaning because it's dumb... Really though. Who does that. It's json ffs.

    • Edited by Ryan_Cole Friday, August 01, 2014 10:45 AM more explaination
    Friday, August 01, 2014 10:41 AM
  • Also, what's the actual token?

    I get a giant url encoded thing back from the request. Is it the thing called : HMACSHA256 ?? Super unclear how this is supposed to work.

    Friday, August 01, 2014 11:00 AM