bytefish / FcmSharp

Firebase Cloud Messaging (FCM) with .NET
MIT License
6 stars 7 forks source link

Recognizing expired tokens #29

Closed roelspruit closed 5 years ago

roelspruit commented 6 years ago

Hi,

I'm using this library to send notifications via firebase. I am storing tokens of users in a database and using these tokens as input for FcmSharp. However, these tokens can expire (see https://firebase.google.com/docs/cloud-messaging/http-server-ref#error-codes)

Is there a way to recognize these expired tokens? As far as I can see FcmSharp does not pass this information back to the client. I think it only throws exceptions when firebase does not return a 200 HTTP status code. In this case, firebase WILL return 200 OK but will also return an error code (at least this is what the FB documentation says)

bytefish commented 6 years ago

Whenever a new Token is generated the onNewToken method is called in the client. From there, just send the updated token to the Database:

bytefish commented 6 years ago

Sorry, I didn't want to close the issue. You are also refering to the old legacy protocol. Actually this protocol is used: https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages.

bytefish commented 6 years ago

These are the errors, that can happen when sending a message:

These errors can be found in the Errors property of the FcmMessageException, when sending a message fails. When a registration token is invalid (invalid-registration-token), then you should remove it from your server.

bytefish commented 6 years ago

As for the error model, I simply put a IDictionary<string, object> as the error, just because I don't know what Google wants an error to look like. I know this isn't very convenient, so feel free to improve the library, if you find it out. ✌️

roelspruit commented 6 years ago

Thank you very much for your responses. My apologies for linking to the wrong protocol. I do still have some strange cases though. For instance, if I create a wrong token (use a correct one and replace some random characters) the library (and I guess firebase itself) still responds as though it succeeds. I would expect an error or an exception to happen in that situation.

bytefish commented 6 years ago

It would be great, if you could produce a minmal test to reproduce the behavior or describe, what's the easiest way to reproduce it. I could for use the Android sample application for example and modify the Registration tokens, to see if messages are reported as delivered for wrong tokens.

Would this work?

Please do not post any credentials.

sir-boformer commented 6 years ago

The Dictionary<string, object> is really inconvenient to work with.

bytefish commented 6 years ago

In the errors? I think so too. But back when I wrote it I had no idea about the possible errors... so I pushed it on the library user. 🤥 Do you know how to safely deserialize Firebase errors into something type-safe?

sir-boformer commented 6 years ago

Seems like the response always looks like this:

{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "errors": [
      {
        "message": "Requested entity was not found.",
        "domain": "global",
        "reason": "notFound"
      }
    ],
    "status": "NOT_FOUND"
  }
}
public class FirebaseErrorResponse
{
    [JsonProperty("code")]
    public int Code { get; set; }

    [JsonProperty("message")]
    public string Message { get; set; }

    [JsonProperty("errors")]
    public List<Error> Errors { get; set; }

    [JsonProperty("status")]
    public string Status { get; set; }

    public class Error
    {
        [JsonProperty("message")]
        public string Message { get; set; }

        [JsonProperty("domain")]
        public string Domain { get; set; }

        [JsonProperty("reason")]
        public string Reason { get; set; }
    }
}

Seems to be a Google standard: https://developers.google.com/search-ads/v2/standard-error-responses

Just in case, it would be nice to have access to the raw response (string).

bytefish commented 6 years ago

I can add the Error Response model, but you can also do it. 😎 Please feel free to also make a Pull Request. I wonder: On which HTTP Status Code are these Errors thrown? What is returned on a 401? What is returned on a HTTP Status Code 500?

sir-boformer commented 6 years ago

I think these are always thrown, no matter which status code. The Code field is also the status code.

bytefish commented 5 years ago

There are no news from my side on this. The Firebase documentation is sparse on this and I don't know the exact error codes. That's why I only pass a Dictionary back to the user and expect them to handle the response, e.g. expired tokens,

While I know this is not a beauty of an API surface, I don't have the time to dig deeper into the docs.

Sorry!