4

I've an issue on using an access token in hapi.js. I'm unable to understand how I can use that token to authenticate. I'm following this article dwyl/hapi-auth-jwt2. I'm using mongodb as my database. But until I send my request like this http://localhost:8000/restricted?token=mycreatedtoken, I can't log into {auth: 'jwt'} pages. But sending the request like this does not seem right. So how can I use that token? Don't I have to save that in local storage or a database to access? This is my code:

app.js

 const jwt = require('jsonwebtoken');
 await server.register(require('hapi-auth-jwt2'));

    server.auth.strategy('jwt', 'jwt', {
        key: 'NeverShareYourSecret',
        validate: validate,
        verifyOptions: { algorithms: ['HS256'] }
      });
      server.auth.default('jwt');

validate function:

const validate = async (decoded, req) => {
let user = await User.findOne({ _id: decoded.id });
if (user) {
     req.user = user;
   return { isValid: true };
  } else {
   return { isValid: false };
 }
};

for login:

method: 'POST',
path: '/login',
config: { auth: false },
handler: async function(req, h) {
  try {
    let { username, password } = req.payload;
    let student = await student.findOne({
      username
    });
    let validUser = student && (await bcrypt.compareSync(password,student.password));

    if (validUser) {
      let token = jwt.sign({ id: user.id }, 'mysecretkey');
      console.log('tpken'+token);
     // return h.view('welcome');
      return { token };
    } else {
      return boom.unauthorized('incorrect pass');
    }
  } 
}

signup

method: 'POST',
path: '/student',
config: { auth: false },
handler: async function(req, h) {
  try {
    let salt = bcrypt.genSaltSync(10);
    req.payload.password = bcrypt.hashSync(req.payload.password, salt);

    let student = new User(req.payload); 
    let result = await student.save();
    const  expiresIn  =  24  *  60  *  60;
    let token = jwt.sign({ id: result.id }, 'mysecretkey',{ expiresIn:  expiresIn
    });
    return {token}   ;     

  } 
}

this path is using jwt token.

 { 
    method: 'GET', 
    path: '/register',
    config: { auth: 'jwt' },
    handler: async (request, h) => {
        try {
              return h.view('student');
        } catch(err){
            return h.response(err).code(500);
        }
    }
 }
ProgrammerPer
  • 1,125
  • 1
  • 11
  • 26

1 Answers1

0

Could you please share your validate function? I understand that you can generate the JWT token. In order to user that token to authenticate your request, you need to send that token with "Authorization" header on your requests to your server.

I am using react for frontend and this is my setup to send JWT token to server.

import axios, {AxiosInstance} from 'axios';

const createClient: () => AxiosInstance = () => {
    const options = {
        baseURL: process.env.REACT_APP_API_URL,
        responseType: 'json',        
        withCredentials: true,
        headers: {
            'X-Requested-With': 'XMLHttpRequest',
            'Authorization': ''
        },
    };

    const instance = axios.create(options);

    // Set the AUTH token for any request
    // ref: https://stackoverflow.com/questions/43051291/attach-authorization-header-for-all-axios-requests
    instance.interceptors.request.use(function (config) {        
        const token = localStorage.getItem("USER_JWT_TOKEN");
        config.headers.Authorization = token ? `Bearer ${token}` : '';     

        return config;
    });

    return instance;
};

export default createClient();

Then when I make requests with this setup, automatically axios sends authentication headers in my all requests.

import apiClient from "./apiClient";

const results = await apiClient.get(`/users`);

There is the curl preview of the request that I copied from chrome's network panel.

curl 'https://myserver.com/users' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: https://myserver.com/' -H 'Origin: https://myserver.com' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...... long JWT token string here' -H 'X-Requested-With: XMLHttpRequest' --compressed
metoikos
  • 1,315
  • 11
  • 18
  • i've added the validate function . And I'm also willing to use react as front-end but I'm not sure how can I send that –  Mar 22 '19 at 07:30
  • Your validate function is OK, but you should return `{ isValid: false }` on your **else** statement. JWT is only logical if you have a single page app that make requests to api backend. You need to add authorization headers to your requests when you trying to pull data from your server. – metoikos Mar 22 '19 at 08:55
  • suppose this is the route where I want authentication `` . On the server i've set auth to 'jwt' for `/add` path. But until i submit the button of post the page shows no 401 error. But after clicking i get auth error if no token set but what i want is that page shouldn't be shown without that token not the elements of the page –  Mar 25 '19 at 10:35