Search code examples
javascriptsecurityvue.jsauth0

VueJS Secure with Auth0 - How is it secure?


I'm missing some sort of (most likely simple) fundamental understanding of securing a JavaScript application such as one using the VueJS framework and a service like Auth0 (or any other OAuth server/service).

1) If you create a SPA VueJS app with routes that require authentication, what stops a user from viewing your bundled code and seeing the views/templates behind that route without needing to login?

2) If you create a VueJS app that authenticates a user and sets some variable in a component like isLoggedIn = true or isAdminUser = true, what stops the user from manipulating the DOM and forcing these values to true?

All your JavaScript code is exposed to the client, so how is any of your code/content actually secure if it can be explored on the code level?


Solution

  • 1) You understand correctly, nothing stops him. That's why you always do all that on the server side. The code in browser/VueJS is only to make the interface make sense, like hiding a button, but the server code should always do the actual check.

    For example:

    1. You have a button "Get secret document" that has a axios request behind to the path /api/sendsecret
    2. In your VueJS app you can do something like v-if="user.isAdmin" to only show the button to the user.

    There's nothing from stopping a user to find that path and just hit it manually with curl or postmaster or any other similar tool

    Thats why the server code (nodeJS with express for example) should always do the checking:

    app.get('api/sendsecret', (req, res) => {
      if (req.user.isAdmin) {
        res.send('the big secret')
      } else {
        res.sendStatus(401) // Unauthorized
      }
    })
    

    2) Again, nothing. You should never authenticate a user in the VueJS application. Its ok to have some variables like isLoggedIn or isAdminUser to make the interface make sense but the server code should always to the actual authentication or authorization.

    Another example. Lets say you're gonna save a blog post

    axios.post('/api/save', {
      title: 'My Blog Post'
      userId: 'bergur'
    }
    

    The server should never, never read that userId and use that blindly. It should use the actual user on the request.

    app.post('api/save', (req, res) => {
      if (req.user.userId === 'bergur') {
        database.saveBlogpost(req.body)
      } else {
        res.sendStatus(401)
      }
    })
    

    Regarding your final marks:

    All your JavaScript code is exposed to the client, so how is any of your code/content actually secure if it can be explored on the code level?

    You are correct, its not secure. The client should have variables that help the UI make sense, but the server should never trust it and always check the actually user on the request. The client code should also never contain a password or a token (for example saving JSONWebToken in local storage).

    Its always the server's job to check if the request is valid. You can see an example on the Auth0 website for NodeJS with Express. https://auth0.com/docs/quickstart/backend/nodejs/01-authorization

    // server.js
    
    // This route doesn't need authentication
    app.get('/api/public', function(req, res) {
      res.json({
        message: 'Hello from a public endpoint! You don\'t need to be authenticated to see this.'
      });
    });
    
    // This route need authentication
    app.get('/api/private', checkJwt, function(req, res) {
      res.json({
        message: 'Hello from a private endpoint! You need to be authenticated to see this.'
      });
    });
    

    Notice the checkJwt on the private route. This is an express middleware that checks if the user access token on the request is valid.