Create OAUTH accounts prior to signin - meteor

I have an app I am working on that has one or two "main" accounts linked to other accounts. I am using accounts-password, accounts-google, and alanning:roles currently, but I may add other OAuth providers later.
The idea is that there will be one or two users that are "admins" for a larger group, and as such I'd like to be able to allow them to add users. I don't mind if I have to go through the OAuth authorization page on first login, but I would like to be able to add the users to the Meteor.users collection and allow the admins to set things up prior to their logging in, but I am not sure how to do it at all. Can I simply add a user to the Meteor.users collection with only the email attribute of the google sub-document populated? I would guess that the email is NOT what Meteor uses to connect a stored Meteor.users document to the corresponding Google OAuth account as there is also an id attribute that seems like it might be more useful for that purpose.

So based on what you say on the comment i elaborate this DEMO, since you want to create users and add that users to some kind of "role" or "group" im using here the meteor-roles package.
allow people to create a group of users
This could be done on some differentes ways, for the demo purpose im creating 1x1 user and leater assign them a Role.
to avoid the autologin behavior you should use a Meteor.method.
//server
Meteor.methods({
createSimpleUser:function(email){
return Accounts.createUser({
email:email,
password:"test123" //you can force the user in the first login to change the password.
})
}
})
//Client
Meteor.call('createUser',"test#gmail.com")
Now that you have the user created, you should assign them a role.
So on some event handler you want,do something like this.
//this should be incide an {{#each}} or {{#with}} in order to this._id works, if not use Sessions
Meteor.users.update({_id:this._id},{$set:{group:newGroup}})
This is just the global idea, you should protect in the allow rules, who can edit the users group, you can also use template helpers like
{{if userIsInRole 'nameGroup'}}
<!-- Show content only available to users in this group -->
{{else}}
<!-- Some warning access denied template -->
{{/if}}
This process will add some stuff to the profile of the user so the app
can associate all the users together
Filter by groups.
Template.example.helpers({
groupX:function(){
return Meteor.users.find({group:"X"})
}
})
when they first login without erasing the stuff I setup for them prior
to them signing in.
Here again there could be many reasons, for example you can add some field inside the current user created.
Meteor.methods({
createSimpleUser:function(email){
return Accounts.createUser({
email:email,
password:"test123",
firstLogin:false //by default the users login is false.
})
}
})
and in the iron route, create a function(why on the router? see Overworked helpers on the David Weldon webpage).
requireEdit = function(){
var query = Meteor.users.findOne({_id:this.params._id})
if(query.firstLogin == false){
this.render('profileEditin') //do some change password here and other stuff
}else{
this.next()'
}
}
And call it on the onBeforeAction() method
This is just the idea and demo is a ugly-fast example of how it should work, good luck

Related

Save data into the Firebase user object

Using this :
firebase.auth().onAuthStateChanged(function(user){
if (user){
Firebase is returning the user, which includes a userID.
When a webpage get this object it takes the user ID, and need to access again the DB records to check some very basic stuff ( if it's a paid user, or another simple key) in order to choose the UI.
Is there away to return in this callback the user including some predefined basic info about him?
If you want to add some extra info to a user account you cannot use the User object, which has a fixed list of properties.
There are two classical approaches:
1. Create a specific User record
You create a Firestore document (or a Realtime Database node) for each user. Usually you use the User's uid as the id of the Firestore Document/RTDB node.
This means that you will need to fetch the database to get this extra user info, e.g.
firebase.auth().onAuthStateChanged(function(user){
if (user) {
firebase.firestore().collection('users').doc(user.uid).get()
.then(...)
}
//...
}
2. Use Custom Claims
If you need to store only a limited number of extra information in order to provide access control, you could use Custom Claims. This is particularly adapted for storing user roles, e.g. paid user.
Custom user claims are accessible via user's authentication tokens, therefore you can use them to modify the client UI based on the user's role or access level. See more details here in the doc.
To get the Claims in the front end, you can do as follows:
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
user.getIdTokenResult()
.then((idTokenResult) => {
// Confirm the user is a paid user.
if (!!idTokenResult.claims.paidUser) {
// Show admin UI.
showPaidUserUI();
} else {
// Show regular user UI.
showRegularUI();
}
})
.catch((error) => {
console.log(error);
});
}
//...
}
It is important to note the following section in the doc:
Custom claims are only used to provide access control. They are not
designed to store additional data (such as profile and other custom
data). While this may seem like a convenient mechanism to do so, it is
strongly discouraged as these claims are stored in the ID token and
could cause performance issues because all authenticated requests
always contain a Firebase ID token corresponding to the signed in
user.
Use custom claims to store data for controlling user access only. All other data should be stored separately via the real-time database
or other server side storage.
Custom claims are limited in size. Passing a custom claims payload greater than 1000 bytes will throw an error.

Add role in meteor user

I'm new in Meteor, and trying to build an todo app using Meteor. For user sign up and sign in, I'm using accounts-ui, accounts-password, accounts-facebook, accounts-google. In my view page, I just write {{> loginButtons}}, and all user sign in and sign up done automatically. Now my problem is how can I add here roles. I have already added alanning:roles, but can't understand how can I add roles here. Because I don't write any code. Any suggestion ???
Thanks in Advance.
You can use Accounts.onCreate on server and do following:
Roles.addUsersToRoles(joesUserId, ['manage-team','schedule-game'], 'manchester-united.com')
Roles.addUsersToRoles(joesUserId, ['player','goalie'], 'real-madrid.com')
Something like
Accounts.onCreateUser(function(options, user){
var role = ['admin'];
user.roles = role
return user;
});

Add custom field on signin form

Using meteor useraccounts package, I would like to add a custom field in signIn form (named token) to enable 2fa authentication.
Unfortunatly on AccountTemplates.addField only work with signUp form, as far as I have worked on it.
Any hint?
The accounts package has an Accounts.onLogin function that you can use to call a method and update the user account.
Accounts.onLogin(function(user) {
Meteor.call('setToken', user)
})
and then
Meteor.methods({
setToken: function(user) {
// Do some clever check
Meteor.users.update(/* Set your token */);
},
});
The advantage of using a method is that you can do some server-side check to ensure your token has not been hacked.
The answer i managed to implement was to change the pattern with a different approach, using directly Meteor API:
Set a special field on user collection: tokenverified: false
Add Meteor.onLogin (called each time you login or refresh manually the page) and Meteor.onLogout callback to set this field to false
Create a template verify2FA to deal with token and set tokenverified: true
Create an iron-router plugin ensure2FA that will check this token and redirect to the verify2FA template.

Meteor: How do I show a page when a user signs up

When a person signs up (accounts entry) it takes them to a page called "dashboard". I want it so that after they sign-up if it is the first time (for that account) that they are seeing the page it will show some sort of welcome message. Is this possible?
Thanks.
Update:
I tried this:
Accounts.onCreateUser(function(options, user) {
console.log('New account created!');
});
But it gave:
Exception while invoking method 'entryCreateUser' Error: insert requires an argument
I am using Accounts Entry. Is there any fix for this?
Without knowing more about your app it's difficult to advise on the best way for you to do this. But here are three possible approaches.
If you are creating your own signup/login events, just route to a 'welcome' route/template on signup event, and 'dashboard route/template on login.
If you are wanting to use default accounts-ui, you can use the Accounts.onCreateUser hook server side to add {'isNewUser' : true} to the user account document. Then check for this property client side to decide what template to display.
Or you can try wrapping Accounts.createUser to include the extra logic you require client side to go to your welcome route/template rather than the dashboard.
The simplest way is to set a session variable then use a helper in your template to key off of that:
In your new account code:
Session.set('isNewUser',true);
Router.go('dashboard')
HTML:
<template name='dashboard'>
{{#if newUser}}Welcome!!{{/if}
... rest of your template ...
</template>
js:
Template.dashboard.helpers({
newUser: function(){
return Session.get('isNewUser');
}
});
You'll also need code to later either delete that Session variable or set it to false.

How can I access another users (not current user) profile from the userId in Meteor?

I doing the following. Adding the current users id as userId in a collection as the author. I would like to be able to access other information in that users (not necessarily the logged in users but could be) so that I could display a profile page. The only work around I have found is to just duplicate the fields from the profile and place them in the collection.
This seems to be less than ideal. Is there a way to access this directly? I am using autopublish so I don't think there should be any permission issues. I am also using iron-router so ideally I would have a route set up like:
Router.map(function() {
...
this.route('profile', {path: '/profile', data: function() { this.params._id}});
});
If you've got autopublish on, then Meteor.users.findOne({_id: 'USERID'}) will give you that user's profile. Obviously, if you turn off autopublish you'll have to work out what information to publish.

Resources