'How to make a POST request with indicating userId?

there was such a problem. I want posts to be created with a username. But, when trying to make a request, userId is always equal to 1.

↓↓↓

Postman

{
    "id": 3,
    "content": "content-5",
    "userId": 1
}

Models

const User = sequelize.define(
  'users',
  {
    id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
    username: { type: DataTypes.STRING, unique: true },
    email: { type: DataTypes.STRING, unique: true },
    password: { type: DataTypes.STRING },
    role: { type: DataTypes.STRING, defaultValue: 'USER' },
  },
  { timestamps: false }
);

const Post = sequelize.define(
  'posts',
  {
    id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
    content: { type: DataTypes.STRING, allowNull: false },
  },
  { timestamps: false }
);

User.hasMany(Post, { foreignKey: 'userId' });
Post.belongsTo(User, { foreignKey: 'userId' });

PostController

  async create(req, res, next) {
    try {
      const { content } = req.body;
      const { id: userId } = req.user;

      const post = await Post.create({ content, userId })
      return res.json(post)
    } catch (err) {
      console.error(err.message);
      res.status(500).send('Server Error');
    }
  }


Solution 1:[1]

your problem seems to be that you don't know how to handle JWTs to retrieve session data

so here is a basic example using jwt-simple and typescript

Edit i've stripped the TS from the code

so a call should be made to obtain a token such as

curl --request POST \
  --url http://localhost:3000/auth \
  --header 'Content-Type: application/json' \
  --data '{
    "usr": "user1",
    "pwd": "123"
}'

which will hit a endpoint that looks like:

app.post("/auth", async (req, res) => {
    const usr = req.body.usr;
    const pwd = req.body.pwd;
    
    //this would be a lookup on your database table not a basic if like i have here
    if (usr === "user1" && pwd === "123") {
        res.send(
            encodeSession(secret, {
                id: 7,
                dateCreated: Date.now(),
                username: usr,
            })
        );
    } else res.send("Invalid login").sendStatus(403);
});

the results will look like

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpZCI6NywiZGF0ZUNyZWF0ZWQiOjE2NTE2NTg3Njk3NTMsInVzZXJuYW1lIjoidXNlcjEiLCJpc3N1ZWQiOjE2NTE2NTg3Njk3NTMsImV4cGlyZXMiOjE2NTE2NTk2Njk3NTN9.JHY4Es9u-aDp1ZzbX-m5iOzbCqWisjqZQTST2nA2_6XUe5NSUbBSGpaXBd_IAlfsLjahJXAbNrxV6N-02E-h6g",
    "issued": 1651658769753,
    "expires": 1651659669753
}

then in a secure endpoint you would call

function getUserDetails(req){
    const [prefix, token] = req.headers.authorization?.split(" ");
    if (prefix === "myToken" && token)
        return decodeSession(secret, token));
    else 
        throw new Error("Invalid token");
}

this would return

{
    "type": "valid",
    "session": {
        "id": 7,
        "dateCreated": 1651658769753,
        "username": "user1",
        "issued": 1651658769753,
        "expires": 1651659669753
    }
}

the call to a secure endpoint would then look like

curl --request GET \
  --url http://localhost:3000/checkauth \
  --header 'Authorization: myToken eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpZCI6NywiZGF0ZUNyZWF0ZWQiOjE2NTE2NTg3Njk3NTMsInVzZXJuYW1lIjoidXNlcjEiLCJpc3N1ZWQiOjE2NTE2NTg3Njk3NTMsImV4cGlyZXMiOjE2NTE2NTk2Njk3NTN9.JHY4Es9u-aDp1ZzbX-m5iOzbCqWisjqZQTST2nA2_6XUe5NSUbBSGpaXBd_IAlfsLjahJXAbNrxV6N-02E-h6g' \
  --header 'Content-Type: application/json'

and for completeness here is the JWT-Simple implementation

import { encode, decode} from "jwt-simple";

export function encodeSession(
    secretKey,
    dataToEncode
){
    // Always use HS512 to sign the token
    const algorithm= "HS512";
    // Determine when the token should expire
    const issued = Date.now();
    const fifteenMinutesInMs = 15 * 60 * 1000;
    const expires = issued + fifteenMinutesInMs;
    const session = {
        ...dataToEncode,
        issued: issued,
        expires: expires,
    };

    return {
        token: encode(session, secretKey, algorithm),
        issued: issued,
        expires: expires,
    };
}

export function decodeSession(
    secretKey,
    tokenString
){
    // Always use HS512 to decode the token
    const algorithm= "HS512";

    let result={};

    try {
        result = decode(tokenString, secretKey, false, algorithm);
    } catch (e) {

        // These error strings can be found here:
        // https://github.com/hokaccha/node-jwt-simple/blob/c58bfe5e5bb049015fcd55be5fc1b2d5c652dbcd/lib/jwt.js
        if (
            e.message === "No token supplied" ||
            e.message === "Not enough or too many segments"
        ) {
            return {
                type: "invalid-token",
            };
        }

        if (
            e.message === "Signature verification failed" ||
            e.message === "Algorithm not supported"
        ) {
            return {
                type: "integrity-error",
            };
        }

        // Handle json parse errors, thrown when the payload is nonsense
        if (e.message.indexOf("Unexpected token") === 0) {
            return {
                type: "invalid-token",
            };
        }

        throw e;
    }

    return {
        type: "valid",
        session: result,
    };
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1