I am trying to use firebase cloud messaging to deploy a http push notifications onto an actual device. When so, I am getting the error
"The credential used to authenticate this SDK does not have permission to send messages to the device corresponding to the provided registration token. Make sure the credential and registration token both belong to the same Firebase project."
I have checked the credentials on both the frontEnd and backEnd side and they all match up with my firebase correctly. I have tried to follow plenty of examples on here and I have missed on all of them. My node.js file looks like
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
export GOOGLE_APPLICATION_CREDENTIALS = "/Users/myname/mylocation/myfile.json"
exports.sendPushNotifications = functions.https.onRequest((req, res) => {
res.send("Attempting to send push notification")
console.log("LOGGER --- Trying to send push message..");
var uid = 'randomUIDString'
var fcmToken = 'myToken'
return admin.database().ref('/users/' + uid).once('value', snapshot => {
var user = snapshot.val();
console.log("username is " + user.name);
var payload = {
notification: {
title: 'Push Notification Title',
body: 'Test Notification Message'
}
}
admin.messaging().sendToDevice(fcmToken, payload)
.then(function(response) {
console.log('Succesfully sent message:', response);
console.log(response.results[0].error);
})
.catch(function(error) {
console.log('Error sending message', error);
});
})
})
The users name prints from calling the uid, but I am having trouble accessing the fcmToken.
I have checked my info.plist and the correct project is listed. Same with apple developer and appDelegate. is there something more that I am missing??
I am using Node.js on backend and creates a token for a user each time logins. angularx-social-login package makes it very easy to integrate Google OAuth with Angular but how to use it with API? After successful login the Google returns user information with token. I was thinking to send this information to backend and login the user but for that I need to create a route which accepts email address and logins user. And this will return JWT token which is not secure. By secure I mean, anyone can access the route without Google Authentication and generate token.
I am looking for ideas how developers achieved this.
I found google-auth-library client package for Node.js managed by Google.
Here is the follow:
Login user with Angular
Send the idToken to backend
Validate token and response to Angular
Node.js:
exports.googleLogin = function(req, res, next) {
//verify the token using google client
return googleClient
.verifyIdToken({
idToken: req.body.token,
audience: config.google.clientID
})
.then(login => {
//if verification is ok, google returns a jwt
var payload = login.getPayload();
var userid = payload['sub'];
//check if the jwt is issued for our client
var audience = payload.aud;
if (audience !== config.google.clientID) {
throw new Error(
'error while authenticating google user: audience mismatch: wanted [' +
config.google.clientID +
'] but was [' +
audience +
']'
);
}
//promise the creation of a user
return {
name: payload['name'], //profile name
pic: payload['picture'], //profile pic
id: payload['sub'], //google id
email_verified: payload['email_verified'],
email: payload['email']
};
})
.then(user => {
return res.status(200).json(user);
})
.catch(err => {
//throw an error if something gos wrong
throw new Error(
'error while authenticating google user: ' + JSON.stringify(err)
);
});
};
I have been integrating fb AccounKit with my ionic application (NodeJS server). Front-end part has been done and I'm able to send and receive OTPs and success status.
But while getting client token from authorization code, I keep getting ""Error verifying the token in the \'access_token\'"' error. I followed the same procedure mentioned in their official docs.
This is my code :
var me_endpoint_base_url = 'https://graph.accountkit.com/v1.0/me';
token_exchange_base_url='https://graph.accountkit.com/v1.0/access_token';
var params = {
grant_type: 'authorization_code',
code: request.body.code,
access_token: app_access_token
};
}
// exchange tokens
console.log(Querystring.stringify(params))
var token_exchange_url = token_exchange_base_url + '?' + Querystring.stringify(params);
Request.get({url: token_exchange_url, json: true}, function(err, resp, respBody) {
console.log(respBody);
var view = {
user_access_token: respBody.access_token,
expires_at: respBody.expires_at,
user_id: respBody.id,
};
var me_endpoint_url = me_endpoint_base_url + '?access_token=' + respBody.access_token;
Request.get({url: me_endpoint_url, json:true }, function(err, resp, respBody) {
console.log(respBody);
if (respBody.phone) {
view.method = "SMS"
view.identity = respBody.phone;
} else if (respBody.email) {
view.method = "Email"
view.identity = respBody.email.address;
}
});
});
Please help?
When making a sever-to-server call to exchange a code for a token, you need to supply your Account Kit App Secret in the access token you're sending.
So the access token should look like:
'AA|{app_id}|{app_secret}'
For ex.
var app_access_token = ['AA', app_id, app_secret].join('|');
You can find your app secret from the Account Kit dashboard. Go on "Account Kit" page under products section of your app on developers.facebook.com and click on the "Show" button next to the box for "Account Kit App Secret" to see your app secret.
Also remember that you should never include your app secret on any javascript code that runs on the client side. This secret is to be used only from your server-side node.js code and no one else should be able to see it
What are the procedures to follow in using GCM for a node based application?
Are there specific codes required on both server side(Node js) and client side(Android/iOS)?
Android device should sent a device token to the server to be able to receive notifications. Here an example how to do it.
Get gcm key to send pushes from server.
Send push with node-gcm package from npm with node.js app.
Basic example:
const gcm = require('node-gcm'); //Google Cloud Messaging
const gcmKey = ''; // Your gcm key in quotes
const deviceToken = ''; // Receiver device token
const sender = new gcm.Sender(gcmKey);
var message = new gcm.Message();
message.addData({
title: 'Push',
body: 'This is push notification',
otherProperty: true,
});
sender.send(message, {registrationIds: [token]}, (err) => {
if (err) {
console.error(err);
}
else {
console.log('Sent');
}
});
I am trying to upload videos from server without any manual authentication by user in the client side . I tried the below code snippet for video upload but it authenticates the user in the browser and asks for the acceptance of the app.
var ResumableUpload = require('node-youtube-resumable-upload');
var googleauth = require('google-auth-cli');
var google = require('googleapis');
var getTokens = function(callback) {
googleauth({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/youtube.upload' //can do just 'youtube', but 'youtube.upload' is more restrictive
},
{ client_id: CLIENT_ID, //replace with your client_id and _secret
client_secret: CLIENT_SECRET,
port: 3000
},
function(err, authClient, tokens) {
console.log(tokens);
callback(tokens);
});
};
getTokens(function(result) {
tokens = result;
upload();
});
var upload = function() {
var metadata = {snippet: { title: 'title', description: 'Uploaded with ResumableUpload' },
status: { privacyStatus: 'public' }};
var resumableUpload = new ResumableUpload(); //create new ResumableUpload
resumableUpload.tokens = tokens;
resumableUpload.filepath = 'youtube/test4.mp4';
resumableUpload.metadata = metadata;
resumableUpload.monitor = true;
resumableUpload.eventEmitter.on('progress', function(progress) {
console.log(progress);
});
resumableUpload.initUpload(function(result) {
console.log(result);
return;
});
}
But for my app it should directly upload the video to youtube from the server. For that I need the access token and refresh token I tried lot to get the access token directly but I couldn't able to get it.
So any help or idea to how to make the video upload directly from server to a channel account. I searched lot in google for a node module to do that but I couldn't able to find it.
I have been using this approach to upload video
Getting the web based generated token using the client library.
Getting the youtube upload permission from user for my application &
access_type=offline.
Access type offline gives refresh token in response. This token
will help to continue upload from backend server token when its
expires.
After getting the permission. It will redirect to URL with code.
Using the given code generate access_token
Save this token for future use.
Use the same token to push the video from your server to youtube
server
Refresh the token when it expires.
But is there any way to implement this approach without getting the youtube upload permission from user for my application.
You can do server side authetication using google API(JWT) with "Service Account". But direct upload from your server to youtube server without user permission is not possible. For uploading the video google needs OAuth2.0 authentication. It will give you error unAuthorized(401)- youtubeSignupRequired with "Service Account" using JWT authentication.
Becuase of the above limitation. You have use below Approach to work with this is-
Get the web based generated token using the client library.
Get the youtube upload permission from user for your application & access_type=offline.
Access type offline gives you refresh token in response. This token will help you to continue upload from backend server token when its expires.
After getting the permission. It will redirect to URL with code.
Using the given code generate access_token
Save this token for future use.
Use the same token to push the video from your server to youtube server
Refresh the token when it expires. And follow the step 3 - 5 again.
Currently this is the only way to upload the video on youtube.
Added the code on git repository nodejs-upload-youtube-video-using-google-api
For why its not possible? Check the below reference link & code:
From google API Doc: This error is commonly seen if you try to use the OAuth 2.0 Service Account flow. YouTube does not support Service Accounts, and if you attempt to authenticate using a Service Account, you will get this error. You can check all the error code & its detail using link: YouTube Data API - Errors
From gadata Issues: Youtube v3 Google Service Account Access
From google blog spot:List of Google API supported using Service Account
Check below code to get access_token from server side
You can check it yourself using below steps & code:
Go to Google Developer Console
Create Project
To Get Google+ API Access go to: APIs & Auth->APIs ->enable YouTube Data API v3
To Enable Service Account go to: APIs & Auth->Credentials->Create new Client ID->Click on Service Account->Create Client Id
Save the secret file on your system & keep it secure.
Create the secret key using below command & file you have downloaded:
openssl pkcs12 -in /home/rajesh/Downloads/Yourkeyfile.p12 -out youtube.pem -nodes
- Enter password: ***notasecret***
6. You can authorize & access api from server side as below:
var google = require('googleapis');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem', #path to pem file which we create using step 6
null,
['https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
console.log(tokens);
});
Get youtube video list using Service Account(working):
var google = require('googleapis');
var youtube = google.youtube('v3');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
youtube.videos.list({auth:authClient,part:'snippet',chart:'mostPopular'}, function(err, resp) {
console.log(resp);
console.log(err);
});
});
Insert youtube video using Service Account and googleapis module:
var google = require('googleapis');
var youtube = google.youtube('v3');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
youtube.videos.insert({auth:authClient,part:'snippet,status,contentDetails'},function(err,resp)
console.log(resp);
console.log(err);
});
});
Insert/Upload API Returned below Error:
{ errors:
[ { domain: 'youtube.header',
reason: 'youtubeSignupRequired',
message: 'Unauthorized',
locationType: 'header',
location: 'Authorization' } ],
code: 401,
message: 'Unauthorized' }
Insert youtube video using Service Account and ResumableUpload module:
var google = require('googleapis');
var ResumableUpload = require('node-youtube-resumable-upload');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
var metadata = {snippet: { title: 'title', description: 'Uploaded with ResumableUpload' },status: { privacyStatus: 'private' }};
var resumableUpload = new ResumableUpload(); //create new ResumableUpload
resumableUpload.tokens = tokens;
resumableUpload.filepath = 'youtube.3gp';
resumableUpload.metadata = metadata;
resumableUpload.monitor = true;
resumableUpload.eventEmitter.on('progress', function(progress) {
console.log(progress);
});
resumableUpload.initUpload(function(result) {
console.log(result);
return;
});
});
Insert/Upload API Returned below Error:
{ 'www-authenticate': 'Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token',
'content-type': 'application/json; charset=UTF-8',
'content-length': '255',
date: 'Tue, 16 Sep 2014 10:21:53 GMT',
server: 'UploadServer ("Built on Aug 18 2014 11:58:36 (1408388316)")',
'alternate-protocol': '443:quic,p=0.002' }
Screen shot attached for "How to get google key?"
Conclusion: Uploading a video without user permission is not possible.