Search code examples
c#firebasefirebase-authenticationfirebase-cloud-messaginghttpwebrequest

Firebase 403 Forbidden Error on attempting to send Push Notification


I have a fully working Legacy HTTP Request:

HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.PreAuthenticate = true;
httpWebRequest.Headers.Add("Authorization", "key=" + key);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string message = "{\"to\":\"" + token.ToString() + 
        "\",\"notification\":{\"body\":\"" + body.ToString() +
        "\",\"title\":\"" + title.ToString() + "\"}," + 
        "\"data\":{\"key\":\"" + dataKey.ToString() + 
        "\",\"value\":\"" + dataValue.ToString() + "\"}}";

    streamWriter.Write(message);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    name = streamReader.ReadToEnd();
}

I am trying to migrate to the latest:

string uri = String.Format("https://fcm.googleapis.com/v1/projects/{0}/messages:send?access_token={1}&key={2}&alt=json", project, AccessToken, key);
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.Accept = "application/json";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string message = "{\"validateOnly\":true," +
        "\"message\":{" +
            "\"token\":\"" + token.ToString() + "\"," +
            "\"notification\":{" +
                "\"body\":\"" + body.ToString() + "\"," +
                "\"image\":\"" + image.ToString() + "\"," +
                "\"title\":\"" + title.ToString() + "\"" +
                "},\"data\":{" +
                "\"key\":\"" + dataKey.ToString() + "\"," +
                "\"value\":\"" + dataValue.ToString() + "\"" +
                "}" +
            "}" +
        "}";
    streamWriter.Write(message);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    name = streamReader.ReadToEnd();
}

But on GetResponse I receive The remote server returned an error: (403) Forbidden. I was prior getting a 401 error (Unauthorized) but that was because I wasnt using the correct access key, I am now and am authorized using this:

var scopes = new[] { "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/firebase.database" };

GoogleCredential credential;
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
    credential = GoogleCredential.FromStream(stream).CreateScoped(scopes);
}
AccessToken = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
return AccessToken;
}

I'm really not sure what I am missing, I have all the Google Cloud APIs necessary enabled for this project.


Solution

  • Add another scope to the oauth method. "https://www.googleapis.com/auth/firebase.messaging" seems straight forward now, but there is no place for this c# post in its entirety. Hopefully this helps someone else with this approach.

    var scopes = new[] { "https://www.googleapis.com/auth/firebase.messaging", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/firebase.database" };
    
    GoogleCredential credential;
    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        credential = GoogleCredential.FromStream(stream).CreateScoped(scopes);
    }
    AccessToken = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();