My question is rather simple should we or should we not store a user object in the JWT's payload?
For example:
WIth user object embedded:
{
iss: "https://YOUR_NAMESPACE",
user: user, // user object from database
aud: "YOUR_CLIENT_ID",
exp: 1372674336,
iat: 1372638336
}
Or is it better to store only a unique id of a user, like so:
With just the user id embedded:
{
iss: "https://YOUR_NAMESPACE",
sub: user.id, //only user id
aud: "YOUR_CLIENT_ID",
exp: 1372674336,
iat: 1372638336
}
JSON Web Token Draft Spec: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token
You can store any kind of information about the user in your token, but I do not think it is useful to store all user informations.
As HTTP is stateless, each time a user connects on your website or web app, the token is sent to the server to authenticate the user. So this token should be as small as possible (that is the aim of the JSON Compact Serialization format of JWT).
You should store an unique information to identify the user such as its email address or its ID (aud: "YOUR_CLIENT_ID").
When needed, you can request informations about the user to the server using API calls or any other protocol.
Related
I have a custom function that validates the Shopify session token and returns the decoded JWT
{
iss: The shop's admin domain.
dest: The shop's domain.
aud: The API key of the receiving app.
sub: The user that the session token is intended for.
exp: When the session token expires.
nbf: When the session token activates.
iat: When the session token was issued.
jti: A secure random UUID.
sid: A unique session ID per user and app.
}
Then, I initialize the context with Shopify.Context.initialize({...})
How can I get the access token using:
const session = await Shopify.Utils.loadCurrentSession(req, res)
Right now, I'm saving the access token in a database during the initial install since I don't know how to use the function above with AWS API Gateway.
What should be req and res knowing that a Lambda handler has event and context as parameters?
I feel req = event. But I have no idea what res should be in this case.
I'm building an application with registration and login, so I need to verify the email after registration. After creating the user I want to send an activation mail with a jwt in get request. After successfully confirming the email and token is not expired the user is logged in.
My question is why, shouldn't I store the jwt local in an array and on the verification
request check if the token is valid and afterwards delete it from the array and set user registration status true?
Do I get any benefits if i store the token in a certain table in the database and also delete it after successful verification? Or shouldn't I delete it at all?
const token = jwt.sign(
{
email: loadedUser.email,
userId: loadedUser._id.toString(),
},
"somesupersecretkey",
{ expiresIn: "1h" }
);
res.status(200).json({ token: token, userId: loadedUser._id.toString() });
No need to store the token in a certain table in the database and you can also set its timeout after successful verification...
I am doing a project with authentication using passport js with the Strategies (Google, Facebook, Local). I am working on the google part now but there is a small problem. When users register locally I save their data to the db (email,username,hashedPassword) but now when they register/signin through google I do not have access to their password (obviously). It is required in the user schema and I do not want to create a new user schema.
Could I save the password as the user id I received from google? I really want to know the correct path I should take.
You could add another field to your schema like provider that specifies the type of authentication that was used. Then you can use the mongoose required validator to make password only required if provider is 'local.' Something like this:
const userSchema= new Schema({
firstName: String,
lastName: String,
email: String,
username: String,
provider: {
type: String,
enum: ['local', 'google', 'facebook']
},
password: {
type: String,
required: function() {
return this.provider === 'local';
}
}
});
When you go use an auth provider, they usually will give you some sort of "token", maybe on your client or on a redirect on your server (depends on your implementation).
Then you have to validate that token with the provider (how to do this depends on the documentation of each provider), because you can not plain trust that a given token is valid.
Once you have validated with the provider that the token is valid, is common that with that token you have access to some info of the user, like email, name, phone number, etc (depends on how you configure your integration) and maybe store which provider they use (fb, google, apple, etc)
Then you can save this information in your schema, and then generate a session for this user (it may be a JWT or a session stored on the db)
Now, when a user sign in, you will do the same validation process of the given token with the user sent, then you can provide a new session
In summary, the key is that instead of using user/pwd to validate against your local database to authenticate a user, they will provide a token, and you have to validate that token against the provider they selected
I work on app with an authentication using Node JS, JWT and Sequelize for the API and I'm using React JS / redux for the front part. I'm successfully implemented the login/logout/register parts for the application, but now I need to access to the current_user logged in.
I put a JWT in the localStorage, but I want to have access to the user ID, user email, user name and more informations about my user currently logged in.
Should I use Cookies ? LocalStorage ? Or should I create a currentUser method in my API ?
I'm a bit lost with this, if someone could help me find some usefull resources or advices !
Thank !
If you put that information in the payload of the JWT, then you can get it without decoding on the server or needing the secret, and can therefore put the token in LocalStorage for use whenever. By the spec, a JWT is <headerINfo>.<payloadInfo>.<signature>. So on the client, you can just do:
// given a payload object of { username: 'bob', userid: 1, email: 'bob#example.com' }
const tokenParts = token.split('.');
const encodedPayload = tokenParts[1];
const rawPayload = atob(encodedPayload);
const user = JSON.parse(rawPayload);
console.log(user.username); // outputs 'bob'
Obviously, this info is available to any client that has access to the Token, so you only want to put stuff in the payload that that's OK for.
Storing the token in LocalStorage is fine. If you need to fetch the user details, create an endpoint in your API such as getUser. You can then use jwt.decode(accessToken, JWT SECRET HERE) and return the decoded value (which will be your user) assuming the accessToken is valid.
You can make a middleware if you haven't already that will ensure that user info is always available to those routes that require it:
const auth = jwt({
secret: JWT_SECRET,
userProperty: 'payload',
algorithms: ['HS256']
});
module.exports = auth;
Then you should have req.payload with user details. Alternatively you can check the Authorization property in your headers depending on how you set up your app.
When logging in, server should send token and user data, you can store that data in Redux store. Then simply request data from there. When user reloads page, send API request with JWT token and server should return user data, that you will again put in Redux store.
I am making an application in which I am using JWT for maintaining sessions. When any new user registers then I provide a JWT token to user and store it in my database as well as in users browser. When user log out, then i delete that token from browser and my database.
But I want that if user is logged in from multiple devices then it it will log out from one device, it does not logout from other devices as well. How do I achieve this?
First, JWT are not supposed to be able to "log out", but to automatically expire, that is why you are supposed to set short expiresIn times.
It is because with JWT, sessions are handled by the client, it is not the server's responsibility to log out users, it is the user who just throw away the JWT.
In your case, I suppose you check if the JWT exist in your DB before allowing the user, and as such, you just need to search and delete the others JWT associated to that account.
But if you want to make things clean, embrace JWT logic: just set short life time, and wait for them to expire.
Just use an array of tokens in database. Each device will have it's own token in the array of tokens (each token was added to db when user first logged in from a new device) and when the user logs out from that device, only the associated token from the tokens array gets deleted. Here is an example of User schema:
var userSchema = new mongoose.Schema(
{
name: {
type: String,
require: true,
trim: true
},
.
.
.
tokens: [
{
token: {
type: String,
required: true
}
}
],
{
timestamps: true
}
);