Jump to content
Vanar

Authorization to the firebase's https://iid.googleapis.com/iid/v1:batchImport

Recommended Posts

I always received FDeviceToken from the request https://iid.googleapis.com/iid/v1:batchImport


HTTP HEADERS: 
    Content-Type: application/json 
    Authorization: key=YOUR_SERVER_KEY 
BODY: 
    { 
    "application": "com.company.app", 
        "sandbox":true, 
        "apns_tokens":[ "7c6811bfa1e89c739c5862122aa7ab68fc4972dea7372242f74276a5326f...." ] 
        } 

 

Answer: 
        { "results": 
        [ { 
          "registration_token": "ejXQlECjCeI:APA91bE7oaUhaFnGyl77lFrySdEaWxocM0oj81uNezACX1wsZXiTyL4OYo5ssvFjjWYpFymMVyqBccboVcwTTW2rvykOmV_CABDM7rTIRCiJFl_9ngf7SrDSYoFouwNj69JSwlH.....",
                  "apns_token": "7c6811bfa1e89c739c5862122aa7ab68fc4972dea7372242f74276a5326f....",
                  "status": "OK"
                  }
                ]
        }

 

But recently this request stopped working (authorization required).

I get the answer:
    { "error": "Not authenticated or unauthorized"}

 

How to solve this problem?
How to rewrite the query?

 

Most likely it is related to this

5413367030758891349.thumb.jpg.a6547273a8370f991aa7a7de1ae21c60.jpg

Share this post


Link to post
On 10/14/2024 at 9:37 PM, Dave Nottage said:

See this documentation. Authorization is now via an OAuth2 token - there is a link in the documentation to details about methods for obtaining the token. 

Dave,
I'm trying Kastri now. Again 🙂

One thing I must do is download a copy of firebase.zip (SDK for iOS) from github. But both 11.2.0 as 11.3.0 give me an error when I try to unzip them: Invalid Zip-file. Tried on both win10 and win11.
I tried to ask a question in the issues section of this github-repo, but my question does not appear in the discussion. Dunno why, no error reported.
So I'm trying here: do you know an alternative to download this firebase.zip?
Thanks,

John

 

Share this post


Link to post
36 minutes ago, John van de Waeter said:

So I'm trying here: do you know an alternative to download this firebase.zip?

There's this link at this page, however it might just be a redirect to the latest version (11.3.0)

 

I notice a huge difference in size between 11.2.0 and 11.3.0 - 319MB vs 612MB!!

Share this post


Link to post
6 hours ago, John van de Waeter said:

Yep, lots of other code in this file. But it contains the original firebase.zip, which in turn has the same problem....

Both unzip OK on macOS, so I tried to "re-zip" the 11.2.0 version on Windows, but that causes Explorer to crash 😞

 

I've asked a question about it in their Slack workspace, since all the other reporting mechanisms don't seem to cover this category.

Share this post


Link to post
On 10/14/2024 at 5:28 PM, John van de Waeter said:

Hi Vanar,
I'm facing the same problem... did you find a solution?

cheers, John

 

Hi, John
I didn't find a normal solution
I temporarily solved the problem like this:
They give me a ready-made authorization key: ya29.c.c0ASRK0Ga_4Z1QIYsqufOCVdT ...., created on the server using PHP
And I slip it into my request ...

Share this post


Link to post
12 minutes ago, Vanar said:

Hi, John
I didn't find a normal solution
I temporarily solved the problem like this:
They give me a ready-made authorization key: ya29.c.c0ASRK0Ga_4Z1QIYsqufOCVdT ...., created on the server using PHP
And I slip it into my request ...

Lol....
I too had a hard fight to send those notifications to the v1-google fcm server.... I never realized that the converting part (apns->fcm) also required this new approach...


Having apps online that suddenly don't receive pn's anymore forces one to be creative....

I'm now trying the Kastri-path.

Share this post


Link to post

Hi,


i was facing with the same problem...
This is my workable solution, in short 🙂 

 

uses System.Net.HttpClient, JOSE.Core.Builder, JOSE.Core.JWT, JOSE.Core.JWA, JOSE.Types.Bytes, JOSE.Types.JSON, JOSE.Signing.RSA, JOSE.Core.JWK
JOSE is taken from https://github.com/paolo-rossi/delphi-jose-jwt  

Info:
FGoogleProjectID :  is your project ID like 'name-95dc3e3' (console.cloud.google.com)
FGoogleServiceEmail: like 'firebase-adminsdk-9tm7h@XXXXXXXX.iam.gserviceaccount.com'
FGoogleServicePrivateKey: '-----BEGIN PRIVATE KEY-----...' taken from the JSON file when you create a key for a Google service account (you need to remove the \n characters from the key)


function CreateGoogleTokenString: String;
begin
  Result := '';
  var JWToken: TJWT := TJWT.Create(TJWTClaims);
  try
    try
      JWToken.Claims.Issuer := FGoogleServiceEmail; 
      JWToken.Claims.SetClaim('scope', 'https://www.googleapis.com/auth/firebase.messaging');
      JWToken.Claims.Audience :='https://oauth2.googleapis.com/token';
      JWToken.Claims.IssuedAt := Now;
      JWToken.Claims.Expiration := IncMinute(Now, 60);  // not more than 60
      var AJWKKey: TJWK := TJWK.Create(FGoogleServicePrivateKey); 
      var LSignature: TJOSEBytes := TJOSE.SerializeCompact(AJWKKey, TJOSEAlgorithmId.RS256, JWToken);
      Result := LSignature.AsString;
    except
      on e: exception do
        raise Exception.Create('Error creating Google Token String: ' + E.Message);
    end;
  finally
    FreeAndNil(JWToken);
  end;
end;

function GetOAuthToken: String;
var
  LResponse: IHTTPResponse;
  LFormUrlencoded: TStringList;
  LRequest: THTTPClient;
begin
  Result := '';
  LRequest := THTTPClient.Create;
  LFormUrlEncoded := TStringList.Create;
  try
    try
      var AToken: String := GCCreateGoogleTokenString;
      LFormUrlEncoded.Add('grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer');
      LFormUrlEncoded.Add('assertion=' + AToken);
      LResponse := LRequest.Post('https://oauth2.googleapis.com/token', LFormUrlencoded);
      if LResponse.StatusCode = 200 then
      begin
        Result := LResponse.ContentAsString();
        var JSONObj: TJSONObject := TJSONObject.ParseJSONValue(Result) as TJSONObject;
        try
          if Assigned(JSONObj) then
            Result := JSONObj.GetValue<string>('access_token');
        finally
          JSONObj.Free;
        end;
      end;
    except
      on e: exception do
      begin
        Result := '';
        raise Exception.Create('Error getting Google Token: ' + E.Message);
      end;
    end;
  finally
    LFormUrlencoded.Free;
    LRequest.Free;
  end;
end;


sending a push message with RESTClient:

 

function CreateBodyMessageJSON(AFBToken: String): String;
// https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification
begin
  var AJSONMain: TJSONObject := TJSONObject.Create;
  try
     var AJSONMessage: TJSONObject := TJSONObject.Create;
     AJSONMessage.AddPair('token', AFBToken);

     // for all
     var AJSONNotification: TJSONObject := TJSONObject.Create;
     AJSONNotification.AddPair('body', FBody);
     AJSONNotification.AddPair('title', FTitle);
     AJSONMessage.AddPair('notification', AJSONNotification);

     // for Android
     var AJSONNotification1: TJSONObject := TJSONObject.Create;
     AJSONNotification1.AddPair('sound', 'default');
//     AJSONNotification1.AddPair('notification_count', TJSONNumber.Create(1)); // if needed
     var AJSONAndroid: TJSONObject := TJSONObject.Create;
     AJSONAndroid.AddPair('notification', AJSONNotification1);
     AJSONMessage.AddPair('android', AJSONAndroid);

     // for IOS
     var AJSONAps: TJSONObject := TJSONObject.Create;
     AJSONAps.AddPair('sound', 'default');
     AJSONAps.AddPair('badge', TJSONNumber.Create(1));  // Show badge on app icon on IOS
     var AJSONPayload: TJSONObject := TJSONObject.Create;
     AJSONPayload.AddPair('aps', AJSONAps);
     var AJSONApns: TJSONObject := TJSONObject.Create;
     AJSONApns.AddPair('payload', AJSONPayload);
     AJSONMessage.AddPair('apns', AJSONApns);

     AJSONMain.AddPair('message', AJSONMessage);
     Result := AJSONMain.ToJSON;
  finally
    AJSONMain.Free;
  end;
end;

RESTClientPushmessage.BaseURL := 'https://fcm.googleapis.com/v1/projects/' + FGoogleProjectID + '/messages:send';
RESTRequestPusMessage.Params.ParameterByName('Authorization').Value := 'Bearer ' +  GCGetOAuthToken;  // pkHTTPHEADER
RESTRequestPusMessage.Params.ParameterByName('Content-Type').Value := 'application/json' // pkHTTPHEADER
RESTRequestPusMessage.Params.ParameterByName('body').Value := CreateBodyMessageJSON(AFireBaseToken);  // pkREQUESTBODY
RESTRequestPusMessage.Execute;

 

If i miss something let me know...

For reading FB token on IOS i use: Firebase SDK for IOS 6.28 (working on Delphi 12.2) 

 

Share this post


Link to post
On 10/16/2024 at 8:54 PM, John van de Waeter said:

But both 11.2.0 as 11.3.0 give me an error when I try to unzip them: Invalid Zip-file. Tried on both win10 and win11.

A follow-up to this: I have contacted their support team, who requested that I provide a video demonstrating the problem 🙄. I have since replied, asking them if they really are incapable of doing two simple steps (Using Windows: download, and try to open) to replicate it themselves.

Share this post


Link to post
17 hours ago, Dave Nottage said:

(Using Windows: download, and try to open) to replicate it themselves.

I used WinZip to unzip the archive, which allowed me to skip files with bad filenames.

I figured if those filenames are not allowed in Windows, these files  are probably not used anyway.

It worked.

 

ps, Dave, if I have questions about Kastri, should I ask them here?

Edited by John van de Waeter

Share this post


Link to post
9 hours ago, John van de Waeter said:

Dave, if I have questions about Kastri, should I ask them here?

If they're actual issues, I'd rather them being reported here. I'm sure it's perfectly alright to ask questions in this forum, though.

Share this post


Link to post
On 10/18/2024 at 6:24 PM, Vladsrb said:

Hi,


i was facing with the same problem...
This is my workable solution, in short 🙂 

 

uses System.Net.HttpClient, JOSE.Core.Builder, JOSE.Core.JWT, JOSE.Core.JWA, JOSE.Types.Bytes, JOSE.Types.JSON, JOSE.Signing.RSA, JOSE.Core.JWK
JOSE is taken from https://github.com/paolo-rossi/delphi-jose-jwt  

Info:
FGoogleProjectID :  is your project ID like 'name-95dc3e3' (console.cloud.google.com)
FGoogleServiceEmail: like 'firebase-adminsdk-9tm7h@XXXXXXXX.iam.gserviceaccount.com'
FGoogleServicePrivateKey: '-----BEGIN PRIVATE KEY-----...' taken from the JSON file when you create a key for a Google service account (you need to remove the \n characters from the key)


function CreateGoogleTokenString: String;
begin
  Result := '';
  var JWToken: TJWT := TJWT.Create(TJWTClaims);
  try
    try
      JWToken.Claims.Issuer := FGoogleServiceEmail; 
      JWToken.Claims.SetClaim('scope', 'https://www.googleapis.com/auth/firebase.messaging');
      JWToken.Claims.Audience :='https://oauth2.googleapis.com/token';
      JWToken.Claims.IssuedAt := Now;
      JWToken.Claims.Expiration := IncMinute(Now, 60);  // not more than 60
      var AJWKKey: TJWK := TJWK.Create(FGoogleServicePrivateKey); 
      var LSignature: TJOSEBytes := TJOSE.SerializeCompact(AJWKKey, TJOSEAlgorithmId.RS256, JWToken);
      Result := LSignature.AsString;
    except
      on e: exception do
        raise Exception.Create('Error creating Google Token String: ' + E.Message);
    end;
  finally
    FreeAndNil(JWToken);
  end;
end;

function GetOAuthToken: String;
var
  LResponse: IHTTPResponse;
  LFormUrlencoded: TStringList;
  LRequest: THTTPClient;
begin
  Result := '';
  LRequest := THTTPClient.Create;
  LFormUrlEncoded := TStringList.Create;
  try
    try
      var AToken: String := GCCreateGoogleTokenString;
      LFormUrlEncoded.Add('grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer');
      LFormUrlEncoded.Add('assertion=' + AToken);
      LResponse := LRequest.Post('https://oauth2.googleapis.com/token', LFormUrlencoded);
      if LResponse.StatusCode = 200 then
      begin
        Result := LResponse.ContentAsString();
        var JSONObj: TJSONObject := TJSONObject.ParseJSONValue(Result) as TJSONObject;
        try
          if Assigned(JSONObj) then
            Result := JSONObj.GetValue<string>('access_token');
        finally
          JSONObj.Free;
        end;
      end;
    except
      on e: exception do
      begin
        Result := '';
        raise Exception.Create('Error getting Google Token: ' + E.Message);
      end;
    end;
  finally
    LFormUrlencoded.Free;
    LRequest.Free;
  end;
end;


sending a push message with RESTClient:

 

function CreateBodyMessageJSON(AFBToken: String): String;
// https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification
begin
  var AJSONMain: TJSONObject := TJSONObject.Create;
  try
     var AJSONMessage: TJSONObject := TJSONObject.Create;
     AJSONMessage.AddPair('token', AFBToken);

     // for all
     var AJSONNotification: TJSONObject := TJSONObject.Create;
     AJSONNotification.AddPair('body', FBody);
     AJSONNotification.AddPair('title', FTitle);
     AJSONMessage.AddPair('notification', AJSONNotification);

     // for Android
     var AJSONNotification1: TJSONObject := TJSONObject.Create;
     AJSONNotification1.AddPair('sound', 'default');
//     AJSONNotification1.AddPair('notification_count', TJSONNumber.Create(1)); // if needed
     var AJSONAndroid: TJSONObject := TJSONObject.Create;
     AJSONAndroid.AddPair('notification', AJSONNotification1);
     AJSONMessage.AddPair('android', AJSONAndroid);

     // for IOS
     var AJSONAps: TJSONObject := TJSONObject.Create;
     AJSONAps.AddPair('sound', 'default');
     AJSONAps.AddPair('badge', TJSONNumber.Create(1));  // Show badge on app icon on IOS
     var AJSONPayload: TJSONObject := TJSONObject.Create;
     AJSONPayload.AddPair('aps', AJSONAps);
     var AJSONApns: TJSONObject := TJSONObject.Create;
     AJSONApns.AddPair('payload', AJSONPayload);
     AJSONMessage.AddPair('apns', AJSONApns);

     AJSONMain.AddPair('message', AJSONMessage);
     Result := AJSONMain.ToJSON;
  finally
    AJSONMain.Free;
  end;
end;

RESTClientPushmessage.BaseURL := 'https://fcm.googleapis.com/v1/projects/' + FGoogleProjectID + '/messages:send';
RESTRequestPusMessage.Params.ParameterByName('Authorization').Value := 'Bearer ' +  GCGetOAuthToken;  // pkHTTPHEADER
RESTRequestPusMessage.Params.ParameterByName('Content-Type').Value := 'application/json' // pkHTTPHEADER
RESTRequestPusMessage.Params.ParameterByName('body').Value := CreateBodyMessageJSON(AFireBaseToken);  // pkREQUESTBODY
RESTRequestPusMessage.Execute;

 

If i miss something let me know...

For reading FB token on IOS i use: Firebase SDK for IOS 6.28 (working on Delphi 12.2) 

 

Hi, Vladsrb!


I tried your solution
It works great on Windows!

 

But I need to run it on iOS
"-For reading FB token on IOS i use: Firebase SDK for IOS 6.28 (working on Delphi 12.2)"

 

Could you please describe the process in more detail:
How do I use Firebase SDK for IOS 6.28,
where can I download Firebase SDK (GetIt doesn't work for me for some reason),
where and what links should I write in the project?

Share this post


Link to post
3 hours ago, Vanar said:

But I need to run it on iOS

Why do you need to send push messages from an iOS device? It's a very bad idea to have private key info in an iOS app. In a web server (where messages should be sent from), the executable (and private key) is (or at least should not be) accessible externally.

3 hours ago, Vanar said:

How do I use Firebase SDK for IOS 6.28,
where can I download Firebase SDK (GetIt doesn't work for me for some reason),

From here: https://github.com/firebase/firebase-ios-sdk/releases/download/CocoaPods-6.28.0/Firebase.zip
..but the code example above which sends messages does not require the iOS SDK, which is used for receiving messages.

  • Like 1

Share this post


Link to post
11 hours ago, Dave Nottage said:

Why do you need to send push messages from an iOS device? It's a very bad idea to have private key info in an iOS app. In a web server (where messages should be sent from), the executable (and private key) is (or at least should not be) accessible externally.

I agree, but I just wanted to test it.
On iOS, the error is:

5238078600681479969.jpg

Share this post


Link to post
17 hours ago, Vanar said:

How do I use Firebase SDK for IOS 6.28

Currently i also get Internal server Error for GetIt, so for FB SDK you can use the link provided by Dave Nottage.

For reading FB token from IOS app using FB SDK: Manual

Hint: When you add Project/Deployment - GoogleService-Info.plist (downloaded from Firebase for IOS) - check 'Remote path' column, must be: .\  

  • Thanks 2

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×