You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TLDR; I ultimately used Firebase Hosting to deploy server code to invoke the HTTP v1 API. See dlcole/httpV1Msg for a sample implementation.
I’m creating this issue to track the changes necessary to migrate to firebase's new HTTP v1 messaging API, as required by June 20, 2024. My app was originally built with the older nativescript/firebase plugin which had excellent documentation on how to send and receive notifications via Firebase Cloud Messaging (FCM) and http POST's. Google does have the document, Migrate from legacy FCM APIs to HTTP v1, but it is WOEFULLY inadequate to document the tasks actually needed to migrate, and the newer firebase plugin @nativescript/firebase-messaging readme while good, doesn't offer much more when it comes to this topic.
What documentation there is suggests that sending notifications via server code is preferable to the simple http POST in FCM. There are code snippets, but not actual working examples, of what such server code should look like, especially within a Nativescript app.
My preference is to continue to use http POST's, as I can obscure my private key if necessary, and I don't see that as being inherently less secure than the server ID I'm currently using with legacy FCM. I found this tutorial to be VERY helpful, but it, too, is incomplete, as the bearer authentication needs to be recreated with each use. (This is worth watching just to get commiseration on how inadequate the Google documentation is.)
The resulting code should look something like this:
const jwt = require('jsonwebtoken');
// Set the necessary claims for the custom token
const uid = 'your-user-id'; // user.uid returned from firebase login
const claims = {
uid: uid,
iat: Math.floor(Date.now() / 1000), // Issued at claim (current time in seconds)
// Add other custom claims if needed
};
// Generate the custom token using your Firebase project's service account private key
const privateKey = `-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----`; // Replace with the private key from downloaded json file
const customToken = jwt.sign(claims, privateKey, { algorithm: 'RS256' });
With this you should have what you need to add the authorization to the HTTP v1 POST:
Authorization: Bearer <customToken>
Sounds easy, right? Well, when I simply require jsonwebtoken, I receive these 6 error messages on Android:
ERROR in node:buffer
Module build failed: UnhandledSchemeError: Reading from "node:buffer" is not handled by plugins (Unhandled scheme).
ERROR in node:crypto
Module build failed: UnhandledSchemeError: Reading from "node:crypto" is not handled by plugins (Unhandled scheme).
ERROR in node:events
Module build failed: UnhandledSchemeError: Reading from "node:events" is not handled by plugins (Unhandled scheme).
ERROR in node:https
Module build failed: UnhandledSchemeError: Reading from "node:https" is not handled by plugins (Unhandled scheme).
ERROR in node:http
Module build failed: UnhandledSchemeError: Reading from "node:http" is not handled by plugins (Unhandled scheme).
ERROR in node:util
Module build failed: UnhandledSchemeError: Reading from "node:util" is not handled by plugins (Unhandled scheme).
This looks unsettlingly similar to the issues I saw with WebPack 5 (see this related issue from last August, with the webpack.config.js changes necessary to fix). I tried using the jose plugin an alternative but received the same error messages.
So, that's where I'm at. If I can resolve these errors messages I think I'll be unstuck. My challenge is translating what solutions I find online to what would be specified webpack.config.js. Yes, I've ready the docs many, many times and it's still alien to me. When I can better articulate a question I'll post that separately.
For completeness, here's the app's current package.json:
This appears to be the same problem identified in this issue and this issue, but so far none of the solutions suggested there resolve the issue.
All this is to be able to invoke jsonwebtoken.sign(), and right now it's only a hopeful guess that that will actually create a useable Authorization: Bearer token.
Edit 12/09/2023:
I received a suggestion from one of the referenced issues, above, and this addition to webpack.config.js eliminates the env errors, but it's hard to say if it might cause other problems.
I'll be honest, I've never seen a rabbit hole this deep. jsonwebtoken is intended for a node environment and it takes all kinds of shenanigans in webapck.config.js to knock down one error after another. I have no idea how many errors might remain, or if jsonwebtoken is even the right utility. (It was suggested by nextpage.ai, but it might have been hallucinating.) I've found other documentation that suggests google-auth as the means to create the bearer token, but it is also intended for a node environment, as is jose. After a full week on this I have nothing to show, except that I've learned more about webpack than I really wanted to know.
I'll ask for help in Discord and hope someone can throw me a bone.
Edit 12/10/2023:
Here’s where things currently stand... From the code at the top of this description, when I run:
I can’t step into jwt.sign in a debugger, and while I’ve spent a lot of time digging through the jsonwebtoken and crypto-browserify source, I’m not making any progress. I expect webpack.config.js is pertinent, so here’s my current file:
I’ve got other oceans to boil, notably migrating from @kefah/nativescript-google-maps to @nativescript/google-maps, so I plan to redirect my efforts there for the time being, hoping perhaps others can make progress on this front.
I’ll be back.
Edit 12/20/2023:
To their belated credit, firebase has added documentation about how to set authorization. Here's the full example. But it still presumes a node server environment, and the line const { google } = require('googleapis'); gave me LOTS of runtime errors.
You beat your head against a wall long enough and you'll think maybe you should at least try a different wall. To that end, I took the approach writing a node server that would contain the service account JSON file, perform the authentication, and send the message. This turned out to be no small effort, but I can now successfully send push notifications via the HTTP v1 API to a topic. Sending to a device is next, but that should be straightforward at this point.
My takeaway from all this is that if you're currently using server code to send FCM messages, then changing that to send via HTTP v1 should be relatively easy. If you're sending your messages from within your app, however, then you have a major migration effort ahead. I've spent about 3 weeks on this so far.
I plan to create a GitHub repository that contains my server code and client driver to help other fellow travelers along this path. I'll update this issue when I have more details.
Edit 12/21/2023:
I spoke too early. Sending a push notification via the node server is, for now, problematic. SOMETIMES it will work, but right now I'm consistently hitting the error
Error: secretOrPrivateKey must be an asymmetric key when using RS2561
when running remotely, but the code does work consistently when running locally.
I was ultimately able to get this working by switching to Firebase Hosting to deploy the server code that invokes the HTTP v1 interface. I still hope to create a GitHub repository with the working code once I get it cleaned up.
TLDR; I ultimately used Firebase Hosting to deploy server code to invoke the HTTP v1 API. See dlcole/httpV1Msg for a sample implementation.
I’m creating this issue to track the changes necessary to migrate to firebase's new HTTP v1 messaging API, as required by June 20, 2024. My app was originally built with the older nativescript/firebase plugin which had excellent documentation on how to send and receive notifications via Firebase Cloud Messaging (FCM) and http POST's. Google does have the document, Migrate from legacy FCM APIs to HTTP v1, but it is WOEFULLY inadequate to document the tasks actually needed to migrate, and the newer firebase plugin @nativescript/firebase-messaging readme while good, doesn't offer much more when it comes to this topic.
What documentation there is suggests that sending notifications via server code is preferable to the simple http POST in FCM. There are code snippets, but not actual working examples, of what such server code should look like, especially within a Nativescript app.
My preference is to continue to use http POST's, as I can obscure my private key if necessary, and I don't see that as being inherently less secure than the server ID I'm currently using with legacy FCM. I found this tutorial to be VERY helpful, but it, too, is incomplete, as the bearer authentication needs to be recreated with each use. (This is worth watching just to get commiseration on how inadequate the Google documentation is.)
The resulting code should look something like this:
const jwt = require('jsonwebtoken');
With this you should have what you need to add the authorization to the HTTP v1 POST:
Authorization: Bearer <customToken>
Sounds easy, right? Well, when I simply
require jsonwebtoken
, I receive these 6 error messages on Android:This looks unsettlingly similar to the issues I saw with WebPack 5 (see this related issue from last August, with the webpack.config.js changes necessary to fix). I tried using the jose plugin an alternative but received the same error messages.
So, that's where I'm at. If I can resolve these errors messages I think I'll be unstuck. My challenge is translating what solutions I find online to what would be specified
webpack.config.js
. Yes, I've ready the docs many, many times and it's still alien to me. When I can better articulate a question I'll post that separately.For completeness, here's the app's current package.json:
And webpack.config.js
Edit 12/08/2023:
After two days of investigation and trial-and-error, this addition to
webpack.config.js
takes care of the 6 build errors I was seeing:const { NormalModuleReplacementPlugin } = require('webpack');
But I'm not unstuck, as I now get the runtime error:
This appears to be the same problem identified in this issue and this issue, but so far none of the solutions suggested there resolve the issue.
All this is to be able to invoke
jsonwebtoken.sign()
, and right now it's only a hopeful guess that that will actually create a useableAuthorization: Bearer
token.Edit 12/09/2023:
I received a suggestion from one of the referenced issues, above, and this addition to
webpack.config.js
eliminates the env errors, but it's hard to say if it might cause other problems.And after that, I resolved a Buffer reference error with
I'll be honest, I've never seen a rabbit hole this deep.
jsonwebtoken
is intended for a node environment and it takes all kinds of shenanigans inwebapck.config.js
to knock down one error after another. I have no idea how many errors might remain, or ifjsonwebtoken
is even the right utility. (It was suggested by nextpage.ai, but it might have been hallucinating.) I've found other documentation that suggestsgoogle-auth
as the means to create the bearer token, but it is also intended for a node environment, as isjose
. After a full week on this I have nothing to show, except that I've learned more about webpack than I really wanted to know.I'll ask for help in Discord and hope someone can throw me a bone.
Edit 12/10/2023:
Here’s where things currently stand... From the code at the top of this description, when I run:
I catch the error
TypeError: crypto.createSign is not a function
I can’t step into
jwt.sign
in a debugger, and while I’ve spent a lot of time digging through thejsonwebtoken
andcrypto-browserify
source, I’m not making any progress. I expectwebpack.config.js
is pertinent, so here’s my current file:I’ve got other oceans to boil, notably migrating from
@kefah/nativescript-google-maps
to@nativescript/google-maps
, so I plan to redirect my efforts there for the time being, hoping perhaps others can make progress on this front.I’ll be back.
Edit 12/20/2023:
To their belated credit, firebase has added documentation about how to set authorization. Here's the full example. But it still presumes a node server environment, and the line
const { google } = require('googleapis');
gave me LOTS of runtime errors.You beat your head against a wall long enough and you'll think maybe you should at least try a different wall. To that end, I took the approach writing a node server that would contain the service account JSON file, perform the authentication, and send the message. This turned out to be no small effort, but I can now successfully send push notifications via the HTTP v1 API to a topic. Sending to a device is next, but that should be straightforward at this point.
My takeaway from all this is that if you're currently using server code to send FCM messages, then changing that to send via HTTP v1 should be relatively easy. If you're sending your messages from within your app, however, then you have a major migration effort ahead. I've spent about 3 weeks on this so far.
I plan to create a GitHub repository that contains my server code and client driver to help other fellow travelers along this path. I'll update this issue when I have more details.
Edit 12/21/2023:
I spoke too early. Sending a push notification via the node server is, for now, problematic. SOMETIMES it will work, but right now I'm consistently hitting the error
Error: secretOrPrivateKey must be an asymmetric key when using RS2561
when running remotely, but the code does work consistently when running locally.
Edit 12/22/2023:
I created this SO post on the above error.
The text was updated successfully, but these errors were encountered: