Search code examples
c#authenticationwebsocketibm-watsonspeech-to-text

C# IBM Speech to Text Get Token using APIKey


Based on the example at https://gist.github.com/nfriedly/0240e862901474a9447a600e5795d500, I am trying to use WebSocket to use the IBM Speech to Text API. But I am having problems with the authentication part. It looks like now IBM does not provide a username/password anymore. Only an api key.

So I cannot find a way to added that example to use an api to get the token.

Any know how to use WebSocket with the IBM apikey for authentication? The IBM doc does not seem to be up to date either as their example are using CURL with username and password https://console.bluemix.net/docs/services/speech-to-text/getting-started.html#getting-started-tutorial

I even saw somewhere that I could replace the username with "api" and the password by my apikey. But that's not working as I get an Unauthorized error from the server.

Maybe I misread and I should pass a token instead of the password. But then how do I get a token from my APIkey with websockets?

I can get a token using HttpClient without problems. But it looks like I cannot use that token with Websocket after that, only further HttpClient calls.


Solution

  • With some help I finally found how to handle the WebSocket with the apiKey.

    I post the code here in case someone else needs it

    IamTokenData GetIAMToken(string apikey)
    {
      var wr = (HttpWebRequest)WebRequest.Create("https://iam.bluemix.net/identity/token");
      wr.Proxy = null;
      wr.Method = "POST";
      wr.Accept = "application/json";
      wr.ContentType = "application/x-www-form-urlencoded";
    
      using (TextWriter tw = new StreamWriter(wr.GetRequestStream()))
      {
        tw.Write($"grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={apikey}");
      }
      var resp = wr.GetResponse();
      using (TextReader tr = new StreamReader(resp.GetResponseStream()))
      {
        var s = tr.ReadToEnd();
        return JsonConvert.DeserializeObject<IamTokenData>(s);
      }
    }
    
    IamTokenData tokenData = GetIAMToken([Your IamApiKey]);
    
    CancellationTokenSource cts = new CancellationTokenSource();
    
    ClientWebSocket clientWebSocket = new ClientWebSocket();
    
    clientWebSocket.Options.Proxy = null;
    clientWebSocket.Options.SetRequestHeader("Authorization", $"Bearer {token.AccessToken}");
    
    // Make the sure the following URL is that one IBM pointed you to
    Uri connection = new Uri($"wss://gateway-wdc.watsonplatform.net/speech-to-text/api/v1/recognize");
    try
    {
      //await clientWebSocket.ConnectAsync(connection, cts.Token);
      clientWebSocket.ConnectAsync(connection, cts.Token).GetAwaiter().GetResult();
      Console.WriteLine("Connected!");
    }
    catch (Exception e)
    {
      Console.WriteLine("Failed to connect: " + e.ToString());
      return null;
    }
    
    // ... Do what you need with the websocket after that ...