I ran into some issues regarding the JWT user being null after a succesfull login.
Did some debugging in the callbacks and saw the following:
2 {
token: {
token: {
name: null,
email: null,
picture: null,
sub: 'e1d4c887-0257-4543-be37-c9b297e2cce6'
},
user: {
id: 'e1d4c887-0257-4543-be37-c9b297e2cce6',
emailVerified: '2022-09-06T09:54:24.163Z',
name: null,
email: null,
image: null
},
account: {
providerAccountId: 'test#test.com',
type: 'email',
provider: 'email'
},
isNewUser: false,
iat: 1662458064,
exp: 1665050064,
jti: '521054a5-7ead-43fc-94f4-f5eb7fffde43'
}
}
I read through the docs and noticed that the correct callback flow would be: signin -> JWT -> Session.
It is possible to return the user object found within the signIn callback, but this is not getting passed into the JWT callback.
Due to the fact that some properties like isNewUser are filled in correctly, could the missing user info be related to a DB issue?
What are some things I could further check in the hopes of solving this issue?
Related
I am facing this issue in integrating Google SignIn flow. The problem I am facing is that after the user successfully sign in program control trigger actions_intent_SIGN_IN intent in the code. From where I can get user details but I am noticing that sometimes conv->user->profile doesn't have the profile information while other time it has. Also When it doesn't have profile information, next time when I invoke some other intent it gets the user token.
This is the Payload I am getting on SignIn Intent.
User {
raw:
{ userStorage: '{"data":{}}',
lastSeen: '2018-10-04T11:17:50Z',
locale: 'en-US',
userId: 'XXXXXXXXXXXX' },
storage: {},
_id: 'XXXXXXXXXXXXXXXXXXXX',
locale: 'en-US',
permissions: [],
last: Last { seen: 2018-10-04T11:17:50.000Z },
name: Name { display: undefined, family: undefined, given: undefined },
entitlements: [],
access: Access { token: undefined },
profile: Profile { token: undefined }
}
As we can see under the profile section token and payload fields should be present. But most of the times it gets missing. Does anyone knows how to fix this ?
Did you try checking whether sign-in is successful with
app.intent('actions_intent_SIGN_IN', (conv, params, signin) => {
if (signin.status === 'OK') {
//do something
}
}
I'm having trouble with this seemingly trivial stuff, harrrr!
I have this user document:
userData = {
account: {
type: 'free'
},
profile: {
name: 'Artem',
},
username: 'aaa#gmail.com',
password: '123'
};
Which I'm sending client-side: Accounts.createUser(userData);
Then server side I want to check if account type equals 'free'. If it doesn't - I want to abort new user creation (and hopefully throw error client side)
There are 2 functions which I've found in the docs that presumably can help me do it:
Accounts.validateNewUser
Problem: it receives 'trimmed-down' user object which doesn't contain properties other than profile, username, password, email. Thus I cannot validate account.type as it doesn't exist on user object being validated.
Accounts.onCreateUser
Problem: it is called after a generic user object is created and there is no way I can cancel inserting new document in Users collection. It absolutely requires to return a user document. If I return undefined it throws errors on server:
Exception while invoking method 'createUser' Error: insert requires an argument
It also doesn't allow to throw method errors (as it's not a method) -> thus I cannot log error client side.
You can use Accounts.validateNewUser with little change to your data structure:
userData = {
profile: {
name: 'Artem',
account : {
type : 'free'
}
},
username: 'aaa#gmail.com',
password: '123'
};
Then you should be able to access data you need.
As far as I remember there were some discussion on meteor forum about removing profile field, that's why I'm solving this kind of problems in different way. For me Meteor.users is collection which should not be changed for sake of peace in mind - it could be changed by future version of meteor. My approach require to write more code in the beginning, but later it pays off, because you have place to store data about user and Meteor.users collection has docs with minimal amount of data.
I would use jagi:astronomy#0.12.1 to create schema and custom methods. In general I would create new collection UserAccounts with schema:
UserAccount = new Astro.Class( {
name: 'UserAccount',
collection: 'UserAccounts',
fields: {
'userId' : {type: 'string'},
'type' : {type: 'string', default:'free'}
},
} )
and add schema to Meteor.users :
User = new Astro.Class( {
name: 'User',
collection: Meteor.users,
fields: {
'services' : {type: 'object'},
'emails' : {type: 'array'}
},
methods:{
account : function(){
return UserAccounts.findOne({userId:this._id})
}
}
} )
The usage looks like this:
var user = Meteor.users.findOne();
user.account().type
In summary:
Accounts.onCreateUser : always allow to create user account and always create UserAccount which corresponds to it ( with field userId)
I am creating default users on the server with a Meteor startup function. I want to create a user and also verify his/her email on startup (I'm assuming you can only do this after creating the account).
Here's what I have:
Meteor.startup(function() {
// Creates default accounts if there no user accounts
if(!Meteor.users.find().count()) {
// Set default account details here
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
roles: ['webmaster', 'admin']
};
// Create default account details here
Accounts.createUser(barry);
Meteor.users.update(<user Id goes here>, {$set: {"emails.0.verified": true}});
}
});
As I said, I assume the user has to be created first before setting the the verified flag as true (if this statement is false please show a solution to making the flag true in the creation of the user).
In order to set the email verified flag to be true I know I can update the user after creation using Meteor.users.update(userId, {$set: {"emails.0.verified": true}});.
My problem is, I don't know how to get the userID of my newly created user, how do I do that?
You should be able to access the user id that is returned from the Accounts.createUser() function:
var userId = Accounts.createUser(barry);
Meteor.users.update(userId, {
$set: { "emails.0.verified": true}
});
Alternatively you can access newly created users via the Accounts.onCreateUser() function:
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
isDefault: true, //Add this field to notify the onCreateUser callback that this is default
roles: ['webmaster', 'admin']
};
Accounts.onCreateUser(function(options, user) {
if (user.isDefault) {
Meteor.users.update(user._id, {
$set: { "emails.0.verified": true}
});
}
});
I am using AngularFire $authWithPassword(credentials[, options]) for login. I assume [options] is "remember" with value of default, sessionOnly, none, as described here.
I tried all 3, I can not see any difference in my mobile app. I logged in my app, then kill/close my app, restart it. All 3 options let my app persist/remember username and password and logged in. Should at least None forget authentication data?
This is the code I use for authentication:
var _remember="default";
if (!$scope.isAutoLogin){ _
remember="none";
//"sessionOnly";
};
auth.$authWithPassword({ email: user.email, password: user.password, remember:_remember })
.then(function (authData) {
console.log("Logged in as:" + authData.uid);
}).catch(function (error) {
If I see it correctly it is just a matter of syntax, your login should be like this:
auth.$authWithPassword({
email : user.email,
password : user.password
}, {
remember: "sessionOnly"
});
Using simple schema and accounts-password. I'm trying to add in an initial account on start-up, but the email and password are not appearing.
Schemas.User = new SimpleSchema({
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
profile: {
type: Schemas.UserProfile,
optional: true
}
});
and
Meteor.startup(function () {
Meteor.users.remove({});
if (Meteor.users.find().count() == 0) {
Accounts.createUser({
username: "newuser",
emails: [{address:"test#test.com", verified:true}],
password:"mypassword"
});
}
console.log(Meteor.users.find().fetch());
}
Gives us:
[{_id: 'xxx', username:'newuser'}]
No email or password. No errors. Thoughts?
New users in this system can only be added by existing users, so I haven't been able to test the user submission form.
Accounts.createUser takes a String as an email property for the options parameter. As for the password problem, it is maybe due to the lack of a services property in your schema. Add to your Schemas.User the following property:
Schemas.User = new SimpleSchema({
// ...
services: {
type: Object,
optional: true,
blackbox: true
}
}
Finally, the Accounts.createUser documentation (see first link) states:
On the client, you must pass password and at least one of username or email — enough information for the user to be able to log in again later. On the server, you do not need to specify password, but the user will not be able to log in until it has a password (eg, set with Accounts.setPassword).
It seems to not apply in your case, but as a last resort, try to call Accounts.setPassword(userId, "mypassword") afterwards. The user's id is returned by Meteor.createUser.