FCM token contains double quotations - android

Ii have configured android for FCM.
public class DERFirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
}
}
The token that I get from firebase server is following
"c5pu6rD06ts:APA91bHEgXUbJR8UegRPnLMgowEC6QxUPP73TiSBIHG1Pe0I8u22298rjpbXBsK94ExTmTbL0VT009AhsIqgMSkoLFZJDuaPSpaLlqBAyIrrtzsdLuWhvCp6CtkZwMT88P-WxBFCT2DH"
This token contains double quotations. So what I am doing wrong that server send me this token. Can any one help me..?
Due to this , when server send request to this token I am getting following error
"message": "The registration token is not a valid FCM registration
token",
"domain": "global",
"reason": "badRequest"

Related

Migrating from Google Sign-In for Android to Firebase Authentication

Currently, we plan to use Google Sign-In for Android, as our server authentication method.
This is what we plan to do.
Client side (Google Sign-In for Android)
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// This idToken will sent to backend server.
String idToken = account.getIdToken();
Server side (Google Sign-In for Android)
// Based on received idToken from client, backend server will call https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=...
// to identify who is this user.
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}
In the future, we might want to migrate to provide more login option. This is my future migration plan, to migrate from Google Sign-In for Android to Firebase Authentication.
Client side (Firebase Authentication)
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
// This idToken will sent to backend server.
String idToken = task.getResult().getToken();
} else {
// Handle error -> task.getException();
}
}
});
Server side (Google Sign-In for Android)
# idToken comes from the client app (shown above)
decoded_token = auth.verify_id_token(idToken)
uid = decoded_token['uid']
My questions are
For Google Sign-In for Android, We plan to store "sub": "110169484474386276334", as an unique identifier to represent a user. Is that a correct field to be used? Is it unique per user? My testing so far is, at client side, we might get different idToken for a same user (At different day). Different idToken from same user, will still yield same sub at server side.
One day, we might migrate to Firebase Authentication to support more login methods. Is it still backward compatible with Google Sign-In for Android. Is Firebase Authentication able to return same "sub" as what is previously returned by Google Sign-In for Android? As you can see in the code example, Firebase Authentication is returning uid.
How can I compare new Firebase Authentication's uid, with previous stored Google Sign-In's sub?
Q1: is basically answered here:
A Google account's email address can change, so don't use it to identify a user. Instead, use the account's ID, which you can get on the client with GoogleSignInAccount.getId(), and on the backend from the sub claim of the ID token.
Q2: Google as Auth provider for Firebase still uses the same Google sign-in flow (in the beginning), while it then authenticates the user against a Firebase project, as well.
there's an example which shows it:
private void signIn() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, REQUESTCODE_SIGN_IN);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == REQUESTCODE_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
// Google Sign In was successful
GoogleSignInAccount account = task.getResult(ApiException.class);
String idToken = account.getIdToken();
// Send token to your backend via HTTPS
// authenticate with Firebase
firebaseAuthWithGoogle(account);
} catch (ApiException e) {
Log.w(TAG, "Google sign in failed", e);
}
}
}
where GoogleSignInAccount account is still the same response.
edit: one can even verify the ID token from FirebaseAuth alike this:
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();
}
}
});

Firebase Notification & User Id

I'm using Firebase with an Android app (Auth, Database and Notification).
I'm trying to send notification from an external server (in nodejs) so an user can send a notification to another user.
So the android app memorize a list of UserId (the same ids from Firebase Auth) and then send this list to the nodejs server.
With this list, the server contact the url 'https://fcm.googleapis.com/fcm/send', but Firebase returns me a InvalidRegistration because i'm sending a list of userId and not the list of registration token created by firebase notification.
Should I memorize those tokens or there is a way to send notification with the user id ?
(And when I try with a list of tokens, of course it's working.)
var requestData = {
"registration_ids": userIds, //Problem is here
"data": {
"message": "A message"
}
};
request({
url: "https://fcm.googleapis.com/fcm/send",
method: "POST",
json: true,
headers: {
"Authorization": "key=firebaseKey",
"content-type": "application/json",
},
json: requestData
},
function(err, response, body) {
});
Yes, you can. For this you have to register these user Ids instead of device Id token. Then firebase recognized your user Ids.
#Override
public void onNewToken(#NonNull String token) {
super.onNewToken(token);
Log.d("user_token: ",token);
}

GCM returning notRegisteded

Here is my Java code.
#Override
protected void onHandleIntent(Intent intent) {
// Make a call to Instance API
InstanceID instanceID = InstanceID.getInstance(this);
String senderId = getResources().getString(R.string.gcm_defaultSenderId);
try {
// request token that will be used by the server to send push notifications
String token = instanceID.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE,null);
Log.d(TAG, "GCM Registration Token: " + token);
// pass along this data
sendRegistrationToServer(token);
} catch (IOException e) {
e.printStackTrace();
}
}
I copied the registration id, and used postman to push notifications to android device, it is giving error: notRegistered.
Here is my postman request
URL: https://gcm-http.googleapis.com/gcm/send
{
"to": "<registration_Key>",
"data": {
"message": "This is a GCM Topic Message!"
}
}
I tried copying the key, I tried creating a rest endpoint in nodejs which will receive this key and execute gcm request, but in both cases it is returning following response.
{
"multicast_id": 7402052379497307216,
"success": 0,
"failure": 1,
"canonical_ids": 0,
"results": [
{
"error": "NotRegistered"
}
]
}

AWS SNS Android GCM - InvalidPlatformToken

Using Xamarin and AWS SNS trying to get push notifications working. They were working just fine the other day. Today they aren't.
I have an Android device and an iOS device. Whenever I change anything in my application the other device is supposed to get a push notification. The iOS device is working.
C# code for subscribing on Android:
[Service(Exported = false)]
public class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent(Intent intent)
{
try
{
Log.Info("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance(this);
var token = instanceID.GetToken(
"shhh it's a secret.", GoogleCloudMessaging.InstanceIdScope, null);
Log.Info("RegistrationIntentService", "GCM Registration Token: " + token);
SendRegistrationToAppServer(token);
Subscribe(token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}
void SendRegistrationToAppServer(string token)
{
// Add custom implementation here as needed.
//... handling my token on the back-end
}
void Subscribe(string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
Dropping some breakpoints in there I can see that my device token does match the token for the AWS endpoint that I'm trying to send messages to. For some reason though, I keep getting error messages back from AWS. This is what AWS is sending me:
{"DeliveryAttempts":1,"EndpointArn":"arn:aws:sns:...:endpoint/GCM/...","EventType":"DeliveryFailure","FailureMessage":"Platform token associated with the endpoint is not valid","FailureType":"InvalidPlatformToken","MessageId":"...","Resource":"arn:aws:sns:...:app/GCM/...","Service":"SNS","Time":"2016-03-28T18:22:59.360Z"}
What could be causing this if I know the token I'm getting back from the application matches the token of my AWS endpoint?
It is most likely that the registration id that is being passed to the SNS is not correct. I would recommend that you turn on the delivery status and see the actual response from GCM, see https://mobile.awsblog.com/post/TxHTXGC8711JNF/Using-the-Delivery-Status-feature-of-Amazon-SNS for information

Life post Android Mobile Backend Starter? Authentication errors

I'm picking up a project from last year that was based on the now discontinued 'mobile backend starter' from Google. I believe the app was left in a working state but it now seems to fail the authentication when the "Secured by Client IDs" setting is selected on the web page google provided. I get the following error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code": 401,
"errors": [
{
"domain": "global",
"location": "Authorization",
"locationType": "header",
"message": "Unauthenticated calls are not allowed",
"reason": "required"
}
],
"message": "Unauthenticated calls are not allowed"
}
The error results from running this method
private void listPosts(final String alertTxt) {
// create a response handler that will receive the result or an error
CloudCallbackHandler<List<CloudEntity>> handler =
new CloudCallbackHandler<List<CloudEntity>>() {
#Override
public void onComplete(List<CloudEntity> results) {
//mAnnounceTxt.setText(R.string.announce_success);
mAnnounceTxt.setText(alertTxt);
mPosts = results;
animateArrival();
updateGuestbookView();
}
#Override
public void onError(IOException exception) {
mAnnounceTxt.setText(R.string.announce_fail);
animateArrival();
handleEndpointException(exception);
}
};
...
I am not really sure where/how to start debugging this?
401 Errors are usually caused by any of the following:
Expired token
Token revocation
Token not authorized for needed scopes
Request not authorized correctly with OAuth
Try refreshToken() to resolve expired token issues

Categories

Resources