0

I've developed a Vue app that gets its data from a CouchDB backend only after a user has logged in with the right credentials. The current state requires the user to enter login info every time the browser is reloaded, and also leaves the login info exposed in the browser. I'm looking for a way to save the credentials (as cookies, possibly, and preferably a vue-centric way), so they can be used to require a module that needs them.

The user sees the following HTML, whence the credential info comes.

LandingPage.vue

<div id="wrapper">
    <el-dialog :visible="!authenticated">
        <div slot="title">LOG IN TO THE DOCUMENTATION REPOSITORY</div>
        <el-form inline>
            <el-form-item>
                <el-input type="text" v-model="username" placeholder="USERNAME"></el-input>
            </el-form-item>
            <el-form-item>
                <el-input type="password" v-model="password" placeholder="PASSWORD"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" :disabled="!(username.length&&password.length)" @click="authenticate">LOG IN</el-button>
            </el-form-item>
        </el-form>
    </el-dialog>
    <the-rest-of-the-app v-if="authenticated"></the-rest-of-the-app>
</div>

Here is the authenticate function:

LandingPage.vue

     authenticate: function(){
         this.authenticated=true
         var credentials = [ this.username, this.password ]
         var Store = require('../store.js')['default'](credentials)
         console.log(Object.keys(Store))
         var self = this;
         Store.getDB().then(val => {
             self.getCategories(Store);
             self.handleChange(Store);
             self.result = val;
             self.$forceUpdate()
         }).catch(err => {
             console.log(err)
         })
     },

This causes data to be loaded that is fetched using functions from the Store module. Store looks like this:

store.js

var path = require('path')
var dir = require('node-dir')
var mime = require('mime-types')

export default function(credentials){
    var serverName = 'localhost:5984'
    var username = credentials[0]
    var adminPassword = credentials[1]
    var serverUrl = `http://${username}:${adminPassword}@${serverName}`
    var nano = require('nano')(serverUrl)
    var documentation = nano.use('documentation')

    return {
        getDB: function(){
            return new Promise(function(accept, reject){
                nano.db.get('documentation', function(err, body) {
                    if (!err) {
                        console.log(body);
                        accept(body)
                    }
                });
            })
        },
        getCategories: function(){
             var self=this
             return new Promise(function(accept, reject){
                  documentation.view('categories', 'list', {"reduce": false}, function(err, body) {
                      if (!err) {
                         accept(body.rows)
                      }
                      else {
                         console.log(err)
                      }

                  })
             })
         }
}

Is there a better way to store the credentials so that:

  1. they won't be lost on refresh,

  2. they won't be exposed in the browser for anyone w/ JavaScript access to access?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
David J.
  • 1,753
  • 13
  • 47
  • 96
  • 1
    There is no way to secure the credentials in the browser. Your app design is flawed. – Randy Casburn Apr 11 '18 at 14:27
  • @RandyCasburn Can you offer an alternative? – David J. Apr 11 '18 at 15:30
  • **You don't, can't and shouldn't conceal credentials from the user.** The credentials belong to the user, and only allow the user to do what you let them do. Your challenge is to make an interface that's so useful the user doesn't need to F12 and type their own js to do something ! Your app's security is ensured by making sure your credentials are tamper-proof and short-lived, within reason, depending on what they secure. – bbsimonbb Apr 11 '18 at 15:32
  • @bbsimonbb I didn't mean that the user is supposed to do anything in the console. I want it to be impossible for malicious actors to somehow hack into a user's session and access saved variables. I guess I should have made that more clear. – David J. Apr 11 '18 at 15:35
  • 2
    Yup. That's primarily the browser's job. You need to be aware of cross-site scripting, which, a bit like SQL injection, requires you to be super careful with what you do with user input. But in general terms, everything you send to the browser belongs to the user, but can't be accessed by anyone else. The whole web relies on this. It's not up to you! – bbsimonbb Apr 11 '18 at 16:10
  • 1
    Your server platform will usually dictate what login credentials are used and how they are stored. If you want to implement OAuth and single sign-on, then you'll need to worry about storing tokens. Other than that, the server controls it and you don't need to worry. Credentials will usually be cookies, and they will usually have the HTTPOnly attribute set, so they can't be accessed with javascript. If you're not using an established server platform with an established authentication module then your api isn't secure, which might be alright in some situations, but don't have any illusions. – bbsimonbb Apr 11 '18 at 16:23
  • @bbsimonbb I'm using Couch's authentication, so I'm not worried about anyone gaining access to sensitive data via the server platform. What I'm building is a very basic way for a group of people inside of a closed network -- some of them with admin privileges -- to use this app. – David J. Apr 11 '18 at 16:29

0 Answers0