How to get Google+ profile with Meteor.loginWithGoogle? - meteor

I'm looking for a working example of Meteor.loginWithGoogle (with meteor 0.6.4.1).
I found this one for loginWithGitHub (https://www.eventedmind.com/posts/meteor-customizing-login) that works fine with GitHub.
It works fine without parameters as show here on client side :
Template.user_loggedout.events({
"click #login": function(e, tmpl){
Meteor.loginWithGoogle({
}, function (err) {
if(err) {
//error handling
alert('error : '+err.message);
} else {
}
});
}
});
with the Accounts params on server side :
Accounts.loginServiceConfiguration.remove({
service: 'google'
});
Accounts.loginServiceConfiguration.insert({
service: 'google',
clientId: 'XXXXXX',
secret: 'YYYYYY'
});
In this case how can i get currentUser information especially the mail ?
Is there a way to get the Google+ profile of the user (if he has one and allows this), the user's avatar for example ?
What are the needed parameters for requestPermissions: , what can i get with this ?
Thanks

After some research i build my own example available here : https://github.com/lc3t35/googlelogin
Thanks to :
https://github.com/m2web/githublogin
https://github.com/ananta-IO/marq
Meteor/MongoDB see available fields for publish?
https://github.com/mrtnbroder/meteor-snippets/blob/master/snippets/js/Accounts/loginWithGoogle.sublime-snippet
https://developers.google.com/accounts/docs/OAuth2Login#obtaininguserprofileinformation

Related

Meteor - Slack oAuth2 Accounts.LoginCancelledError

I am using in my Meteor application Slack package: acemtp:accounts-slack and Sign in with Slack button. Unfortunately I am getting an error and cannot login. I am getting following error in console:
"No matching login attempt found",
errorType: "Accounts.LoginCancelledError"
Button redirects me to the following link: https://slack.com/oauth/authorize?client_id=188243231058.189281460071&response_type=code&scope=identity.basic,identity.email,identity.avatar&redirect_uri=http://localhost:3000/_oauth/slack?close&state=eyJsb2dpblN0eWxlIjoicG9wdXAiLCJjcmVkZW50aWFsVG9rZW4iOiIzWktaaWFhdGNRNkpheld5WiIsImlzQ29yZG92YSI6ZmFsc2V9
and response is: 404 File Not Found
I've already added to my Slack application following redirect urls:
http://localhost:3000/_oauth/slack?close
http://localhost:3000/
Unfortunately it does not work. I am not sure what happened. It was working week ago and stopped yesterday. Users can't sign in.
This is my loginWithSlack method:
Meteor.loginWithSlack({requestPermissions: ["identity.basic", "identity.email", "identity.avatar"]}, (error) => {
if (error) {
$notification({
type: 'error',
title: 'Signup with slack error',
message: error.error ? error.error.message : JSON.stringify(error)
});
console.log(error);
slackLog.error(error);
} else {
this.$router.push({name: 'home'})
Meteor.call('loginSlackUpdate', (error) => {
if (error) {
$notification({
type:'warning',
title: "Error activating account",
message: error.error ? error.error.message : JSON.stringify(error)
});
slackLog.error(error);
}
});
}
});
The '?' in the redirect_uri is no longer accepted by Slack as a valid character. You can remove it by configuring the loginStyle property when configuring your Slack service (in your server side application code) :
ServiceConfiguration.configurations.upsert(
{ service: 'slack' },
{
$set: {
loginStyle: "redirect",
clientId: "1292962797", // See table below for correct property name!
secret: "75a730b58f5691de5522789070c319bc"
}
}
);
Link is here : http://docs.meteor.com/api/accounts.html#service-configuration
For more details, you can check this issue out too : https://github.com/meteor/meteor/issues/2758
Hope this helps!

How to populate client-side Meteor.user.services after OAuth with built-in accounts-ui package in Meteor v1.4+?

I'm using accounts-ui and accounts-google in Meteor v1.4.1. I can't get the user.services object to appear scoped in the client code. In particular, I need google's profile picture.
I've configured the server-side code to authenticate with Google like so:
import { Meteor } from 'meteor/meteor';
import { ServiceConfiguration } from 'meteor/service-configuration';
const services = Meteor.settings.private.oauth;
for (let service of Object.keys(services)) {
ServiceConfiguration.configurations.upsert({
service
}, {
$set: {
clientId: services[service].app_id,
secret: services[service].secret,
loginStyle: "popup"
}
});
}
...and the client side code to configure permissions like so:
Accounts.ui.config({
requestPermissions: {
google: ['email', 'profile']
},
forceApprovalPrompt: {
google: true
},
passwordSignupFields: 'EMAIL_ONLY'
});
When users click the 'Sign-In with Google' button, a pop-up appears and they can authenticate. No prompt appears, however, despite forceApprovalPrompt being set to true for google.
The big issue is that when I execute this,
const user = Meteor.user();
console.log(user.services);
anywhere in client code, I do not see the expected user services information. I check my database and it is definitely there for the taking:
$ mongo localhost:27017
> db.users.find({})
> ... "services" : { "google" : { "accessToken" : ... } } ...
I'm curious what I'm missing? Should I explicitly define a publish function in order for user services data to exist in the client?
The services property is intentionally hidden on the client side for security reasons. There are a couple of approaches here :
Suggestions
My preferred one would be to expose a meteor method to bring you the
public keys and avatars you might need in the few places you'd need
them.
On a successful login, you could record the data you need somewhere in the user object, but outside of the services property.
As you said, you could make a new publication which explicitly specifies which fields to retrieve and which ones to hide. You have to be careful what you publish, though.
Code Examples
Meteor methods:
// server
Meteor.methods({
getProfilePicture() {
const services = Meteor.user().services;
// replace with actual profile picture property
return services.google && services.google.profilePicture;
}
});
// client
Meteor.call('getProfilePicture', (err, profilePicture) => {
console.log('profile picture url', profilePicture);
});
Update on successful user creation (you might want to have a login hook as well to reflect any avatar/picture changes in google):
// Configure what happens with profile data on user creation
Accounts.onCreateUser((options, user) => {
if (!('profile' in options)) { options.profile = {}; }
if (!('providers' in options.profile)) { options.profile.providers = {}; }
// Define additional specific profile options here
if (user.services.google) {
options.profile.providers.google = {
picture: user.services.google.picture
}
}
user.profile = options.profile;
return user;
});
Publish only select data...
// Server
Meteor.publish('userData', function () {
if (this.userId) {
return Meteor.users.find({ _id: this.userId }, {
fields: { other: 1, things: 1 }
});
} else {
this.ready();
}
});
// Client
Meteor.subscribe('userData');

Meteor - template not updated after user sign in

I built an app with simple user login, using Accounts-unstyled. It all works fine, except that the template showing user data is not re-rendered with the user logs in. However if the user reloads the page, then his data is present.
My code doesn't really contain anything related to user, except for fetching the correct user's data. Do I need to manually trigger a refresh after the login?
The app is at www.barelinks.in. Test login: user=test; password=pwdpwd.
Upon first login nothing changes, but if you reload you will see the user's data.
Here is the code for the subscription:
if(Meteor.isServer) {
Meteor.publish('links', function linksPublication(userId) {
return Links.find({ user: userId });
});
}
And the helper fetching the right data (the Regex is for the search feature):
Template.body.helpers({
links: function() {
var nbSkip = linksPerPage*(Template.instance().page.get() - 1);
var queryRegex = new RegExp(Template.instance().query.get(), 'i');
return Links.find({ user: Meteor.userId(), title: queryRegex }, { sort: { createdAt: -1 }, limit: linksPerPage, skip: nbSkip });
},
});
Thanks!
I recognized that the content is updated when refreshing the page in a logged in state. Than you can switch forth and back and everything works as expected. I came usually across this behavior when the data subscription is not as it should be.
The server automatically updates the data according to a change of logged in state, you need to rely on the this.user property in the publish function.
if(Meteor.isServer) {
Meteor.publish('links', function linksPublication() {
return Links.find({ user: this.userId });
});
}

Trying to publish users in Meteor

I'm quite new in Meteor and I got an issue: I added some information to users and I'd like to be able to see it in a view.
So I create my users, here is my event:
Accounts.createUser({
username: username,
email: email,
password: password,
firstname:firstname,
lastname:lastname,
chief:chief
},
function(error){
if(error){
alert(error.reason)
}else{
Router.go('home');
}
});
Accounts.onCreateUser(function(options,user){
user.firstname = options.firstname;
user.lastname = options.lastname;
user.chief = options.chief;
return user;
});
then I publish my collection to get access on my client side of the app:
Meteor.publish("personaldata", function () {
return Meteor.users.find({_id: this.userId});
});
And without doing anything else I got an issue on my app: there is no error message on my command prompt, but when I open my app I got an Ironn:Router message. Here is the message:
'organize your application'
Router.route('/', function () {
this.render('Home', {
data: function () {
return Items.findOne({_id: this.params._id});
}
});
});
Yes the whole part is the message. I tried to subscribe to the collection in 'home' to settle the issue but it doesn't work, the same message is displayed.Does someone know why this message is displayed ? How can I have access to those data? Isn't it the proper way?
Hope you guys can figure out what the problem is, thanks.
Found the problem...
As I'm stupid I put my publish in the lib directory, so this was on both the server and the client side... Meteor didn't know what to do with it on the client side.

meteor.js : find users by email

In my meteor.js app, I'm trying to write a simple admin page which can find a user by his/her email address.
I can see that in the Meteor.users collection there is an 'emails' array, which has objects like so
{ address : 'foo#foo.com',
verified : false
}
Normally in Mongodb I can search inside this 'emails' array like so :
Meteor.users.find({ emails.address : 'foo#foo.com' });
But this query is throwing an error :
While building the application:
client/admin.js:224:41: Unexpected token .
Aka Meteor doesn't like the nested query...
Any ideas on how to query the Meteor.users collection by email address ?
You can also use what you had, just put it in quotes:
Meteor.users.find({ "emails.address" : 'foo#foo.com' });
If on the server, Meteor has a special function for this :
Accounts.findUserByEmail(email).
I believe this is the recommended way.
Emails holds an array of emails. Each email has an address.
Try { emails: { $elemMatch: { address: "foo#foo.com" } } }.
Information on $elemMatch is here.
Information on emails as an array is here.
By default, Meteor only publishes the logged in user and you can, as you mention, run queries against that user. In order to access the other users you have to publish them on the server:
Meteor.publish("allUsers", function () {
return Meteor.users.find({});
});
And subscribe to them on the client:
Meteor.subscribe('allUsers');
And run the following command
Meteor.users.find({"emails": "me#example.com"}).fetch()
OR
Meteor.users.find({"emails.0": "me#example.com"}).fetch()
Refer this
If you want to find all emails inside Accounts array, and do an insensitive query:
const hasUser = Meteor.users.findOne({
emails: {
$elemMatch: {
address: {
$regex : new RegExp(doc.email, "i")
}
}
}
});
One possible workaround, if this works on the server but not the client, is to use a users_by_email method on the server:
if (Meteor.isServer) {
Meteor.methods({
'get_users_by_email': function(email) {
return Users.find({ emails.address: email }).fetch();
}
});
}
if (Meteor.isClient) {
foo_users = Meteor.call('get_users_by_email', 'foo#bar.baz');
}

Resources