How to get all of device tokens from Firebase? - firebase

How to get device tokens (FCM registration tokens) from Firebase?
I'm making mobile app using firebase and its server using node.js.
I want to send push notification message from server, but I don't know how to get devices token.
How to get device tokens from external server? I'm using Firebase admin SDK now.
Is the device token only generated when the app is connected fcm server?
Should I save token to another database when user first run the app and register FCM server?

1. How to get device tokens from external server? I'm using Firebase admin SDK now.
There is currently no API to retrieve all the Registration tokens for your app from the Server side. It's the developer's (you) responsibility to send and store the Registration token to your App Server, which is generated from the Client App side.
2. Is the device token only generated when the app is connected FCM server?
The documentation pretty much covered this (see also my answer here):
On initial startup of your app, the FCM SDK generates a registration token for the client app instance.
It doesn't technically get connected to the FCM Servers. It connects to the FirebaseInstanceID service (via the SDK), which in turn generates the Registration Token.
3. Should I save token to another database when user first run the app and register FCM server?
As I mentioned in #1, you should save it where you can easily access it to send a message.

The device token is generated when the app first connects, this token must then be stored in your database, and replaced if a new token is assigned
public class MyAndroidFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "MyAndroidFCMIIDService";
#Override
public void onTokenRefresh() {
//Get hold of the registration token
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//Log the token
Log.d(TAG, "Refreshed token: " + refreshedToken);
}
private void sendRegistrationToServer(String token) {
//Implement this method if you want to store the token on your server
}
}
See the following Tutorial

I suggest not storing the tokens at all. Storing the token seems like a good idea until you realize that your users have multiple devices (iOS device, android device, desktop etc.) Now you have to manage storing multiple device tokens per user and that can get messy fast.
Instead, ignore the tokens that are generated and simply subscribe each user to a topic such as when user logs in or creates account subscribe them to a topic made of their userid
NSString* useridchannel = [NSString stringWithFormat:#"user_%ld", (long)userid];
[[FIRMessaging messaging] subscribeToTopic:useridchannel completion:^(NSError * _Nullable error) {
NSLog(#"Subscribed user to topic %#", useridchannel);
}];
When user logs out make sure to unsubscribe them from that topic as they probably don't want to receive notifications if they are no longer logged into your app
NSString* useridchannel = [NSString stringWithFormat:#"user_%ld", (long)userid];
[[FIRMessaging messaging] unsubscribeFromTopic:useridchannel completion:^(NSError * _Nullable error) {
NSLog(#"Unsubscribed user from %#", useridchanel);
}];
I realize that Device Groups are supposed to be used for this purpose, but again I don't want to be bothered with storing and managing tokens and also Firebase Admin SDK for PHP does not support sending messages to Device Groups. By using topics there is no need to deal with device tokens and you can send messages to all the users devices from server, the app, or firebase console easily.

You can make a get request to
https://<<your_project_name>>.firebaseio.com/.json?auth=<<your_database_secret_key>>
The database secret key you get in Firebase console under the tab settings/serviceaccounts/databasesecrets
This returns a JSON file containing all Storage data of your project.

Related

How a Firebase token is generated?

I'm doing analysis on Firebase Token and understood below points:-
-> A Firebase token is saved in database which will be used for sending notifications.
-> The token generally do not expire except in the following cases:
- The app deletes Instance ID
- The app is restored on a new device
- The user uninstalls/reinstall the app
- The user clears app data.
-> When we use a token which is expired we get errors like Not Registered from the response while sending messages.
-> To avoid the error, we should be deleting the token from database.
However I have found that If we login to a cloud application (which is my app currently), a new fcm token gets generated when i logged in to a new browser say FireFox, Edge etc.
So, the token is generated based on browser or System IP or what exactly the Fcm uses to generate a token ?
The method used to generate the token is an implementation detail, and you should not depend on that to build your app.
A token uniquely identifies a device. Each device receives messages independently of each other, and does not know anything about the user of that device. It's expected that if a user signed into an app on multiple devices, that each device would generate a unique token. If you want to send message to a user, you will have to map each of the user's device tokens in your own database, and send the message to each of them, or only the ones that the user chooses.
You can expect that device tokens might change over time. If you send a message to a device, and the API tells you that the token is not valid, you should simply delete it from your records.

Firebase admin - get Google OAuth token

I have a web application where users can sign in with Google.
To the sign-in process, I add a scope to be able to access Google Calendar.
Now that the user is signed in, I would like to - in server-side - get their current Google access token in order to make a request and get a list of their events.
Is there a way to get the current OAuth token (no need for refresh token) in order for me to make this completely on the server-side?
I'd say that you can check this article and put special attention to the recommendation for websites.
I understand you have configured already the consent screen, which is the first step of the basic steps on using OAuth 2.0. So I understand that you only have to perform the following steps:
Obtain an access token from the Google Authorization Server
Examine scopes of access granted by the user.
Send the access token to an API
I think you can also give a look to this other doc for more GCP insights over your goal to authorize the request using user tokens
Edited:
Regarding the Firebase Authentication, I understand this happens at the user's device, and you could use some code to retrieve the token and then send it to your back end servers as mentioned in here.
As a sample here there's the sample code for retrieving the token in Android:
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
A little about OAuth 2.0
Whenever a user signs up to your app/website via Google or 3rd Party, an Authorization Code, this Authorization Code is exchanged for an AccessToken & RefreshToken.
The AccessToken sent via Google are valid generally for 60 minutes.
Offline Access (Server Side)
Let's break it down to two parts:
If your need to update within 60 minutes of user's last activity
You can use firebase along with gapi to achieve that. You'll be provided with the AccessToken that can be sent back to server to add to calendar.
More info on implementation
If you need to update after 60 minutes of user's last activity
Firebase & gapi's most method handle the AuthorizationCode flow internally. They even further refresh the AccessToken after 60 minutes. This is beneficial for most developers as they won't have a headache of managing all the tokens.
This method but, hides RefreshToken & AuthorizationCode from the developer. That is even if your server has the access token, it won't be able to refresh it and it would be deemed useless.
To achieve complete offline access, in the initial request to get AuthorizationCode you will need to send a HTTP GET parameter access_type to offline
GAPI provides you with grantOfflineAccess() method which returns the AuthorizationCode that can be later used on your server to fetch access token & refresh token.
Note: If you are storing AuthorizationCode in your database, make sure it is secure. The limitation in Firebase are set due to security reason. It is more secure to not talk with AuthorizationCode generally.
More links
https://developers.google.com/identity/protocols/oauth2/web-server
https://developers.google.com/identity/sign-in/web/reference
https://developers.google.com/identity/sign-in/web/server-side-flow
https://developers.google.com/identity/sign-in/web/backend-auth
Retrieve Google Access Token after authenticated using Firebase Authentication

Firebase Push Notification - How to keep track of user FCM tokens?

This is a general question around FCM tokens. Currently in my react-native app, as soon as I have new token, I make an API call to link this token with a user ID. And when this token is also refreshed, I make the same API call again.
We use those tokens to send 'Happy Birthday' push notifications and the likes.
I would like to know in the event that a user does not use the app, this token will get expired and we do not have a way to keep track of the token. The birthday push notifs will still be sent to the old expired token. How can we mitigate this? Any idea ?
I am actually looking for a way/strategy to still have the push notifications being delivered to the user even if they have not used the app for a while? Do you think scheduled push notifications might work?
When you send data to an expired token, you'll get a response indicating this. You can capture this response, and use that to remove the tokens from your database.
The samples repo for Cloud Functions has a great example of this. Modified from there:
var response = admin.messaging().sendToDevice(tokens, payload);
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensSnapshot.ref.child(tokens[index]).remove();
}
}
});
I would like to know in the event that a user does not use the app,
this token will get expired and we do not have a way to keep track of
the token. The birthday push notifs will still be sent to the old
expired token. How can we mitigate this? Any idea?
In my case, I register for firebase token each time my front end application gets launched. Most of the time it sends the registration token which is already stored in my database. However, when a new firebase registration token is received in my server side, I store the new token and while sending the push notification, I send the notification to all available registration token that I have.
You cannot figure out if the user has stopped using your application until you get notified about launching your application by sending the firebase registration token to the server side application. Hope that helps.
We shall drive campaigns that retain our clients. All the above answers are right though.

Proper way to verify user's mobile number using Firebase

I know that I can use Firebase's phone verification on Android and iOS, but the problem is that the information about client's verification can easily be forged on the client side, because I using only server side SSL certificate, so, only client knows that the server is trusted.
So, I decided to send mobile number on the server-side and check it there: send verification code and ask this verification code from the user. But I can't see any C++ server Firebase SDK, only client-side C++ SDK is available.
So, I have two options:
Understand how is client-side verification can be trusted on the server-side(note that I can have untrusted clients)? So, it's means I could use main Firebase phone number auth method.
Use server-side phone verification.
Please, help me with this misunderstanding in the Firebase.
Client side absolutely works here. The flow is like this:
You request a sign in using a phone number
The Firebase Phone Auth server sends a code to that number
The user enters your code into your app, which sends it to the Firebase Auth server
The Firebase Auth server returns you a Firebase Auth token
This works because a malicious user could only know the code if they had your phone. It doesn't guarantee the device is the one with that phone number (the user could have two phones, or sign in with a phone on a laptop), but it does verify the user has access to that number.
For verifying that to your own backend, you retrieve a Firebase ID token. This is just a little bundle of base64 encoded JSON, but importantly its cryptographically signed by Firebase. This means on your server you can verify that it was really created by Firebase, for the user and phone number that is contained within it. A user couldn't generate one of those tokens without access to the underlying account.
See the docs on verifying ID tokens for more!
So your next steps would be:
Retrieve the Firebase ID token
You can do this any time you're signed in.
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
Verify on server the contents of the ID token.
The admin SDKs are set up out of the box to check for the right certificate, audience, expiry, and other important properties of an ID token.
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
decodedToken will contain properties for the phone number too!

Firebase (FCM) registration token

I am the new for FCM. Here are some questions about the registration token:
Is the registration token generated by the FCM connection server?
Does the token change periodically in the connection server?
When?
Will it force the onTokenRefresh() in the app to be called?
I have googled for a week but didn't get any details. Please help. Thanks.
1. Is the registration token generated by the FCM connection server?
No. It gets generated by the FirebaseInstanceID. The way I understand the flow of event on first time registration:
The app retrieves a unique Instance ID.
The registration token is generated by calling the InstanceId.getToken().
Developer (usually) sends the token to the App Server.
2. Does the token change periodically in the connection server?
I think the onTokenRefresh() docs pretty much answers this.
Called when the system determines that the tokens need to be refreshed. The application should call getToken() and send the tokens to all application servers.
This will not be called very frequently, it is needed for key rotation and to handle Instance ID changes due to:
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
The system will throttle the refresh event across all devices to avoid overloading application servers with token updates.
See this part of the docs for more details.

Resources