I'm writing in Node using passport.js to authenticate.
console.log(req.user);
returns
{ group: 'CuManager',
password: 'password',
username: 'administrator',
cu_id: 2,
_id: 569fd3f4328ef124be533caf }
but
console.log(req.user.cu_id);
returns
undefined
I was thinking that cu_id property maybe is not available due to serialization/deserialization, but it's there. I just can't access it.
How can I do that?
I need it for
find({cu_id : req.user.cu_id})
BTW I can't help thinking passport.js is little overcomplicated (maybe we just don't get along). What else can I use to authenticate users in Node (I use express)?
If req.user is a Mongoose document, you should probably add cu_id to the proper schema.
Otherwise you can use something like req.user.toObject().cu_id to access the property, or make sure that somehow the result of doc.toObject() is assigned to req.user.
As for a Passport-replacement: this depends on how exactly you want to authenticate your users. If you're POST'ing a login form to an Express route, you can perform the password validation and session setup yourself.
try parsing it in JSON.
JSON.parse(req.user)['cu_id']
Related
Hi I'm trying to build a NestJS API and wanna learn the best practices to do it.
So I was wondering why the documentation of Nest JS
https://docs.nestjs.com/security/authentication
is providing an example of authentication with coupling passport-local and passport-jwt strategies?
Couldn't it be possible to just use the passport-jwt?
If the answer is, yes but it's not a good practice, could you provide explanations.
And if the answer is yes and it's the best practice, do you have any idea why they put an example that is not using best practices on such an important subject like authentication?
If I remember well the documentation, from the time I did my own authentication with Nest, the jwt and the local strategies are 2 ways to validate your users access but can be used in complementary.
The local strategy allow your server to validate the user with its username and password. So it will work well for a login endpoint, where the user fill the login form of your app.
Using this first step, you can use the jwt token api to create a token that will identify the user. You can set for example this token in a cookie, to be able to access it on your server when the user will make other requests.
Now, the jwt strategy will be perfect to validate the user by checking its datas and its signature in the token.
So to answer your question, you can of course use only one of this 2 strategies, but you will need to implement what they do on your own.
For example, the local strategy will be really easy to imitate by a simple endpoint in a resolver or a controller which check user information (username and password) in your DB, and set a cookie if succeed or respond an unauthorized if it failed
Hope what I say make sens !
Couldn't it be possible to just use the passport-jwt?
Yes, is possible use login controller without passport-local.
Passport-local only receibe two params (username and password) and you need implement validation, the returned value is pass how "user" propertie in Query object.
You can omit passport-local, implement the login controller with a loginDto in the #Body and validate credentials, are the same.
Example:
#Post('/auth/login')
async login(#Body() loginUserDto: LoginUserDto){
user = validation.....
if !(user) throw new UnauthorizedException();
return generateJwt(user);
}
where LoginUserDto can be
export class LoginUserDto {
#ApiProperty()
#IsString()
#IsLowercase()
#IsNotEmpty()
username: string;
#ApiProperty()
#IsNotEmpty()
#IsString()
password: string;
}
passport-jwt is only for validate the jwtoken sent by the user to privates routes of resources (endpoints).
The answer to the question if it is good practice, i don't know, for me is the same.
I followed the docs,
https://docs.mongodb.com/realm/node/manage-email-password-users/#node-manage-email-password-users
app.emailPasswordAuth.registerUser(email, password);
It complains registerUser is undefined.
By following the type interface, I tried realmApp.auth.emailPassword.registerUser, it complains registerUser is not a function.
I have checked email/password user authentication, which is on.
Can anyone tell me what could possibly go wrong here?
I couldn't find any example that is using Node.js to register a user with email and password.
Figured it out.
The docs should be updated to realmApp.auth.emailPassword.registerEmail(email, password);
I'm using Sails.js framework, and I have User model with login field.
I also have User controller that allows me to send request like
http://localhost:1337/user/:id
And it returns given user data. However I'd prefer to use user login instead of user id so I could use /user/mylogin instead of /user/564a0aacecf0e8fb20c38a4e. Is there any way to do it without creating routes myself (I like how sails handle all default routes including relations like /user/:id/comments and I dont want to rebuild all of those just to use login instead of id)
You could do /user?login=username. This is handled by sails's blueprint api: http://sailsjs.org/documentation/reference/blueprint-api/find-where
If you really want it you can have it. But you have to get your hands a bit dirty. There are a few possibe ways. But I am pointing you out the easiest way seemed to me.
Add a route like following in your config/routes.js.
'/user/:myLogin': {
controller: 'user',
action:'getUserByUserLogin'
}
Add an action named getUserByUserLogin in your
api/controller/UserController.js. You can access the myLogin
value from request object from the controller action with
req.param("myLogin").
module.exports = {
getUserByUserLogin: function(req, res){
var myLogin = req.param("myLogin");
/* Do whatever you want */
}
};
I'm using passport to authenticate users at my site. Users can register orders, which have and foreignKey (ObjectId) to the User object.
Example-objects (written as mongoose schemas):
var orderSchema = new mongoose.Schema({
...
address: String,
_userID: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'}
});
var userSchema = new mongoose.Schema({
email: String,
});
Mongoose will create the primary key for each object.
My question is; is it enough to check if req.user._id === order._userID? Or can the req.user object be tampered with? Can I trust that req.user._id is the id of the logged in user?
I've found a couple of good resources, but it's not exactly what I'm asking of.
http://toon.io/articles/understanding-passportjs-authentication-flow/
http://passportjs.org/guide/authenticate/
So the question:
can the req.user object be tampered with?
Is difficult to answer, since you could have code within your application that will have access to your request object, and within it, modify the user. It's important to understand what code you have running within the flow of each request for anyone really, but especially those concerned about the security of their application. With that said, I can at least point you to where in the code this is established, and you can trace it with a debugger to assure yourself of the flow.
As you've mentioned, the passport documentation discusses authentication configuration options in their guide, and by default will process "logging in" the user when your strategy dictates successful authentication. You can provide a custom callback (mentioned in the referenced documentation above) to process this as well. In the end, it's important that req.logIn is called (which is done by default without any custom callbacks provided). Here's a link to the source. (Passport extends the request object via this code to provide helper functions which it later uses.)
The specific line you maybe interested in is here, which assigns to the req object the property user with a value of the authenticated user:
this[property] = user;
From there on, you have access to the logged in user under req.user, and their ID under req.user.id. Again note that this logIn function should only be called when the passport strategy states that successful authentication has occurred. But in this way, passport has provided you with a way of easily authenticating the user, and then getting access to this user via the request object.
I was looking for a way to let my client authorize with the facebook JS SDK and then somehow transfer this authorization to my node server (so it can verify requests with the fb graph api)
I stumbled across:
https://github.com/jaredhanson/passport-facebook/issues/26
&
https://github.com/drudge/passport-facebook-token
what seems to be an entirely different strategy from passport-facebook.
Am I correct when assuming that:
One logs in with the fb JS SDK, and then the facebook-token strategy somehow extracts the token and fb id from the document or body object?
Or is there any other decent way to achieve this? I'm namely trying to avoid the redirects enforced by the server SDKs
I've spent a couple of days this week trying to figure out the best way to use Facebook Authentication for a private API, using passport.js — passport-facebook-token is perfect for this.
You are correct in assuming these are two separate authentication strategies. You don't need passport-facebook installed to use passport-facebook-token.
If you have Facebook authentication implemented in the client-side JS (or iOS etc.), and are looking for a way to then authenticate API requests using your user's Facebook authToken, passport-facebook-token is a really elegant solution.
passport-facebook-token works totally independently of passport-facebook, and basically handles the redirects required by Facebook internally, before passing the request along to your controller.
So to authenticate an API route using passport-facebook-token, you'll need to set up a passport strategy like so:
passport.use('facebook-token', new FacebookTokenStrategy({
clientID : "123-your-app-id",
clientSecret : "ssshhhhhhhhh"
},
function(accessToken, refreshToken, profile, done) {
// console.log(profile);
var user = {
'email': profile.emails[0].value,
'name' : profile.name.givenName + ' ' + profile.name.familyName,
'id' : profile.id,
'token': accessToken
}
// You can perform any necessary actions with your user at this point,
// e.g. internal verification against a users table,
// creating new user entries, etc.
return done(null, user); // the user object we just made gets passed to the route's controller as `req.user`
}
));
It's worth noting that the User.findOrCreate method used in the passport-facebook-token Readme is not a default mongo/mongoose method, but a plugin that you'll have to install if you want it.
To use this auth strategy as middleware for any of your routes you'll need to pass it an access_token object either as a URL parameter, or as a property of the request body.
app.get('/my/api/:access_token/endpoint',
passport.authenticate(['facebook-token','other-strategies']),
function (req, res) {
if (req.user){
//you're authenticated! return sensitive secret information here.
res.send(200, {'secrets':['array','of','top','secret','information']});
} else {
// not authenticated. go away.
res.send(401)
}
}
NB. the access_token property is case-sensitive and uses an underscore.
The documentation for passport-facebook-token isn't extensive, but the source is really well commented and pretty easy to read, so I'd encourage you to take a look under the hood there. It certainly helped me wrap my head around some of the more general ways that passport works.