I follow the instruction to send the id token of the Google account to the back end server to be authenticated but it seems like the token does not exist.
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
var id_token = googleUser.getAuthResponse().id_token;
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
console.log('Token: ' + id_token);
}
The line Token: is not printed in the console. Anybody could tell me what's going on? Much appreciated
Related
I am trying to receive notifications in an Expo React Native App.
The notifications will be sent using Azure Notification Hub REST API
I followed the steps below :
Added the Android project in Firebase Console
To get the Server Key I followed - Firebase messaging, where to get Server Key?
Configured the FCM ServerKey in Azure Notification Hub
Added the google-services.json at the root in my React Native App and modified app.json as mentioned in - https://docs.expo.dev/push-notifications/using-fcm/
To register in ANH, we first need the SAS Token - https://learn.microsoft.com/en-us/rest/api/notificationhubs/common-concepts I generated the token with the following code
const Crypto = require('crypto-js');
const resourceURI =
'http://myNotifHubNameSpace.servicebus.windows.net/myNotifHubName ';
const sasKeyName = 'DefaultListenSharedAccessSignature';
const sasKeyValue = 'xxxxxxxxxxxx';
const expiresInMins = 200;
let sasToken;
let location;
let registrationID;
let deviceToken;
function getSASToken(targetUri, sharedKey, ruleId, expiresInMins) {
targetUri = encodeURIComponent(targetUri.toLowerCase()).toLowerCase();
// Set expiration in seconds
var expireOnDate = new Date();
expireOnDate.setMinutes(expireOnDate.getMinutes() + expiresInMins);
var expires =
Date.UTC(
expireOnDate.getUTCFullYear(),
expireOnDate.getUTCMonth(),
expireOnDate.getUTCDate(),
expireOnDate.getUTCHours(),
expireOnDate.getUTCMinutes(),
expireOnDate.getUTCSeconds()
) / 1000;
var tosign = targetUri + '\n' + expires;
// using CryptoJS
//var signature = CryptoJS.HmacSHA256(tosign, sharedKey);
var signature = Crypto.HmacSHA256(tosign, sharedKey);
var base64signature = signature.toString(Crypto.enc.Base64);
//var base64signature = signature.toString(CryptoJS.enc.Base64);
var base64UriEncoded = encodeURIComponent(base64signature);
// construct autorization string
var token =
'SharedAccessSignature sr=' +
targetUri +
'&sig=' +
base64UriEncoded +
'&se=' +
expires +
'&skn=' +
ruleId;
console.log('signature:' + token);
return token;
}
I then called the create registration API - https://learn.microsoft.com/en-us/rest/api/notificationhubs/create-registration-id
The registrationID has to be extracted from the response header of the API Call
I used the following code to generate the ANH Regsitration ID
async function createRegistrationId() {
const endpoint =
'https://xxxxxx.servicebus.windows.net/xxxxxxx/registrationIDs/?api-version=2015-01';
sasToken = getSASToken(resourceURI, sasKeyValue, sasKeyName, expiresInMins);
const headers = {
Authorization: sasToken,
};
const options = {
method: 'POST',
headers: headers,
};
const response = await fetch(endpoint, options);
if (response.status !== 201) {
console.log(
'Unbale to create registration ID. Status Code: ' + response.status
);
}
console.log('Response Object : ', response);
for (var pair of response.headers.entries()) {
//console.log(pair[0] + ': ' + pair[1]);
}
location = response.headers.get('Location');
console.log('Location - ' + location);
console.log('Type - ' + response.type);
registrationID = location.substring(
location.lastIndexOf('registrationIDs/') + 'registrationIDs/'.length,
location.lastIndexOf('?api-version=2015-01')
);
console.log('Regsitration ID - ', registrationID);
return location;
}
Next step was to update this registration ID in ANH with the Native Device Token
I used expo-notifications package and the method getDevicePushTokenAsync() method to get the native device token
async function registerForPushNotificationsAsync() {
let token;
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const {
status
} = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
token = (await Notifications.getDevicePushTokenAsync()).data;
console.log(token);
} else {
alert('Must use physical device for Push Notifications');
}
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
return token;
}
The native device token was in the following format on Android device
c6RI81R7Rn66kWZ0rar3M2:APA91bEcbLXGwEZF-8hu1yGHfXgWBNuxr_4NY_MR8d7HEzeHAJrjoJnjUlneAIiVglCNIGUr11qkP1G4S76bx_H7NItxfQhZa_bgnQjqSlSaY4-oCoarDYWcY-Mz_ulW8rQZFy_SA6_j
I then called the updateRegistrationId API - https://learn.microsoft.com/en-us/rest/api/notificationhubs/create-update-registration
async function updateRegistraitonId() {
//IF you use registrationIDs as in returned location it was giving 401 error
const endpoint =
'https://xxxxx.servicebus.windows.net/xxxxxxx/registrations/' +
registrationID +
'?api-version=2015-01';
const endpoint1 = location;
const headers = {
Authorization: sasToken,
'Content-Type': 'application/atom+xml;type=entry;charset=utf-8',
};
//Remember to create well-formed XML using back-ticks
//else you may get 400 error
//If you use the tags element it was giving an error
const regDATA = `<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<GcmRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
<GcmRegistrationId>${deviceToken}</GcmRegistrationId>
</GcmRegistrationDescription>
</content>
</entry>`;
const options = {
method: 'PUT',
headers: headers,
body: regDATA,
};
const response = await fetch(endpoint, options);
if (response.status !== 201) {
console.log(
'Looks like there was a problem. Status Code: ' + response.status
);
console.log('Response Object : ', response);
//return;
}
}
According to API documentation, I should get 201 response, I got 200 response code . I am not sure if this is the issue
After this I had the notification handling code to recieve the notification,similar to the code in - https://docs.expo.dev/versions/latest/sdk/notifications/
I then tried to send notification using Test Send from ANH, it failed with the error -
**
"The Token obtained from the Token Provider is wrong"
**
I checked in ANH Metrics, the error was categorized as GCM Authentication error, GCM Result:Mismatch SenderId
I tried to check for documentation to add the SenderId , but I couldnt find anyway to inlcude the SenderId also in the payload of updateRegistration call (in xml atom entry)
I tried to use the device token and send directly from Firebase Console, I did not receive it either.
I used the Direct Send API of Azure notification Hub but still did not receive anything
I am suspecting there could be some issue in the way I am handling notifiations in the client device, I can fix that later , but first I will have to resolve the error I am getting in Test Send in Azure NH
Any help to be able to successfully send using Test Send in ANH or pointers ahead for next steps will be much appreciated
I have created an Attachment with image:
{
"_rid": "xD4vALTE7QBAAwAAAAAAAA==",
"Attachments": [
{
"contentType": "image/jpeg",
"id": "10b91d7d-2e5e-466e-a896-3ee54baff4dc",
"media": "/media/xD4vALTE7QBAAwAAAAAAALobDgYB",
"_rid": "xD4vALTE7QBAAwAAAAAAALobDgY=",
"_self": "dbs/xD4vAA==/colls/xD4vALTE7QA=/docs/xD4vALTE7QBAAwAAAAAAAA==/attachments/xD4vALTE7QBAAwAAAAAAALobDgY=",
"_etag": "\"00000d37-0000-0000-0000-5a09602a0000\"",
"_ts": 1510563882
}
],
"_count": 1
}
What is the url to the Media object?
When I use the Cosmos .NET SDK method DocumentClient.ReadMediaAsync(string mediaLink) where mediaLink is /media/xD4vALTE7QBAAwAAAAAAALobDgY= then I can get the Media stream and display the image. But this only works when connecting to Cosmos Db Emulator, when doing the same on the Azure Cosmos DB instance, then I get this error:
Unknown server error occurred when processing this request. ActivityId: 53508de6-2456-4213-947e-4361a8118574, Microsoft.Azure.Documents.Common/1.17.99.1, documentdb-dotnet-sdk/1.19.0 Host/32-bit MicrosoftWindowsNT/6.2.9200.0
The Attachment creation with Medial upload works.
I was thinking to try to query the CosmosDB using the Postman, but I cannot figure out the url to get the Media object.
The url to the Media object is: https://[YOUR-DOCDB-HOST]/media/xD4vALTE7QBAAwAAAAAAALobDgYB
I call this as a GET request in Postman with the following Pre-Request Script:
// store our master key for documentdb
var mastKey = [YOUR-DOCUMENTDB-KEY-HERE];
console.log("mastKey = " + mastKey);
// store our date as RFC1123 format for the request
var today = new Date();
var UTCstring = today.toUTCString();
postman.setEnvironmentVariable("RFC1123time", UTCstring);
// define resourceId/Type now so we can assign based on the amount of levels
var resourceId = "[YOUR-RID-HERE]"; // _rid in attachment document
var resType = "media";
// assign our verb
var verb = request.method.toLowerCase();
// assign our RFC 1123 date
var date = UTCstring.toLowerCase();
// parse our master key out as base64 encoding
var key = CryptoJS.enc.Base64.parse(mastKey);
console.log("key = " + key);
// build up the request text for the signature so can sign it along with the key
var text = (verb || "").toLowerCase() + "\n" +
(resType || "").toLowerCase() + "\n" +
(resourceId || "").toLowerCase() + "\n" +
(date || "").toLowerCase() + "\n" +
"" + "\n";
console.log("text = " + text);
// create the signature from build up request text
var signature = CryptoJS.HmacSHA256(text, key);
console.log("sig = " + signature);
// back to base 64 bits
var base64Bits = CryptoJS.enc.Base64.stringify(signature);
console.log("base64bits = " + base64Bits);
// format our authentication token and URI encode it.
var MasterToken = "master";
var TokenVersion = "1.0";
auth = encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + base64Bits);
console.log("auth = " + auth);
// set our auth token enviornmental variable.
postman.setEnvironmentVariable("authToken", auth);
There are two variables: [YOUR-DOCUMENTDB-KEY-HERE] and [YOUR-RID-HERE]. The kicker is, you need to query attachment meta data first to get the _rid value to use in the token when requesting the media.
The authToken and RFC1123time postman variables are used in the Authorization header:
I have a Page Fragment that allows users to create an entry. When they click the send button it runs the following:
newSOEmailMessage(widget);
widget.datasource.createItem();
app.closeDialog();
This activates a Client Script that sends an email to the user which includes the values from the widget fields:
function newSOEmailMessage(sendButton) {
var pageWidgets = sendButton.root.descendants;
var currentuser = Session.getActiveUser().getEmail();
var htmlbody = currentuser + 'has created new system order for: <h1><span style="color:#2196F3">' + pageWidgets.ShowName.value + ' - ' + pageWidgets.UsersPosition.value + '</h1>' +
'<p>R2 Order #: <b>' + pageWidgets.R2OrderNumber.value + '</b>' +
'<p>Delivery Date: <b>' + pageWidgets.DeliveryDate.value.toDateString() + '</b>' +
'<p>Start of Billing: <b>' + pageWidgets.SOB.value.toDateString() + '</b>' +
'<p>Sales Person: <b>' + pageWidgets.SalesPerson.value + '</b>' +
'<p> </p>' +
'<p>Company: <b>' + pageWidgets.Company.value + '</b>' +
'<p> </p>' +
'<p>Notes: <b>' + pageWidgets.Notes.value + '</b>';
google.script.run
.withSuccessHandler(function() {
})
.withFailureHandler(function(err) {
console.error(JSON.stringify(err));
})
.sendEmailCreate(
'user#email.com',
'New order for: ' + pageWidgets.ShowName.value + ' - ' + pageWidgets.UsersPosition.value,
htmlbody);
}
All of this works fine except the "currentuser" option (after var htmlbody =). With the code above I get the following error:
Session is not defined
at newSOEmailMessage (Notifications_ClientScripts:7:45)
at SystemOrders_Add.SubmitButton.onClick:1:1
I would like "currentuser" to equal the email address (or preferably the user's actual name).
ex: "John Doe has created a new system order for..."
What am I missing?
Thank you!
Note: I already have a Directory Model setup to show user's names in a comments section for a different Model. That Model is running the following (I'm assuming I could add that to my SystemOrders model?)
// onCreate
var email = Session.getActiveUser().getEmail();
var directoryQuery = app.models.Directory.newQuery();
directoryQuery.filters.PrimaryEmail._equals = email;
var reporter = directoryQuery.run()[0];
Looks like you are mixing server and client side APIs
// It is server side API
var email = Session.getActiveUser().getEmail();
// It is client side API
var email = app.user.email;
If you want to utilize user Full Name from the directory, then you need to load it advance, for instance in app startup script:
// App startup script
// CurrentUser - assuming that it is Directory model's datasource
// configured to load record for current user.
loader.suspendLoad();
app.datasources.CurrentUser.load({
success: function() {
loader.resumeLoad();
},
failure: function(error) {
// TODO: Handle error
}
});
So, you can refer to this datasource item later in your code:
var fullName = app.datasources.CurrentUser.item.FullName;
Also, I would recommend send emails only when record is actually created:
// Sends async request to server to create record
widget.datasource.createItem(function() {
// Record was successfully created
newSOEmailMessage(widget);
});
I have tested my meteor app on dev and the verification email is sent out. But on production it is not. Could it maybe the content of smtp.js? My code is as follows:
// server/smtp.js
Meteor.startup(function () {
var smtp = {
username: 'dummy#wbs.co.za',
password: 'hw783378hjshd',
server: 'smtp.wbs.co.za',
port: 25
}
process.env.MAIL_URL = 'smtp://' + encodeURIComponent(smtp.username) + ':' + encodeURIComponent(smtp.password)
+ '#' + encodeURIComponent(smtp.server) + ':' + smtp.port;
});
// (server-side)
Meteor.startup(function() {
// By default, the email is sent from no-reply#meteor.com. If you wish to receive email from users asking for help with their account, be sure to set this to an email address that you can receive email at.
Accounts.emailTemplates.from = 'NOREPLY <no-reply#meteor.com>';
// The public name of your application. Defaults to the DNS name of the application (eg: awesome.meteor.com).
Accounts.emailTemplates.siteName = 'No Reply';
// A Function that takes a user object and returns a String for the subject line of the email.
Accounts.emailTemplates.verifyEmail.subject = function(user) {
return 'Confirm Your Email Address';
};
// A Function that takes a user object and a url, and returns the body text for the email.
// Note: if you need to return HTML instead, use Accounts.emailTemplates.verifyEmail.html
Accounts.emailTemplates.verifyEmail.html = function(user, url) {
return 'click on the following link to verify your email address: ' + url;
};
});
// (server-side) called whenever a login is attempted
Accounts.validateLoginAttempt(function(attempt){
if (attempt.user && attempt.user.emails && !attempt.user.emails[0].verified ) {
console.log('email not verified');
throw new Meteor.Error(403, 'Verification email has been sent to your email address. Use the url in the email to verify yourself.');
return false; // the login is aborted
}
return true;
});
Please help.
I am successfull to get "userID" and "access token" but unable to get name and other basic details at my destination page.
How can i get that?
Here is my code.
<div id="fb-root">
</div>
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript">
FB.init({ appId: '225565837521406', status: true, cookie: true, xfbml: true, oauth: true });
// FB.login({ scope: 'name,email,user_birthday'});
FB.getLoginStatus(function(response) {
if (response.status === 'connected')
{
var theSession=response.session;
var theSession = eval('(' + theSession + ')');
var name=response.name;
var name=eval('(' + name + ')');
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
var email=response.authResponse.email;
// alert("Name: " +name+ " UserID: " +uid+ " Access Token: " +accessToken);
document.getElementById("fb-root").innerHTML="Name: " +name+ "<br />UserID: " +uid+ "<br />Access Token: " +accessToken+ "<br />Email: " +email+ "<br />Session: " +theSession;
}
else if (response.status === 'not_authorized')
{
alert("Not Authorized..");
}
else
{
alert("nothing..");
}
});
</script>
Do a console.log of the response - you'll notice the response object contains:
An 'authResponse' object, containing an access token, user id, signed request and the expiry for the access token, and
A status field, telling you the auth status of the user.
Information about the signed request can be found here: https://developers.facebook.com/docs/authentication/signed_request/
Information about Facebook client side auth can be found here: https://developers.facebook.com/docs/authentication/
Anyway, none of this gets you information about the user. To do that, you must query the Graph API. To get basic info about the user, try:
https://graph.facebook.com/me?access_token=ACCESS_TOKEN_FROM_ABOVE. The result will be a JSON object containing the users name etc.
HTH