1

I'm trying to send a POST request at Firebase via HTTP, either in code or with the REST Debugger, but it returns an error:

HTTP/1.1 401 The request was missing an Authentification Key (FCM Token). Please, refer to section "Authentification" of the FCM documentation, at https=//firebase.google.com/docs

image

image

Using the Postman extension from Chrome, it works.

image

This is the code:

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  IdHTTP, IdIOHandler, IdIOHandlerStream,
  IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdSSLOpenSSLHeaders_Static,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo,
  IdGlobal, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdServerIOHandler, IdCoderMIME;
begin
  try
    IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    IdIOHandler.ReadTimeout := IdTimeoutInfinite;
    IdIOHandler.ConnectTimeout := IdTimeoutInfinite;
    IdHTTP := TIdHTTP.Create(nil);
    try
      idHttp.Request.Clear;
      idHttp.Request.CustomHeaders.Clear;
      idHttp.Request.ContentType := 'application/json';
      idhttp.Request.Charset := 'UTF-8';
      IdHTTP.IOHandler := IdIOHandler;
      IdHTTP.ReadTimeout := IdTimeoutInfinite;
      IdHTTP.Request.Connection := 'Keep-Alive';
      IdIOHandler.SSLOptions.Method := sslvSSLv23;
      IdHTTP.Request.Method := 'POST';
      IdHTTP.Request.CustomHeaders.Values['Authorization:key'] := 'AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';
      jsonString := '{"to" : "APA91bFJSdGW_yrX7p_TNKZ4k0OpdXTQM6xdd7BUsslk6zSvZlBmoAnfvyX-nBm4DYY-xxxxx......",' +
                    '"data" : {' +
                    '"Nick" : "Teste de Push",' +
                    '"body" : "Corpo do push",' +
                    '"Room" : "Apenas um teste"' +
                    '},}';
      JsonToSend := TStringStream.Create(jsonString);
      try
        response := IdHTTP.Post('https://fcm.googleapis.com/fcm/send', JsonToSend);
        response := response.Replace(Char(#10), '');
      except
        on E:EIdHTTPProtocolException do
        memo1.Lines.Insert(0, e.ErrorMessage);
      end;
      memo1.Lines.Insert(0, response);
    finally
      IdHTTP.Free;
    end;
  finally
    IdIOHandler.Free;
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
NetNúcleo
  • 33
  • 1
  • 3
  • 2
    I'm voting to close this question as off-topic because it is not written in English and this is an English language site. Please ask your question at http://pt.stackoverflow.com/ insteadl – Ken White Feb 22 '17 at 13:21
  • Post em PT: http://pt.stackoverflow.com/questions/185965/delphi-google-firebase-http – NetNúcleo Feb 22 '17 at 14:09
  • Device-to-device message sending is not possible without the use of a server. – mjn Feb 22 '17 at 16:20
  • see https://stackoverflow.com/questions/38432243/how-to-send-device-to-device-notification-by-using-fcm-without-using-xmpp-or-any?noredirect=1&lq=1 – mjn Feb 22 '17 at 16:33
  • It is not device-to-device. It is a desktop application that sends the http request to Firebase. When I use curl, it works. curl --header "Authorization: key=$api_key" \ --header Content-Type:"application/json" \ https://fcm.googleapis.com/fcm/send \ -d "{\"registration_ids\" :[\"APA91bFJSdGW_yrX7p_TNKZ4k0OpdXTQM6xdd7BUsslk6zSvZlBmoAnfvyX-....xxxxxxx\"]}" \ {"data" : { \ "Nick" : "Teste de Push", \ "body" : "Corpo do push", \ "Room" : "Apenas um teste" \ },} – NetNúcleo Feb 22 '17 at 17:28
  • Hint: if you embed the [server key](https://firebase.google.com/docs/cloud-messaging/server) in a desktop application (or in an app), it may be extracted and misused. The server key should only be used on the app server in a secure environment (vault). – mjn42 Feb 23 '17 at 09:20

1 Answers1

9

Your Delphi code is not assigning the Authentication request header correctly. You need to change this:

IdHTTP.Request.CustomHeaders.Values['Authorization:key'] := 'AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

To this instead:

IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'key=AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

You should set the IdHTTP.Request.BasicAuthentication property to false as well.

Aside from that, since you are setting the Request.Charset property to UTF-8, you should construct the TStringStream to match:

JsonToSend := TStringStream.Create(jsonString, TEncoding.UTF8);

With that said, try the following code:

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo,
  IdGlobal, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL
  {$IFDEF IOS}
  , IdSSLOpenSSLHeaders_Static
  {$ENDIF}
  ;

...

begin
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdIOHandler.SSLOptions.Method := sslvSSLv23;
    IdHTTP.IOHandler := IdIOHandler;

    IdHTTP.Request.ContentType := 'application/json';
    IdHTTP.Request.Charset := 'UTF-8';
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'key=AAAAYsnMbsY:APA91bEjYZK-xxxxxxx......';

    jsonString := '{"to" : "APA91bFJSdGW_yrX7p_TNKZ4k0OpdXTQM6xdd7BUsslk6zSvZlBmoAnfvyX-nBm4DYY-xxxxx......",' +
                   '"data" : {' +
                   '"Nick" : "Teste de Push",' +
                   '"body" : "Corpo do push",' +
                   '"Room" : "Apenas um teste"' +
                   '},}';
    JsonToSend := TStringStream.Create(jsonString, TEncoding.UTF8);
    try
      response := IdHTTP.Post('https://fcm.googleapis.com/fcm/send', JsonToSend);
      response := response.Replace(#10, '');
    except
      on E: EIdHTTPProtocolException do
        response := e.ErrorMessage;
    end;
    Memo1.Lines.Insert(0, response);
  finally
    IdHTTP.Free;
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770