Skip to main content

Adding login, signup on Vue with Cryptr

Cryptr - Vue illustration

Beginner Vue.js Tutorial with Cryptr Authentication

Vue.js >= 23min

Learn how to build a Vue.js application from scratch and add Cryptr authentication.

With this tutorial, no prior knowledge of Node or Vue is needed and it will take you through all the steps. You'll just need to have a code editor (I personally use VS Code) and access to the terminal in order to complete this tutorial.

Let's begin! ๐Ÿ˜‰

1. Configurationโ€‹

Create Vue application with routerโ€‹

Rendering

๐Ÿ› ๏ธ๏ธ The CLI will now ask you a few questions so that it can set up the app correctly. The options important to check for this tutoriak are listed below. Choose Manually select features

Rendering

๐Ÿ› ๏ธ๏ธ Check Router. Press "Space" to select feature and "Enter" once you have finished choosing your features

Rendering

Router is required

A couple of options are available, it mainly depends on your preferences, but you need to add Router to handle protected routes

๐Ÿ› ๏ธ๏ธ Pick 2.x - This tutorial is for Vue2 (but Vue3 could work).

Rendering

For other options, you can choose as you like. ๐Ÿ™‚

Rendering

Add Cryptr SPA JSโ€‹

Cryptr SPA JS will provide all the features you need to your app while respecting authentication standards such as OAuth2 & Proof Key Exchange.

๐Ÿ› ๏ธ๏ธ To add this library:

yarn add @cryptr/cryptr-spa-js

Integrate the cryptr pluginโ€‹

Cryptr SPA JS will provide all the features you need to your app while respecting authentication standards such as OAuth2 & PrThe best way to effectively implement a user authentication flow is to create a reusable wrapper around Cryptr's SDK to integrate directly into Vue in order to take advantage of all the Cryptr features.

In this way, the Cryptr SDK will fit well with Vue JS. You just need to add the following file CryptrPlugin.js as a Vue2 plugin in your src:

src/CryptrPlugin.js
import Vue from "vue";
import CryptrSPA from "@cryptr/cryptr-spa-js";

let clientWrapper;

const isRedirectFromCryptr = () =>
window.location.search.includes("code=") &&
window.location.search.includes("state=");

export const getCryptrClient = () => clientWrapper;

const setCryptrClientWrapper = options => {
if (clientWrapper) {
return clientWrapper;
}

clientWrapper = new Vue({
data() {
return {
client: null,
error: null,
isAuthenticated: false,
canRefresh: false,
loading: true,
user: null
};
},

async created() {
this.client = await CryptrSPA.createClient(options);
this.loading = true;
this.isAuthentcated = this.client.isAuthentcated;
this.canRefresh = this.client.canRefresh(this.client.getRefreshStore());
try {
// 1. When user is returning to its browser
if (!this.isAuthenticated && this.canRefresh) {
await this.client.handleRefreshTokens();

// 2. When user is returning to the app after authentication
} else if (!this.isAuthenticated && isRedirectFromCryptr()) {
await this.client.handleRedirectCallback();
}
} catch (e) {
this.error = e;
} finally {
this.isAuthenticated = await this.client.isAuthenticated();

this.user = await this.client.getUser();

this.loading = false;
}
},

methods: {
signInWithRedirect() {
return this.client.signInWithRedirect();
},
signUpWithRedirect() {
return this.client.signUpWithRedirect();
},
logout() {
this.loading = true;
this.client.logOut();
this.loading = false;
return true;
}
}
});

return clientWrapper;
};

export default {
install(Vue, options) {
Vue.prototype.$cryptr = setCryptrClientWrapper(options);
}
};

2. Application Keysโ€‹

Create application with Cryptrโ€‹

You're going to use Cryptrโ€™s authentication service to do the tutorial.

๐Ÿ› ๏ธ๏ธ First, sign up for a free Cryptr account here. Once you're registered, you'll be taken to the Cryptr Onboarding to create your application

Rendering Rendering

๐Ÿ› ๏ธ๏ธ You can then create your application by following the onboarding steps.

Rendering

Once you've completed all the funnel, after the processing steps, you arrive on the homepage of the back-office where you have access to various guides that will help you. They will depend on the choices of technology you have made in the funnel.

Rendering

๐Ÿ› ๏ธ๏ธ You can get your environment configuration by first clicking on ยซ applications ยป in the left menu, then by clicking on the application you will have created. A modal will appear and this is where you may copy/paste your environment variables.

Rendering Rendering

Add your Cryptr credentialsโ€‹

๐Ÿ› ๏ธ๏ธ Add a .env file to your environment using the shell:

Rendering

๐Ÿ› ๏ธ๏ธ Then fill in the .env file with this code, and make sure to replace YOUR_CLIENT_ID and YOUR_DOMAIN with yours:

.env.local
VUE_APP_AUDIENCE=http://localhost:8080
VUE_APP_CLIENT_ID=YOUR_CLIENT_ID
VUE_APP_DEFAULT_LOCALE=en
VUE_APP_DEFAULT_REDIRECT_URI=http://localhost:8080
VUE_APP_TENANT_DOMAIN=YOUR_DOMAIN
VUE_APP_CRYPTR_TELEMETRY=FALSE
VUE_APP_CRYPTR_REGION=eu

Or you may also go to the Cryptr back-office and copy/paste your environment variables in the modal that is displayed as soon as you select your application:

Rendering

Restart the terminal

Make sure to restart your shell/terminal when you modify the environment file

๐Ÿ› ๏ธ๏ธ Integrate your CryptrPLugin with your credentials to Vue:

src/main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import CryptrPlugin from "./CryptrPlugin";

Vue.config.productionTip = false;

const cryptrConfig = {
audience: process.env.VUE_APP_AUDIENCE,
client_id: process.env.VUE_APP_CLIENT_ID,
cryptr_base_url: process.env.VUE_APP_CRYPTR_BASE_URL,
default_locale: process.env.VUE_APP_DEFAULT_LOCALE,
default_redirect_uri: process.env.VUE_APP_DEFAULT_REDIRECT_URI,
telemetry: process.env.VUE_APP_CRYPTR_TELEMETRY,
tenant_domain: process.env.VUE_APP_TENANT_DOMAIN
};

Vue.use(CryptrPlugin, cryptrConfig);

new Vue({
router,
render: (h) => h(App),
}).$mount("#app");

3. Secure the Profile pageโ€‹

Protect your routesโ€‹

Now is the time to protect your private pages with a guard. Thanks to this little helper, we will easily take advantage of the Vue router.

Rendering

๐Ÿ› ๏ธ๏ธ Copy and paste:

src/CryptrGuard.js
import { getCryptrClient } from "./CryptrPlugin";

export const cryptrGuard = (to, from, next) => {
const cryptr = getCryptrClient();

// 1. Check if user is authenticated
const signinUnlessAuthenticated = () => {
if (cryptr.isAuthenticated) {
return next();
}

cryptr.signInWithRedirect();
};

// 2. Handle loading as a guard clause
if (!cryptr.loading) {
return signinUnlessAuthenticated();
}

// 3. Watch the loading to call again
// the signinUnlessAuthenticated() function
cryptr.$watch("loading", loading => {
if (!loading) {
return signinUnlessAuthenticated();
}
});
};

๐Ÿ› ๏ธ๏ธ Import the CryptrGuard in your router. Then, rename views/About.vue to views/Profile.vue, it will be the page we want to make unavailable from a user without session, then replace the about part with profile in the router. On each route to protect you need to add a guard clause to check the user before to enter.

src/router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import { cryptrGuard } from "../CryptrGuard";

Vue.use(VueRouter);

const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/profile",
name: "Profile",
beforeEnter: cryptrGuard,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/Profile.vue"),
},
];

const router = new VueRouter({
routes,
});

export default router;

The Cryptr plugin will provide you all functions you need directly to your templates.

๐Ÿ› ๏ธ๏ธ For a good demonstration, copy and paste the following code in your src/App.vue:

src/App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/" style="margin-right: 5px;">Home</router-link>
<span v-if="!$cryptr.isLoading && !$cryptr.isAuthenticated">
<button
v-on:click="$cryptr.signInWithRedirect"
to="#"
style="margin-right: 5px;"
>
Login
</button>
<button
v-on:click="$cryptr.signUpWithRedirect"
to="#"
style="margin-right: 5px;"
>
Signup
</button>
</span>

<router-link to="/profile">Protected route</router-link>

<button
v-if="$cryptr.isAuthenticated"
v-on:click="$cryptr.logout"
to="#"
style="margin-left: 5px;"
>
Logout
</button>
</div>
<router-view />
</div>
</template>

// ...

Decode your user dataโ€‹

Cryptr user data can be decoded easily.

๐Ÿ› ๏ธ๏ธ Try the following code inside your profile page:

src/router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import { cryptrGuard } from "../CryptrGuard";

Vue.use(VueRouter);

const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/profile",
name: "Profile",
beforeEnter: cryptrGuard,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/Profile.vue"),
},
];

const router = new VueRouter({
routes,
});

export default router;

The Cryptr plugin will provide you all functions you need directly to your templates.

๐Ÿ› ๏ธ๏ธ For a good demonstration, copy and paste the following code in your src/App.vue:

src/views/Profile.vue
<template>
<div class="profile">
<h1>This is an profile page</h1>
<ul>
<li>
<small>{{ $cryptr.user.sub }}</small>
</li>
<li>{{ $cryptr.user.email }}</li>
</ul>
</div>
</template>

Itโ€™s done. You can now start the application by running `yarn serve``

You should see this screen:

Rendering

SANDBOX EMAIL

You can log in with a sandbox email and we send you a magic link which should directly arrive in your personal inbox. Your sandbox email is based on your account's email. The email's structure is as follows: my-user-to-test@sandbox.my-admin-name. For example testemail@sandbox.lucas

Once youโ€™ve logged in, you can view the profile page.

I hope this was helpful, and thanks for reading! ๐Ÿ™‚