80

I'm trying to test out Firebase Cloud messaging APIs as all functionality is not available from console (notably customization of notifications when app is in background). But for some reasons, I cannot get it to work, and it always shows up 401 error. I investigated the reasons for this, and tried it after regenerating new server key, but the error remains constant. Surprisingly, when I generated a new server key, it is not reflected in Firebase console and it shows server key as empty. Also, I tried adding my IP address to the server whitelist IPs but still no luck. I've attached a screenshot of a request that I did with Postman (I substitue the server key in place of serverKey.

I'm stuck on this for a few hours and would really appreciate some help.enter image description here

gaurav jain
  • 3,119
  • 3
  • 31
  • 48
  • Try to generate a new key and pay attention to set: key-type=server (no android or ios or browser) and ip-whitelist= leave it empty (this will allow all the ips) – Diego Giorgini Jun 04 '16 at 19:26
  • I generated a new key again, type is server. Left ip-whitelist empty. Still same result :(. Just wanted to know that if there's any mistake in how I'm making the request? – gaurav jain Jun 04 '16 at 20:10
  • The request looks ok. Maybe try using curl and post the full output of the request&response. If you cannot find a solution please contact Firebase Support: https://firebase.google.com/support/contact/bugs-features/ – Diego Giorgini Jun 04 '16 at 20:56
  • Thanks Diego, I deleted the earlier comment, because I didn't send any notification payload in the request hence no notification came in emulator, so it was my mistake. I will re-try and post the results again here. – gaurav jain Jun 05 '16 at 04:26
  • Great! so the 401 was an issue with postman. Regarding the emulator, check if your app can obtain a device token. If it does then it should be able to receive the message – Diego Giorgini Jun 05 '16 at 04:27
  • I tried again. When app is in foreground, I got the notification to work and got a callback in onMessageReceived. When it's in background I didn't get any callback in onMessageReceived, though I received the notification. So at the end, using curl gives me same behavior as the console. Any ideas? Thanks for your help. – gaurav jain Jun 05 '16 at 05:38
  • Check out my answer to this other question: http://stackoverflow.com/a/37626817/613115 ("Full explanation" part) – Diego Giorgini Jun 05 '16 at 05:41
  • Great!, thank you so much. I forgot that it'll work only for data-only messages in case of background. So the problem is resolved. – gaurav jain Jun 05 '16 at 05:48

10 Answers10

248

I don't know if someone uses the [Web API Key] as the [YOUR_SERVER_KEY] for POSTMAN test and keep getting '401 Error'. [Web API Key] is not [YOUR_SERVER_KEY].

You should go to your Firebase console and check this:

to get the correct Server key.

Hope it help.

S1ngoooor
  • 2,567
  • 2
  • 11
  • 13
  • I'm trying using the server key but it keeps on throwing the error `invalid token` can somebody tell me what is it that I'm doing wrong – Gardezi Oct 02 '17 at 16:14
38

I noticed from your screenshot that you were using "key: serverKey". Could you try using "key=serverKey" instead?

Also you don't need to have "POST fcm.googleapus.com/fcm/send"; this is not proper json and would explain the error you are seeing. The URL of the request is already defined elsewhere so remove it from the payload.

Arthur Thompson
  • 9,087
  • 4
  • 29
  • 33
  • 1
    Ì get this result : JSON_PARSING_ERROR: Unexpected character (P) at position 0. – gaurav jain Jun 08 '16 at 09:32
  • Could you add the json payload to your answer so the full text of the json is visible? – Arthur Thompson Jun 08 '16 at 13:22
  • 1
    You don't need to have "POST https://fcm.googleapus.com/fcm/send" this is not proper json and would explain the error you are seeing. The URL of the request is already defined elsewhere so remove it from the payload. – Arthur Thompson Jun 08 '16 at 13:39
  • Hi Arthur, your above comment solves the problem. Would be happy if you add it to the answer so that I can accept it. Thanks. – gaurav jain Jun 09 '16 at 07:15
  • Hi @ArthurThompson, is this valid for getting the json that we put into the database and retrieving it through a GET request? I am trying to do so passing an `Authorization: Bearer xxx` as per the website documentation (https://firebase.google.com/docs/reference/rest/database/user-auth) under Using the access token, but no luck. Still getting a `"Unauthorized request."`. – Edison Spencer Jun 19 '17 at 21:14
20

I faced the same problem.

the problem was that I was using the legacy server key. when I used the new version of the server key the problem solved.

in your firebase console goto settings -> cloud messaging

then use the new server key. it is longer than the old version key.

Karim
  • 390
  • 4
  • 17
19

go to https://console.firebase.google.com/u/0/project/[project-name]/settings/cloudmessaging/

Project credentials

you can use Server Key or Legacy server key

Omar Makled
  • 1,638
  • 1
  • 19
  • 17
  • 4
    I was make a mistake by using "Web API Key". There are so many credentials which make me confuse – Harun Dec 17 '18 at 09:09
2

I too am facing the Same problem... I am using curl in php for posting and it works only if I have php files stored on my LocalHost server. When I try to use access the files via a free hosting online, then it say Unautorized 401.

So I would suggest if you can, use the Localhost.

  • P.S. In FCM there is a method of allowing multiple access clients like Goolge Chrome or android client or etc. I am trying to figure out If that's what's giving the error of Unauthorized, may be we will have to list Chrome or any browser as a user client in our FCM Console project. – Sugam Mankad Jun 10 '16 at 05:59
  • 9
    Just Solved the problem for me, I changed the Server API Key, which is given on the Cloud messaging tab, in FCM Console. In Project Overview, Manage, there is the Cloud Messaging tab, it shows a SERVER API KEY use that may be. – Sugam Mankad Jun 10 '16 at 06:42
  • 1
    Second comment did the trick for me; if you follow the [official FCM docs](https://firebase.google.com/docs/server/setup) they direct you to click on ' -> Permissions -> Service Accounts' and then create a new Service Account for your server. That will download a `.json` file containing a key, however **the key inside does not allow API access**. Clicking 'Manage -> Cloud Messaging' will deliver the correct API key. Ignore the official docs if you want FCM to work. – aroth Jul 25 '16 at 00:40
  • 1
    API key was wrong. I was using one created on the developer console. Turns out the key is at console.firebase.google.com > gear icon > general > cloud messaging tab. – black Aug 22 '16 at 14:26
1

I have the same problem at Server Side Code(C#).

You basically used wrong Server Key (or API Key) for service side code.

Follow below Link over stackoverflow posted by me (Helpful to find Server Key (or API Key) )

FCM (Firebase Cloud Messaging) Push Notification with Asp.Net

Community
  • 1
  • 1
Nilesh
  • 1,013
  • 14
  • 21
1

401 with FCM through HTTPv1 (Error and Solution for Bearer)

If you are using FCM via HTTP v1, then you will have to make two sucessive POST requests:

1/ In the first call, you make a POST request to 'https://accounts.google.com/o/oauth2/token' (or using API packages) using your firebase service account key at 'https://console.firebase.google.com/u/0/project/{{firebaseProjectName}}/settings/serviceaccounts/adminsdk'
to get the access token.

2/ Then you have to make another POST request to 'https://fcm.googleapis.com/v1/projects/{{firebaseProjectName}}/messages:send'. If you have followed the steps for the migration from legacy HTTP to HTTP v1 (very clear documentation) on firebase website, you have to make some small changes at the content of the post request and also using 'Bearer ${accessToken.data}' for the Authorization.

In my case I was not properly awaiting for the accessToken in the first function (forgot the 'await' keyword in front of the function making the post request and AndroidStudio did not notice either that there was something wrong).

Make sure that you await the result of the first post request as it is a Future.

If you don't, Bearer will be null when you make the second POST request because you did not await for it.

Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
  • Thanks! This helped a lot (the migration docs link). I am new to this (implementing push) and was trying to implement HTTPv1 straight as advised by Google, but that documentation is rubbish - the migration one actually has a lot more about HTTPv1 than the HTTPv1 on its own – Imre Nov 26 '22 at 21:02
0
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.Size;

public class PushNotificationSubmit {

    public static void main(String[] args) {
        new PushNotificationSubmit().send("sample message title", "sample message body");
    }

    final String serverKey = "AAAA_*******";
    final String fcmUrl = "https://fcm.googleapis.com/fcm/send";

    /**
     * note from google: The value should be an array of registration tokens to which to send the multicast message. The array must contain at least 1 and at most 1000 registration tokens.
     * send to specific users
     *
     * @param messageTitle
     * @param messageBody
     * @param tokenList
     */
    @Size.List({@Size(min = 1), @Size(max = 999)})
    public void send(String messageTitle, String messageBody, List<String> tokenList) {
        try {
            String payloadJson = createMessageAsJson(messageTitle, messageBody, tokenList);
            doSend(payloadJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * send to all users that registered in my topic
     *
     * @param messageTitle
     * @param messageBody
     */
    public void send(String messageTitle, String messageBody) {
        try {
            String payloadJson = createMessageAsJson(messageTitle, messageBody, null);
            doSend(payloadJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String createMessageAsJson(String messageTitle, String messageBody, List<String> tokenList) {
        JSONObject payloadObj = new JSONObject();
        try {
            JSONObject notifyObj = new JSONObject();
            notifyObj.put("title", messageTitle);
            notifyObj.put("body", messageBody);
            payloadObj.put("notification", notifyObj);

            if (tokenList != null) {
                if (tokenList != null && tokenList.size() > 0) {
                    JSONArray regId = new JSONArray();
                    for (int i = 0; i < tokenList.size(); i++) {
                        regId.put(tokenList.get(i));
                    }
                    payloadObj.put("registration_ids", regId);
                }
            } else {
                payloadObj.put("to", "/topics/all");
            }

            return payloadObj.toString();
        } catch (Exception e) {
            // TODO: add logger
            e.printStackTrace();
            throw e;
        }
    }

    private void doSend(String payloadJson) throws Exception {
        HttpClient httpclient = HttpClientBuilder.create().build();
        try {
            HttpPost httpPost = new HttpPost(fcmUrl);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Authorization", "key=" + serverKey);
            httpPost.setEntity(new StringEntity(payloadJson, "UTF-8"));

            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();

            System.out.println("push notification status: " + response.getStatusLine());
            EntityUtils.consume(entity);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }
}
M.Namjo
  • 374
  • 2
  • 13
0

In C# HttpClient response

For wrong server key it will happen, Invalid Key, Unauthorize, 401

-1

I was facing the same problem, i solved it by using the following steps

1- In the server from where you are sending push, Use the browser key only, you can get it from Firebase console or google api console as I have highlighted in the below images:-

Google api console

Firebase console, click on the project-->settings

Note : The Firebase console web api key and google console browser key are the same you can use either of them

enter image description here

enter image description here

2- If you follow the first step only you will get the Unauthorized error, to resolve this you need to authorize your browser key in google console by adding your server IP address from where you will send the push. Click on the edit pencil icon on the right side of your browser key in google api console, above first image

enter image description here

After adding your Ip address click save Make sure that your device token is not empty on which you are sending the push, I hope your push will be sent successfully now.

Mehroz Munir
  • 2,248
  • 1
  • 18
  • 16
  • please comment for your downvoting – Mehroz Munir Dec 18 '16 at 04:30
  • 1
    The Frebase console is not the same as Google console browser key. In fact as part o the Firebase documentation they advise you to use ONLY the key in Firebase console and not any other key – Nik Dec 18 '16 at 05:49