Add Authentication and Personalization to VuePress
There are several advantages to using a static site generator such as VuePress. With VuePress, you can focus on writing content using markdown, and the VuePress application generates static HTML files. VuePress also turns your content into a single-page application (SPA), so transitions between pages seem instant and seamless. The generated static files can be cached and distributed across a content delivery network (CDN) for even more performance. For the reader, VuePress creates a great experience.
However, a “static” site does not mean you cannot add dynamic touches to your content. In this tutorial, you will learn how to customize VuePress to create a personalized experience based on the person currently viewing the content.
Install VuePress
Note: To complete this tutorial, you must have Node.js version 8 or higher installed, and a good text/code editor such as Visual Studio Code.
The first step is to create a new folder on your computer for the VuePress project. Name it anything you like. VuePress is a command-line interface (CLI) application. Therefore, you will need to open your terminal (macOS or Linux) or command prompt (Windows). Change the current directory at your command line (terminal or command prompt) to the folder you created for the project. Next, use npm
to initialize this folder.
npm init -y
Now install VuePress using npm
.
npm install vuepress@1.0
Next, you need to add a couple of commands to the project for running your local VuePress website and building the application. Open your project folder in the code editor of your choice. Edit the package.json
file and change the section labeled "scripts"
to the following.
"scripts": {
"build": "vuepress build docs",
"dev": "vuepress dev docs"
},
Create a new folder in your project named docs
. Inside the docs
folder, create a new file named readme.md
. Open this file and add the following markdown content.
# Hello VuePress
This is going to be awesome!
Now run the following command at the command line.
npm run dev
Navigate in your browser to http://localhost:8080
. You should see something like this screenshot.
You now have a running VuePress application!
One of the excellent features of VuePress is it automatically updates your locally-running application with any changes you make. To demonstrate, leave the development server running at the command line. Make a change to readme.md
file and save it. When you return to the browser, you should immediately see that change reflected without having to refresh the page!
Configure VuePress
Much of VuePress is customizable through configuration. In this step, you will configure your VuePress application to add a title and basic navigation.
Create a new folder in the project under docs
named .vuepress
. Notice the period in front of the text, which is required. In the .vuepress
folder, create a new file named config.js
.
module.exports = {
title: "My Documentation Site",
description: "This is going to be awesome!",
themeConfig: {
nav: [
{ text: "Home", link: "/" },
{ text: "About", link: "/about/" }
]
}
};
Go back to your browser and view http://localhost:8080
. You should now see an updated header with the title and navigation!
Add Authentication to VuePress
In the past, adding user login, registration, password reset, and other security features to an application was no trivial task. And, creating application security from scratch also meant potential risk for you or your customers’ data. Thankfully, today there are online services like Okta that take the pain and worry out of adding security to your applications.
Create an Okta Account
The first thing you need to do is create a free Okta developer account.
After creating your account, click the Applications link at the top, and then click Add Application.
Next, choose a Single-Page Application and click Next.
Enter a name for your application, such as My VuePress. Then, click Done to finish creating the application.
Near the bottom of the application page, you will find a section titled Client Credentials. Copy the Client ID and paste it somewhere handy. You will need this later.
Click on the Dashboard link. On the right side of the page, you should find your Org URL. Copy this value and paste it somewhere handy. You will need this later, too.
Next, enable self-service registration. This will allow new users to create their own account. Click on the Users menu and select Registration.
- Click on the Edit button.
- Change Self-service registration to Enabled.
- Click the Save button at the bottom of the form.
Add the Okta Vue Component to VuePress
To use Okta in your VuePress application, you will need the Okta Vue component. Go to your command window and run the following command.
npm install @okta/okta-vue@1.1
Note: If the local development server is still running, you can press CTRL+C to stop it.
Create a new file under the .vuepress
folder named oktaConfig.js
. Add the following code to this new file.
export const oktaConfig = {
issuer: "https://{yourOktaDomain}/oauth2/default",
client_id: "{yourClientId}",
redirect_uri: "http://localhost:8080/implicit/callback/",
scope: "openid profile email"
};
Next, change {yourOktaDomain}
and {yourClientId}
to match the Org URL and Client ID you previously copied in the previous steps. Save this file.
Customize the Default VuePress Theme
To complete the task of adding authentication to your VuePress application, you will need to create a custom theme. One way to do this is to create a copy of the default VuePress theme and modify it.
To create a copy of the default theme, go to your command prompt and type the following command.
npx vuepress@1.0 eject docs
You should now see a new folder under docs/.vuepress
named theme
.
You need to modify the application to register the Okta Vue component. In the theme
folder, create a new file named enhanceApp.js
. Add the following code to this file.
import Auth from '@okta/okta-vue';
import {oktaConfig} from './oktaConfig';
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData // site metadata
}) => {
Vue.use(Auth, oktaConfig);
};
Next, create a new folder under .vuepress
named components
. In the components
folder, create a new file named AuthCallback.vue
. Add the following code to this file.
<template>
<p>Redirecting after login...</p>
</template>
<script>
export default {
async beforeMount() {
// Process the auth tokens
await this.$auth.handleAuthentication();
// get the redirect path from local storage
const path = this.$auth.getFromUri();
// redirect browser to the original page
window.location.replace( path );
}
}
</script>
Create a new folder in the docs
folder named implicit
. In the implicit
folder, create a new folder named callback
. In the callback
folder, add a new file named index.md
. Open this file and add the following.
# Logging In
<AuthCallback />
Next, create a new file under .vuepress/theme/components
named LoginLink.vue
. Paste the following code into this file.
<template>
<div class="nav-item">
<a
v-if="authenticated"
href="/"
@click.stop.prevent="logout"
class="nav-link"
>Sign out ()</a>
<a v-else href="/" @click.stop.prevent="login" class="nav-link">Login</a>
</div>
</template>
<script>
export default {
created() {
this.isAuthenticated();
},
data() {
return {
user: null,
authenticated: false
};
},
methods: {
async isAuthenticated() {
const authenticated = await this.$auth.isAuthenticated();
if (authenticated) {
this.user = await this.$auth.getUser();
} else {
this.user = null;
}
this.authenticated = authenticated;
},
login() {
const currentPath = this.$router.history.current.path;
this.$auth.loginRedirect(currentPath);
},
async logout() {
await this.$auth.logout();
await this.isAuthenticated();
// Navigate back to home
this.$router.push({ path: '/' });
}
}
};
</script>
Next, open the NavLinks.vue
file in the theme/components
folder. Make the following changes.
- In the template, add
<LoginLink />
before the closing</nav>
tag. - Add
import LoginLink from './LoginLink.vue'
to the list ofimport
statements. - Add
LoginLink
to the list ofcomponents
.
Your code should look similar to the following snippet.
<OutboundLink/>
</a>
<LoginLink />
</nav>
</template>
<script>
import DropdownLink from '@theme/components/DropdownLink.vue'
import { resolveNavLinkItem } from '../util'
import NavLink from '@theme/components/NavLink.vue'
import LoginLink from './LoginLink.vue'
export default {
components: { NavLink, DropdownLink, LoginLink },
Now for the moment of truth! Run your dev server again using npm run dev
, and open your browser to http://localhost:8080
. You should see a new Login link in the navigation!
Note: If the application shows that you are already logged in, you can test the login process by clicking Sign out or by opening a new private/incognito window in your browser.
Clicking on that link should redirect you to the Okta login page for your application. Sign in with your Okta developer account (or test registering a new account with a different email address).
After logging in, you should be redirected back to the application with an updated Sign out link with your name.
Add Personalization to VuePress
There are times writing documentation when it’s necessary to instruct the reader to substitute some value with their own. You witnessed this earlier in this tutorial when you were asked to replace {yourOktaDomain}
and {yourClientId}
with your actual account values. Wouldn’t it be great to do this for your readers automatically? You can!
In this last step, you will add a library to VuePress to automatically replace a token such as {email}
with the actual email of the current reader.
In the .vuepress/theme
folder, add a new file named tokenReplacer.js
. Open this file and paste the following code.
function scanChildNodes(node, results) {
if (node.childNodes.length) {
for (let i = 0; i < node.childNodes.length; i++) {
scanChildNodes(node.childNodes[i], results);
}
} else if (node.nodeType == Node.TEXT_NODE) {
results.push(node);
}
}
export function getAllTextNodes() {
const results = [];
scanChildNodes(document, results);
return results;
}
export function nodeReplace(nodes, token, value) {
nodes.forEach(node => {
node.nodeValue = node.nodeValue.replace(
new RegExp( `\{${ token }\}`, "gi" ),
value
);
});
}
Next, open the Layout.vue
file. There will be a total of four changes you need to make to this file. First, add the following line to the list of imports
.
import {getAllTextNodes, nodeReplace} from '../tokenReplacer'
Second, update the mounted()
function with the following code.
mounted () {
this.replaceTokens();
this.$router.afterEach(() => {
this.isSidebarOpen = false
this.replaceTokens();
})
},
Third, add the following function to the top of the list of methods
. Don’t forget to add a comma after the replaceTokens
method.
replaceTokens() {
this.$auth.getUser().then( user => {
if ( user ) {
const nodes = getAllTextNodes();
// Look for any occurrence of {yourEmail} and replace it with user's email
nodeReplace( nodes, "yourEmail", user.email );
}
} );
},
Last, update your docs/readme.md
to include a couple of tokens.
# Hello VuePress
This is going to be awesome!
## Token Replacement Example
When logged in, this value will be your actual email address: `{yourEmail}`
Now start your local dev server with npm run dev
and view http://localhost:8080
. Before login, you should see something like this.
Log in and observe the value.
Success! You can now move forward with adding support for more tokens.
Learn More About Vue and Authentication
This post only scratches the surface of what Vue and VuePress can do. Want to learn more? Check out these other great posts!
- Build a Basic CRUD App with Vue.js and Node
- Add Identity Management to Your Vue.js App
- Add Authentication to Any Web Page in 10 Minutes
- What the Heck is OAuth?
You can find the complete project source code on GitHub.
Okta Developer Blog Comment Policy
We welcome relevant and respectful comments. Off-topic comments may be removed.