title: remote server returned an error: (401) unathorized in C# GCM response
body: <p>I have seen this question posted in a thousand places and I have tried all the solutions that have worked for others but I am not able to get this to work for me.  I used this post as my baseline for the project that Im using (<a href="https://stackoverflow.com/questions/11431261/unauthorized-when-calling-google-gcm">Unauthorized when calling Google GCM</a>).  I have tried both the API key and the browser key with no success.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Web;
  using System.Net;
  using System.Net.Security;
  using System.Security.Cryptography.X509Certificates;
  
  using System.IO;
  
  namespace GCMTest
  {
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
  
          private void button1_Click(object sender, EventArgs e)
          {
              string BrowserAPIKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  
              string message = "some test message";
              string tickerText = "example test GCM";
              string contentTitle = "content title GCM";
              string postData = "{ \"registration_ids\": [ \"" + txtRegistrationID.Text + "\" ], \"data\": {\"tickerText\":\"" + tickerText + "\", \"contentTitle\":\"" + contentTitle + "\", \"message\": \"" + message + "\"}}";
  
              string response = SendGCMNotification(BrowserAPIKey, postData);
          }
  
          private string SendGCMNotification(string apiKey, string postData, string postDataContentType = "application/json")
          {
              // from here:
              // https://stackoverflow.com/questions/11431261/unauthorized-when-calling-google-gcm
              //
              // original:
              // http://www.codeproject.com/Articles/339162/Android-push-notification-implementation-using-ASP
  
              ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
  
              //
              //  MESSAGE CONTENT
              byte[] byteArray = Encoding.UTF8.GetBytes(postData);
  
              //
              //  CREATE REQUEST
              HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
  
              Request.Method = "POST";
              Request.KeepAlive = false;
              Request.ContentType = postDataContentType;
              //Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
              Request.Headers.Add(HttpRequestHeader.Authorization, String.Format("key={0}", apiKey));
              Request.ContentLength = byteArray.Length;
  
              //Stream dataStream;
              try
              {
                  Stream dataStream = Request.GetRequestStream();
  
                  dataStream.Write(byteArray, 0, byteArray.Length);
                  dataStream.Close();
              }
              catch (Exception e)
              {
                  MessageBox.Show(e.Message);
              }
  
              //
              //  SEND MESSAGE
              try
              {
                  WebResponse Response = Request.GetResponse();
  
                  HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
  
                  if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
                  {
                      MessageBox.Show("Unauthorized - need new token");
  
                  }
                  else if (!ResponseCode.Equals(HttpStatusCode.OK))
                  {
                      MessageBox.Show("Response from web service isn't OK");
                  }
  
                  StreamReader Reader = new StreamReader(Response.GetResponseStream());
                  string responseLine = Reader.ReadToEnd();
                  Reader.Close();
  
                  return responseLine;
              }
              catch (Exception e)
              {
                  MessageBox.Show(e.Message);
              }
              return "error";
          }
  
  
          public static bool ValidateServerCertificate(
                                                    object sender,
                                                    X509Certificate certificate,
                                                    X509Chain chain,
                                                    SslPolicyErrors sslPolicyErrors)
          {
              return true;
          }
      }
  
  }
  </code></pre>
  
  <p>Its erring on this line:</p>
  
  <pre><code>WebResponse Response = Request.GetResponse();
  </code></pre>
  
  <p>With the following message:
  "The remote server returned an error: (401) Unauthorized."</p>
  
  <p>The form allows an input of a device registration id.  If I can get this working it will be altered to be more usable in a production environment.  The application is running on my local machine right now but will ultimately reside on a remote server.  </p>
  
  <p>Any help that I can get would be GREATLY appreciated.  I have been reading posts about this for a week now and I haven't been able to make any progress.  One thing that I think might be causing this problem is the fact that Im running this locally instead of on the server.  Does this request need to come from the address that is listed in the "referer" in the browser key?</p>
  
  <p>Thanks again!</p>