GCM giving error: (401) Unauthorized - c#

I am trying to write the web api in c# to send push notification in android device. which is giving me the 401 unauthorized error. i have follow all the step to send the notification. i am not able to understand why i am not authorize user.
here is my function to send notification.
public String Post(string message, string regId)
{
try
{
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/json";
tRequest.Headers.Add(string.Format("Authorization: key=**server-api-key**"));
tRequest.Headers.Add(string.Format("Sender: id=**sender-id**"));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message="
+ message + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + regId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
tReader.Close();
dataStream.Close();
tResponse.Close();
return sResponseFromServer;
}
catch (Exception e)
{
throw;
}
}
Get the api key from
server key 1
and sender id from
Project number
My post function accept the message and regId which is device id.

I don't know C# and may be missing something. It looks like your post data is not in JSON format. I don't see any braces. This SO question has examples of how to post JSON-formated data.
Also, try validating your API key using curl as explained in this example.

Related

Firebase integration with C#

string RegId = "************";
string ApplicationID = "*****";
string SENDER_ID = "***";
var value = "sandeepweb"; //message text box
WebRequest tRequest;
tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send"); tRequest.Method = "post";
tRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", ApplicationID)); tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
//Data post to the Server
string postData =
"collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message="
+ value + "&data.time=" + System.DateTime.Now.ToString() +
"&registration_id=" + RegId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse(); dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd(); //Get response from GCM server
tReader.Close(); dataStream.Close();
tResponse.Close();
lblsuccess.Text = sResponseFromServer;
App Crashes When i send any notification. Notifications are sent from Firebase console. Do I need to make some changes in above code?
You can use FireSharp. it uses Firebase REST API behind the scenes and make your queries easy and felxible. You dont have to deal with a large messy code
Push Example:
var todo = new Todo {
name = "Execute PUSH",
priority = 2
};
PushResponse response =await _client.PushAsync("todos/push", todo);
response.Result.name //The result will contain the child name of the new data that was added

Push notification Chrome Mobile Ver 42+

I am trying a demo of push notification suggested by this article.
https://developers.google.com/web/updates/2015/03/push-notificatons-on-the-open-web?hl=en
and trying to run code from github https://github.com/GoogleChrome/samples/tree/gh-pages/push-messaging-and-notifications
As per instruction I have done following things -
1. Created project on google developer console.
2. Added browser application key in to config.js > gcmAPIKey :'browser api key'
3.Added gsm_sender_id :'Project number' into manifest.json
4. Hosted application on https://somedomain.com
and result is this
Whenever I click on SendPushMessage button it doesn't show any notification. While debugging, I found that this request get fired
https://xxsomedomainxxx.azurewebsites.net/api/get/?subscriptionId=APA91bE_xyl2sP8l1pa8j4n84VGfJgKVb28I0DJK5qo9zUVLy0ZSRsyl2BbjLDSZ-Y625LqsmMp3rIH4PW3s1v_ccBOdCbWYsxaF525FHRbx5odr-z1a1uPrP4zqy4DFlKkwa9pyHhkdxL0ggxGBbC_bB6LTZSDuTKlDeXTRhywcY9X5KxBXrxhS_4M8oJFUi3eW6FikEUiJ
As per my observation I need to catch substriptionId on server and need to do something with it. So what kind of code should I need to write on server for below API
https://xxsomedomainxxx.azurewebsites.net/api/get/
I have created one WCF REST service with following code and its sending notification to android chrome 42+.
But one problem is here, notification shows message from service-worker.js file, not from in this code
var value = "Hello from server";
. I am working on it and update this answer soon.
Please update this function in main.js file
function getNotification(subscription) {
navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function (subscription) {
console.log('getNotification', subscription)
fetch('/pushnotificationservice.svc/sendnotification?key=' + subscription.subscriptionId).then(function (obj) {
console.log('getNotification', obj)
});
});
});
WCF Service Code
public string SendNotification(string key)
{
ServiceData myServiceData = new ServiceData();
try
{
string GoogleAppID = "2440XXXXXXXX";//put your project number here
string redId = key;
var SENDER_ID = "youremail#gmail.com";//I haven't tried with another junk value
var value = "Hello from server";//this message do not displayed in notification
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", "Your browser key"));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + key + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
tReader.Close();
dataStream.Close();
tResponse.Close();
return sResponseFromServer;
}
catch (FaultException fex)
{
myServiceData.Result = false;
myServiceData.ErrorMessage = "unforeseen error occurred. Please try later.";
myServiceData.ErrorDetails = fex.ToString();
throw new FaultException<ServiceData>(myServiceData);
}
}

GCM Using JSON to send to multiple RegistrationIDs : No notification arrives

I'm using Android Google Cloud Messaging to send notifications to a device, with c#.net. I got the API Key, RegistrationID and senderID ( Well first method worked no there's nothing wrong with the configuration of GCM).
Here's the first method where I want to send the message to just 1 registrationID(check postData, i'm not using Json):
public void SendPushNotification(string regID, string message)
{
{
string GoogleAppID = "APIKey";
var SENDER_ID = "SenderID";
var value = message;
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", GoogleAppID));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + regID + "";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
HttpWebResponse httpResponse = (HttpWebResponse)tResponse;
string statusCode = httpResponse.StatusCode.ToString();
tReader.Close();
dataStream.Close();
tResponse.Close();
}
catch {
throw new WebFaultException<string>("Error", HttpStatusCode.ServiceUnavailable);
}
So when calling it, the device successfully receives the message.
Here's my second method, where I use Json format to send to multiple IDs:
(Note that the procedure doesn't take registrationID as a parameter because I added it to the list i declared in the code)
public void SendPushNotification(string message)
{
string stringregIds = null;
List<string> regIDs = new List<string>();
//Here I add the registrationID that I used in Method #1 to regIDs
//Then I use
stringregIds = string.Join("\",\"", regIDs);
//To Join the values (if ever there are more than 1) with quotes and commas for the Json format below
try
{
string GoogleAppID = "APIKey";
var SENDER_ID = "SenderID";
var value = message;
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", GoogleAppID));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
string postData = "{\"collapse_key\":\"score_update\",\"time_to_live\":108,\"delay_while_idle\":true,\"data\": { \"message\" : "+"\""+value+"\",\"time\": "+"\""+System.DateTime.Now.ToString()+"\"},\"registration_ids\":[\""+stringregIds+"\"]}";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
HttpWebResponse httpResponse = (HttpWebResponse)tResponse;
string statusCode = httpResponse.StatusCode.ToString();
tReader.Close();
dataStream.Close();
tResponse.Close();
}
catch {
throw new WebFaultException<string>("Error", HttpStatusCode.ServiceUnavailable);
}
The Method doesn't give any errors or anything but the notification doesn't arrive in the device. (I console.writelined postData and it's the same format of http://developer.android.com/google/gcm/http.html
So I don't really know what to fix, it would be really easier to send notifications to users at the same time not just send 1 to each User every X seconds.
Thanks.
Changing
Request.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
to
Request.ContentType = "application/json";
Does answer the question.
He is providing JSON data where he has explicitly implied quite the opposite.
The HTTP header must contain the following headers:
Content-Type: application/json for JSON;
application/x-www-form-urlencoded;charset=UTF-8 for plain text.
See: https://developer.android.com/google/gcm/http.html
Use
Request.ContentType = "application/json";
Replace this line:
Request.ContentType = "application/json";

Push notifications -Error - Missing Registration

I have sent push notification using ASP.net C# by GCM to android mobiles.
But I tried different kinds of code but all arr return Missing Registration error, So please help me.
try PushSharp. it's pretty straightforward.
and check this instruction - How to Configure & Send GCM Google Cloud Messaging Push Notifications using PushSharp
var push = new PushBroker();
//Registering the GCM Service and sending an Android Notification
push.RegisterGcmService(new GcmPushChannelSettings("theauthorizationtokenhere"));
//Fluent construction of an Android GCM Notification
//IMPORTANT: For Android you MUST use your own RegistrationId here that gets generated within your Android app itself!
push.QueueNotification(new GcmNotification().ForDeviceRegistrationId("DEVICE REGISTRATION ID HERE")
.WithJson("{\"alert\":\"Hello World!\",\"badge\":7,\"sound\":\"sound.caf\"}"));
You can install it via nuget.
public class GCMSNS
{
public static string SendGCMNotification(string deviceId, string message)
{
string GoogleAppID = "XYxxxxxxxxxxxxxxxxxxxx";//This is API Key Server
var SENDER_ID = "11111111111111"; //This is Google Project Id
var value = message;
WebRequest tRequest;
tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", GoogleAppID));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" +
System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
StreamReader tReader = new StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
tReader.Close();
dataStream.Close();
tResponse.Close();
return sResponseFromServer;
}
}

Unauthorized when calling Google GCM

I trying to use Google GCM for sending push notifications. But get a WebException that says that the remote server returns 401 unautorized. I can't foung why it doen't work.
Anyone that knows why it doesn't work?
Here is my code:
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
Request.Method = "POST";
Request.KeepAlive = false;
string postData = "{ 'registration_ids': [ '"+registrationId+"' ], 'data': {'message': '"+message+"'}}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
Request.ContentType = "application/json";
//Request.ContentLength = byteArray.Length;
//Request.Headers.Add(HttpRequestHeader.Authorization, "GoogleLogin auth=" + AuthString);
Request.Headers.Add(HttpRequestHeader.Authorization, "Authorization: key=AIzaSyCEygavdzrNM3pWNPtvaJXpvW66CKnjH_Y");
//-- Delegate Modeling to Validate Server Certificate --//
//-- Create Stream to Write Byte Array --//
Stream dataStream = Request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//-- Post a Message --//
WebResponse Response = Request.GetResponse();
HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
{
var text = "Unauthorized - need new token";
}
else if (!ResponseCode.Equals(HttpStatusCode.OK))
{
var text = "Response from web service isn't OK";
}
StreamReader Reader = new StreamReader(Response.GetResponseStream());
string responseLine = Reader.ReadLine();
Reader.Close();
Daniel - Dude there is an issue with the GCM documentation ! Use Browser key as the authorization key at the place of Server API key . It will work.
OK, i am just shooting in the dark here. Take a look at this line:
Request.Headers.Add(HttpRequestHeader.Authorization, "Authorization: key=AIzaSyCEygavdzrNM3pWNPtvaJXpvW66CKnjH_Y");
Shouldn't it be:
Request.Headers.Add(HttpRequestHeader.Authorization, "key=AIzaSyCEygavdzrNM3pWNPtvaJXpvW66CKnjH_Y");
Since you're telling it this is a Authorization header, there's no need to add 'Authorization: ' again, does it?
Also, make sure the string constant 'HttpRequestHeader.Authorization' is 'Authorization'.

Categories