If you are looking for a solid elegant Authentication platform that has a Self-Hosted option for complete control, or fully managed option then SuperTokens is here to save the day and protect your application so you don’t have to roll your own auth solution.
Don’t like reading much? and are keen to just have a play and hack around a base implementation of SuperTokens with a custom UI Vue.js Frontend, I have published a working example on github that is self-hosted and containerised here: Project-MA Github SuperTokens Vue. Otherwise keep reading to understand the implementation, configuration and how to get started with SuperTokens as your authentication platform, which I have enjoyed working with.
Below is a visual of the core components of the SuperTokens implementation and authentication process
Self-Hosted SuperTokens Deployment
Deploying Self-Hosted Supertokens into your Vue.js web application can be broken down into 4 parts;
- Vue.js Frontend Custom UI - SuperTokens-Web-JS
- Custom Middleware API Service with Node supertokens-node and express
- SuperTokens Core Service; provided by Supertokens
- Database for persistence of state and user data
This deployment uses one of SuperTokens “Email-Login” recipes, of which you have many to choose from, eg: “One-Time Password, SMS, Federate with Google,Github etc.. ” I’ll go through each step explaining any quirks and gotcha’s I experienced that could help you if you get stuck during implementation. In the end we deploy our web application with authentication via docker containers from a single docker-compose file. I have deployed this stack with Hashicorps Nomad orchestrator too, which worked nicely.
To keep some sort of standard with the Vue App, I have used default values when creating the app with the following command:
npm create vue@latest
Hopefully this makes it more familiar to start with and allows more focus on the SuperTokens implementation, and not on how to setup a Vue app.
Vue.js Frontend Custom UI - SuperTokens-Web-JS
Once you have decided on a Frontend UI layout and design, i.e. your view, router and components, we can then add our custom Login/SignUp Form as a component “login.vue” in ./src/components
that hooks up to our SuperTokens Middleware API Server. First you have to initialise SuperTokens into your Web App in main.ts, here is a snippet:
// main.ts
import { createApp } from "vue";
import router from "./router";
import App from "./App.vue";
import SuperTokens from "supertokens-web-js";
import Session from "supertokens-web-js/recipe/session";
import EmailPassword from "supertokens-web-js/recipe/emailpassword";
SuperTokens.init({
appInfo: {
appName: "SuperTokens Vue",
apiDomain: "http://localhost:3002", // Endpoint of the SuperTokens Middleware API server
apiBasePath: "/auth", // Ths is the default for SuperTokens API Middleware
},
recipeList: [EmailPassword.init(), Session.init()],
});
As we are only deploying locally, the apiDomain endpoint for our middleware api server localhost:port will reflect this, if its a production deployment, change to your domain to prevent CORS issues. Also Take note of the supertokens-web-js version, because if you choose a version that is not compatible with the backend supertokens node version, you will get “500” error type responses. This one got me as the error doesnt tell you its a compatiblity problem at the start, so don’t forget to double check your frontend and backend compatibility here: SDK Compatibility Table
Protecting your Frontend Routes
When configuring your Vue Router in ./router/index.ts, you can add Supertokens session check to verify that the user has logged in successfully, and if they are, a truthy response is given to allow access to the other Web Apps pages(routes), if a false response is returned, the user is simply returned back to the login page(login.vue /login). Here is the src/router/index.ts of the Vue.js router config to allow this;
// ./router/index.ts
import { createRouter, createWebHistory } from "vue-router";
import Session from "supertokens-web-js/recipe/session";
import HomeView from "../views/HomeView.vue";
import Login from "../components/login.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "home",
component: HomeView,
},
{
path: "/login",
name: "login",
component: Login,
},
{
path: "/about",
name: "about",
component: () => import("../views/AboutView.vue"),
},
],
});
// Protecting Frontend Routes with Supertokens Session check
router.beforeEach(async (to, from, next) => {
if (to.name !== "login" && !(await Session.doesSessionExist()))
next({ name: "login" });
else next();
});
export default router;
Login.vue Component
SuperTokens documentation provide great examples of methods to use in your login.vue component to get your application started with functional Login and sign-up form button actions. At a minimum Supertokens login and sign-up methods need a “email” and “password” field entered, with Vue, we use v-model to update the password variable/data/const and the same for email entered at login. The v-btn uses @click=“onLogin” to execute the SuperTokens onLogin method. Here are snippets from the login.vue component;
<!-- login.vue -->
<template>
<v-text-field
density="compact"
placeholder="Email address"
prepend-inner-icon="mdi-email-outline"
variant="outlined"
v-model="userId"
>
</v-text-field>
<div
class="text-subtitle-1 text-medium-emphasis d-flex align-center justify-space-between"
>
Password
</div>
<v-btn
class="mb-8"
color="green"
size="large"
variant="tonal"
block
@click="onLogin"
>
Log In
</v-btn>
</template>
In the Script section of login.vue component we define the onLogin and onSignUp methods. This component uses the Vue Options API (mainly for readability purposes), Composition API would be more typescript friendly, here is a snippet(partial)
// login.vue
<script lang="ts">
import { signUp } from "supertokens-web-js/recipe/emailpassword";
import { doesEmailExist } from "supertokens-web-js/recipe/emailpassword";
import { signIn } from "supertokens-web-js/recipe/emailpassword";
export default {
methods: {
onLogin: async function signInClicked(email: string, password: string) {
try {
let response = await signIn({
formFields: [{
id: "email",
value: this.operatorId
}, {
id: "password",
value: this.password
}]
})
if (response.status === "FIELD_ERROR") {
response.formFields.forEach(formField => {
if (formField.id === "email") {
// Email validation failed (for example incorrect email syntax).
window.alert(formField.error)
}
})
} else if (response.status === "WRONG_CREDENTIALS_ERROR") {
window.alert("Email password combination is incorrect.")
} else if (response.status === "SIGN_IN_NOT_ALLOWED") {
// the reason string is a user friendly message
// about what went wrong. It can also contain a support code which users
// can tell you so you know why their sign in was not allowed.
window.alert(response.reason)
} else {
// sign in successful. The session tokens are automatically handled by
// the frontend SDK.
// window.location.href = "/login"
this.$router.push({path:'/login'})
}
} catch (err: any) {
if (err.isSuperTokensGeneralError === true) {
// this may be a custom error message sent from the API by you.
window.alert(err.message);
} else {
window.alert("Oops! Something went wrong.");
}
}
}
}
}
</script>
These are the main areas of focus when setting up the frontend UI login form with SuperTokens, for the complete code, you can reference the github page I posted here
SuperTokens API Server Middleware
Out of the box, SuperTokens provide Backend SDK’s for NodeJS, Python and Golang.. we’ll be using NodeJS. A reminder to check compatibility versions between frontend and backend(supertokens-node) SDK’s from the link mentioned earlier. We’ll be using Express.js as the web app REST API framework.
Supertokens online Documentation provide a great guide on how to implement this backend SDK for our middleware. The main thing to keep in mind when initialising the SuperTokens Backend SDK is the connectionURI should point to the SuperTokens Core service, which in our example is the docker-compose service name and port that it advertises on.
// st-middleware-api.ts
supertokens.init({
framework: "express",
// debug: true,
supertokens: {
// connectionURI: "https://try.supertokens.com", This is a core hosted for demo/testing purposes.
connectionURI: "http://st-core:3567",
// apiKey: "",
},
appInfo: {
appName: "VueJS SuperTokens Auth",
apiDomain,
websiteDomain,
apiBasePath: "/auth",
websiteBasePath: "/auth",
},
recipeList: [
EmailPassword.init(),
Session.init(),
Dashboard.init(),
UserRoles.init(),
],
});
You can point the ConnectionURI to https://try.supertokens.com to help troubleshoot and test functionality, I found this test endpoint very useful. For the appInfo, Supertokens uses the websiteDomain for CORS, so make sure this parameter is the url of where your frontend website is loaded from, in our case its: http://localhost:7070 which is the port we map to the Nginx service hosting our Vue web app.
As you can see in the above code snippet, this is where we load the SuperToken recipes we wish to use. We are starting of with a basic Email/Password login recipe, a User Management Dashboard and UserRoles.
SuperTokens Core Service
The Self-Hosted SuperTokens Core Service is available as a Docker Image you can deploy onto your own private Orchestrator, I used HashiCorp’s Nomad workload orchestrator which was simple to deploy and get running. In this example, we use Docker-Compose to deploy the st-core service locally; here is the snippet from the docker-compose.yml config we use;
st-core:
image: registry.supertokens.io/supertokens/supertokens-postgresql:9.2.2
depends_on:
st-db:
condition: service_healthy
ports:
- 3567:3567
environment:
POSTGRESQL_CONNECTION_URI: "postgresql://supertokens_user:superPassword@st-db:5432/supertokens"
networks:
- a-net
restart: unless-stopped
healthcheck:
test: >
bash -c 'exec 3<>/dev/tcp/127.0.0.1/3567 && echo -e "GET /hello HTTP/1.1\r\nhost: 127.0.0.1:3567\r\nConnection: close\r\n\r\n" >&3 && cat <&3 | grep "Hello"'
interval: 30s
timeout: 5s
retries: 5
After getting your SuperTokens Core service running and integrated with the your middleware-api server, you can start playing around with SuperToken login and functionality. The User data state will not be persisted yet, as we have not deployed the PostgreSQL database yet, which is the last step in completing a Self-Hosted implementation of SuperTokens.
If you don’t want to write your own User Management dashboard, the SuperTokens Core service provides one as a recipe you can load using the following url: http://localhost:3002/auth/dashboard

Keep in mind that by default the Dashboard UI is loaded from an external CDN.
User Data Persistence and State Management with PostgreSQL
SuperTokens Documentation provides the steps on how to create the Database schema, it was quit seamless when using the Docker images. For a production deployment, you just have to ensure that the filesystem you host the PostgreSQL data on is globally available to mount in a cluster deployment. I published in an earlier post on how to achieve state management with a Hashicorp Nomad Cluster.
Getting started with Adding Users with Email Password Recipe
For the example Vue application we deploy from the github example provided, we are prompted with a Login Form that has the option of Sign-Up or Login. For the first time, click on Sign-Up with the Email/Password entered in the fields provided. This will log you in whilst at the same time creating the email user id in the database.
I have provided a Logout Button to test the session verification and frontend route protection. To re-login you can use the same email/password used in the Sign-Up step.
This deployment is a very basic deployment with no real-world logic on how you manage Sign-Up, registrations of new users etc.. as this can vary greatly between applications and security requirements.
SuperTokens is a very feature rich Authentication platform, constantly evolving and improving the state of security with authentication everyday.
SuperTokens have some great documentation and reference guides, check them out if you are looking for a modern Authentication solution with a great developer experience. SuperToken-Docs
Hopefully this base sample Vue.js App can help you get a flying secure start.