mikenicholson / passport-jwt

Passport authentication using JSON Web Tokens
MIT License
1.96k stars 213 forks source link

How to set Token Bearer in the authorization header? #225

Closed alamenai closed 2 years ago

alamenai commented 3 years ago

I've tried to check if they're online examples of how to use JWT extractors to get the token from the request but I failed to understand how to send the token with the request after the user login.

When I use Postman, there's a tab called Authorization where I can choose the type Bearer Token which enabled me to add the token with the Authorization and the request http://localhost:5000/profile went successfully.

However, the browser stills showing me only unauthorized when I try to access the profile http://localhost:5000/profile.

I've followed the documentation configuration:


passport.use(
  new JWTStrategy(
    {
      jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
      secretOrKey: "mysecret",
    },
    function (jwtPayload, done) {
      return User.findOne({ username: jwtPayload.username })
        .then((user) => {
          return done(null, user);
        })
        .catch((err) => {
          return done(err);
        });
    }
  )
);

I sent the token through the Authorization header in thereq`:

Router.post("/", (req, res, next) => {
  passport.authenticate("local", { session: false }, (err, user, info) => {
    if (err) return next(err);
    if (!user) {
      return res.redirect("/login?info=" + info);
    }
    req.logIn(user, { session: false }, (err) => {
      if (err) return next(err);
      const token = jwt.sign({ username: user.username }, "mysecret");
      req.headers.authorization = token;
      res.json({ user, token: `Bearer ${token}` });
    });
  })(req, res, next);
});
MeStrak commented 3 years ago

When you send your token in the req does it have the string 'Bearer' in front of it?

Try req.headers.authorization = `Bearer ${token}`;

I'm not certain that's the answer, it's just the first thing that stood out to me when I saw your second block of code.

When you send the request from your browser, check the headers for that request in the Chrome Dev Tools network tab and you should be able to see Authorization: Bearer <very long token>.

StephanBijzitter commented 2 years ago

You don't. The Authorization header is to be sent from the frontend to the backend; not the other way around. You'll need to remove req.headers.authorization = token;

To access http://localhost:5000/profile (assuming a GET request, but feel free to change):

// Do this every time the token expires
const {token} = await fetch('http://localhost:5000/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        email: '...', // or username, whatever you picked for the local strategy
        password: '...'
    })
}).then((response) => response.json());

// Once you have a token, you can use it to retrieve your profile
const profile = await fetch('http://localhost:5000/profile', {
    method: 'GET',
    headers: {
        Authorization: token
    }
}).then((response) => response.json());
mikenicholson commented 2 years ago

Closing as the question appears to be answered.

in the future, public help sites like Stack Overflow would be a better fit for general questions like this. GitHub issues should generally be reserved for bugs and features requests.

jovi-tsx commented 2 years ago

You don't. The Authorization header is to be sent from the frontend to the backend; not the other way around. You'll need to remove req.headers.authorization = token;

To access http://localhost:5000/profile (assuming a GET request, but feel free to change):

// Do this every time the token expires
const {token} = await fetch('http://localhost:5000/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        email: '...', // or username, whatever you picked for the local strategy
        password: '...'
    })
}).then((response) => response.json());

// Once you have a token, you can use it to retrieve your profile
const profile = await fetch('http://localhost:5000/profile', {
    method: 'GET',
    headers: {
        Authorization: token
    }
}).then((response) => response.json());

I think you answered my problem too, but... How do I validate this token? Once the guy log in into my app, I need to save his bearer token somewhere, right? Let's say probably in my database since I can't set a header for all future requests. But when he tries to retrieve his data (/profile), how I'll send a header with the authorization token if the token wasn't on the client side when he logged in?