December 19, 2017

How To Protect Your Vue.js Application With Jscrambler

by Carlos Matias

protecting-vue-js-app

Introduction

Vue.js is a framework for building user interfaces whose core functionality revolves around building the view layer of your application. But with additional resources and libraries, Vue is able to power modern and sophisticated applications and stands toe-to-toe with other view focused libraries. You can find more information about it here.

We've already shown you how to build a to-do app in Vue and how Vue can power a static blog. In this blog post, we're going to walk through the steps required to have your Vue application protected with Jscrambler, by integrating it with your build process or in your npm scripts.

The examples shown in this article use Vue’s version 2 although they’re also compatible with previous versions of Vue.

Getting started with Vue

Vue's CLI offers a pretty neat way of getting started with Vue.js apps. This is the way we created our to-do Vue app in a previous blog post, which is going to be one of the apps we're protecting. We will also use a sample Vue project (a Hacker News clone in Vue) to show that you can integrate any app with Jscrambler, independently of its size or nature.

First thing to do is install the Vue's CLI

npm install --global vue-cli  

Now we need a sample project. We’re going to use the to-do app we’ve built on a previous blog post. If you simply want the code just clone this repository and follow the steps in the README. The code is essentially the same as the one from the tutorial, except with a few adaptations to Vue's version 2. These adaptations are necessary changes for the Vue code to work. The integration with Jscrambler will remain the same.

If you want to follow along the tutorial instead of cloning the repo, run the following commands and follow the article:

vue init webpack vuetodo  
cd vuetodo  
npm install  

Integrating Jscrambler with Vue

Vue applications can be built with Webpack but Vue also supports builds with Browserify and Rollup. We're going to address Jscrambler's integration with Webpack builds first, since it's what our apps use and it's also the most popular building tool. References to builds with Browserify and Rollup can be found in following sections.

Jscrambler Configuration

If you haven't tried Jscrambler out before reading this article, please consider reading the getting started guide which will walk you through the steps on how to protect your application. This will make this section easier to grasp. It will also teach you how to configure Jscrambler and use a custom configuration.

For this blog post, this is the Jscrambler configuration we're using, based on Jscrambler's Obfuscation default template. Create a .jscramblerrc file at the root of your project and paste your configuration.

{
  "keys": {
    "accessKey": "<YOUR_ACCESS_KEY>",
    "secretKey": "<YOUR_API_KEY>"
  },
  "applicationId": "<YOUR_APP_ID>",
  "params": [
    {
      "name": "whitespaceRemoval"
    },
    {
      "name": "identifiersRenaming",
      "options": {
        "mode": "SAFEST"
      }
    },
    {
      "name": "dotToBracketNotation"
    },
    {
      "name": "deadCodeInjection"
    },
    {
      "name": "stringConcealing"
    },
    {
      "name": "functionReordering"
    },
    {
      "options": {
        "freq": 1,
        "features": [
          "opaqueFunctions"
        ]
      },
      "name": "functionOutlining"
    },
    {
      "name": "propertyKeysObfuscation"
    },
    {
      "name": "regexObfuscation"
    },
    {
      "name": "booleanToAnything"
    }
  ],
  "areSubscribersOrdered": false,
  "applicationTypes": {
    "webBrowserApp": true,
    "desktopApp": false,
    "serverApp": false,
    "hybridMobileApp": false,
    "javascriptNativeApp": false,
    "html5GameApp": false
  },
  "languageSpecifications": {
    "es5": true,
    "es6": false,
    "es7": false
  },
  "useRecommendedOrder": true,
  "jscramblerVersion": "<JSCRAMLBER_VERSION>",
  "sourceMaps": false
}

Don't forget to fill out which Jscrambler version you wish to use, as well as your application's id and your API keys. At the time of writing, the stable Jscrambler version is version 5.1.

Protecting Our App (with Webpack)

Jscrambler applications are easily integrated with Webpack by using Jscrambler's Webpack Plugin. It should be the last plugin that performs any type of modification to the source code.

All of Jscrambler's configurations can be set up or overridden inside the plugin. However, it is not recommended that you include your application's Id or your API keys inside your Webpack's configuration file, so keep them inside the .jscramblerrc file. They will be automatically included when making the request to Jscrambler's API.

Let's install Jscrambler's Webpack Plugin as a dev dependency of our project:

npm i --save-dev jscrambler-webpack-plugin  

Quick example:

const JscramblerWebpack = require('jscrambler-webpack-plugin');

module.exports = {  
  entry: {
    main: './app/index.js',
  },
  output: {
    filename: 'dist/[name].js'
  },
  // ...
  plugins: [
    new JscramblerWebpack({
      enable: true, // optional, defaults to true
      chunks: ['main'], // optional, defaults to all chunks
      // and other jscrambler configurations 
      // overrides the .jscramblerc file
    })
  ]
};

Considering our To-do app, we want to perform a protection whenever we're making a production build, so we will change the webpack.prod.conf.js file which is inside the build directory.

Our production build is already using the UglifyJsPlugin to minify the code. We want to add Jscrambler's plugin after it. Don't worry, your code will remain minified since Jscrambler offers minification features in the form of the identifiersRenaming and whitespaceRemoval transformations.

//... other requires
const JscramblerWebpack = require("jscrambler-webpack-plugin")

const env = config.build.env

const webpackConfig = merge(baseWebpackConfig, {  
  // ...
  plugins: [
    // ...
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    new JscramblerWebpack({
      enable: true,
      chunks: ['app'] // protect just our app.js file
    }),
  //...

Now we run our production build by doing the following:

npm run build  

Our protected app is under /dist/static/js/app.<HASH>.js.

Hacker News Clone Integration

Another example we can look at the is the following Hacker News Clone project.

In order to protect this app, all we need to do is, to install Jscrambler's Webpack plugin and, in the build/webpack.base.config.js, add the following:

//...
const JscramblerWebpack = require("jscrambler-webpack-plugin")

const isProd = process.env.NODE_ENV === 'production'

module.exports = {  
  //...
  plugins: isProd
    ? [
        new webpack.optimize.UglifyJsPlugin({
          compress: { warnings: false }
        }),
        new JscramblerWebpack({
          enable: true,
          chunks: ['app']
        }),
    //...
}

Then all we need to do is build and run our app, following the same steps we did previously. Our protected app file's path is /dist/app.<HASH>.js.

Browserify

Jscrambler currently doesn't offer direct integration with Browserify builds. However, this doesn't mean we cannot protect our Browserify app.

You can create a sample Browserify Vue app by running the following command:

vue init browserify vue-browserify  

If we run the app's build script we can see that our built assets are compiled to dist/build.js. We can also see that the following build command is uglifying the assets:

{
  "build": "cross-env NODE_ENV=production browserify -g envify -p [ vueify/plugins/extract-css -o dist/build.css ] -e src/main.js | uglifyjs -c warnings=false -m > dist/build.js"
}

Since we're only generating one bundle file, we do not need uglifyjs, so we can remove it from our build command. You should also remove it from your devDependencies.

Now, in order to add Jscrambler, you should create a .jscramblerrc or a jscrambler.json file with your configuration on the root of the project. We will be using the one shown in the section above.

We also need to install Jscrambler's package as a dev dependency

npm i --save-dev jscrambler  

And lastly, change our build command to the following:

{
  "build": "cross-env NODE_ENV=production browserify -g envify -p [ vueify/plugins/extract-css -o dist/build.css ] -e src/main.js > dist/build.js && jscrambler -o ./ dist/build.js"
}

After you run npm run build, the protected code will be in dist/build.js.

If you're using a JSON configuration file instead of a .jscramblerrc you'll need to add the config flag to the command as such:

jscrambler -c config.json -o ./ dist/build.js  

Rollup

Jscrambler also doesn't offer direct integration with rollup builds, so we will have to take the same approach as in the Browserify case.

You can create a sample Rollup Vue app by running the following command:

vue init dangvanthanh/vue-rollup-boilerplate vue-rollup  

After you install all the dependencies, also install Jscrambler's package and add your configuration to the project.

Then, add the following script to the app's package.json, after the build:js script:

{
  "build": "run-s build:**",
  "build:js": "cross-env NODE_ENV=production rollup -c",
  "build:jscrambler": "jscrambler -o ./ dist/assets/js/*.js"
}

After building, our protected app file is dist/assets/js/app.js

Final Remarks

Vue is a simple, fast and effective framework for creating dynamic user interfaces and also a great way of leveraging component-based applications.

By combining the build process with Jscrambler you can have your code protected whenever you perform a production build, keeping your code safe and secure.

All of the build processes shown in this tutorial support source-maps. Jscrambler also supports source-maps, but their usage is outside of the scope of this article. If you want to integrate your build process with Jscrambler's source-maps, you can find more information in the documentation.

Follow this link to check out more of Jscrambler's Vue related articles.