0

So I've created a small 2 page VUE with a login page and then routed over to a search page. On login the Python handles the LDAP check and creates the JWT and it looks like it exists in the cookies in the browser however i'm not sure how to handle it when back in "Vue" land.

In addition I though it wasn't great to keep this info in cookies in the browser....hmmmmm

const routes = [
  {
    path: '/',
    name: 'home',
    component: LoginEntry,
    props:{test:'Service Center Search Portal'}
  },
  {
    path: '/scsearch',
    name: 'scsearch',
    component: SearchView
  },

The cookies which I see...added image


Added Code

router.beforeEach(async (to, from, next) => {
  console.log('runniing router');
  console.log(to.name);
  
  if (to.name === "scsearch") {
  
    const response = await axios.get('/api/jwt/check');
    console.log('juust did call');
    console.log(response.status);
    if ( response.status === 401 ) {
      console.log('ressponse status 401');
      return next({ name: "home" });
  }
  console.log('doing noothiing');
  next();
}else{
  next();
}
});

Added Code -2 (Working)

router.beforeEach(async (to, from, next) => {
  console.log('runniing router');
  console.log(to.name);
 
  if (to.name === "scsearch") {
 
  console.log('doing call');
  const response = await axios.get('/api/jwt/check')
  .then(function(value){
    console.log(value);
    next('/');
  })
  .catch(function(err){
    console.log(err)
  });
  
  console.log('juust did call');
  console.log(response);

  console.log('doing noothiing');
  next();
}else{
  next();
}
});
BostonMacOSX
  • 1,369
  • 2
  • 17
  • 38
  • Can you provide more information on what Vue routes you want to protect? And what's inside your JWT payload? – Owl Jul 10 '20 at 23:01
  • there is a / route for the login page which calls /page/login in flask.... then there is a /search which I want to be the protected search "page" the JWT payload will contain a department # of the logged in person...no other information is necessary in the JWT....if I need to I couuld add a logged in = 1 or something.... – BostonMacOSX Jul 10 '20 at 23:07
  • By protected, do you mean only logged in user can access `/search`? or user with certain department tag? And "there is a / route for the login page which calls /page/login in flask" means you are not creating a Vue SPA right? – Owl Jul 10 '20 at 23:13
  • True....I have two .vue files and the router which swiitches between them. – BostonMacOSX Jul 10 '20 at 23:21
  • If you are using vue router, that means you are creating a SPA. Are you using vue-router like [this](https://router.vuejs.org/guide/essentials/named-routes.html)? (Just because it's switching URL path, doesn't mean it's not a SPA) – Owl Jul 10 '20 at 23:26
  • @Owl sorry fell asleep...added code above – BostonMacOSX Jul 11 '20 at 13:25
  • Check my answer – Owl Jul 11 '20 at 15:09

2 Answers2

0

As for JWT, there is no better place to store them than the cookie. LocalStorage/sessionStorage could be unsafe (Read about Cross-Site-Scripting attacks).

I don't have any experience with Vue, but i guess to protect your 'search page', you should have something in your local state, that says the author has been authorized, if not route the client to login page.

ashah
  • 31
  • 3
0

I'm still not sure if this is what you want, but from your question, I assume that:

  1. You are using Vue SPA
  2. You want user that's not logged in can't access route /scsearch on your Vue app
  3. You store your JWT on cookie and can be accessed with document.cookie
  4. If there's JWT on cookie, that means user is logged in, if there's no JWT on cookie, that means user is logged out.

What you want is navigation guard, this is how you use it:

// function to get cookie by name, taken from https://stackoverflow.com/a/15724300/12397250
function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}



const router = new VueRouter({ ... })

// do something everytime user is changing route
router.beforeEach((to, from, next) => {
  // if user is accesing route "ssearch" and not logged in, redirect to home
  // assuming you store your jwt on your cookie with key "authtoken"
  if (to.name === "ssearch" && !getCookie("authtoken")) {
    // User is not logged in, redirect to route "home"
    // return here is important so you don't call other next() below
    return next({ name: "home" });
  }

  // Do nothing
  next();
});

const app = new Vue({
  router
}).$mount('#app')

Edit:

Since you are using HTTPOnly cookie, you need to check it by sending a request to your backend API.

for example:

router.beforeEach(async (to, from, next) => {

  
  if (to.name === "ssearch") {
    // You need to implement this function, you can use XHR, or library like axios. 
    // You also need to add new endpoint to check cookies on your flask app
    const response = await http.get("http://yourbackend.com/api/auth/check");
    
    // Assuming if the jwt verification failed, it returns 401
    if ( response.status === 401 ) {
      return next({ name: "home" });
    }
  }

  next();
});
Owl
  • 6,337
  • 3
  • 16
  • 30
  • Thanks....but what prevents the user from creating a cookie by name and just saying hey the cookie exists.....sorry new to the cookie thing – BostonMacOSX Jul 12 '20 at 22:26
  • Nothing prevents it, this is a client side navigation guards, don't rely on this for security. You should put JWT verification on whichever API endpoints that's called from `/ssearch` page, so if the user set the cookie by name, they still won't be able to do anything on `/ssearch` since they don't have a valid JWT. – Owl Jul 13 '20 at 06:31
  • So I implemented your code above...the only issue is that the access_token_cookie is HttpOnly so it doesn't show up in the list...so I can't check for it..... – BostonMacOSX Jul 13 '20 at 13:37
  • only issue is that I don't beliieve you can use await outsside of an async functiion – BostonMacOSX Jul 13 '20 at 16:17
  • Whoops I missed that, check my answer again. – Owl Jul 13 '20 at 16:21
  • so close...but when I return the 401 the script just stops.....at the axios.get line – BostonMacOSX Jul 13 '20 at 22:24
  • Can you edit your answer with your `beforeEach` code? – Owl Jul 14 '20 at 07:32
  • I was able to update the code with a promise catch ..maybe that is due to axios and not http.get.......seems to be working now..... – BostonMacOSX Jul 14 '20 at 14:48