

Add Authentication and Authorization to Vue.js Apps with Auth0 and GraphQL
source link: https://www.tuicool.com/articles/hit/3e6vuqv
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

TL;DR
- Add authentication to Vue.js app with Auth0
- Authorization using JWT and Hasura GraphQL permissions
- A sample Vue app protected by login to fetch articles written by logged in user
- Source code for sample app

Tech Stack
The app uses the following stack that needs to be setup and configured to get it working:
- Vue.js with vue-cli-plugin-apollo and vue-router
- Auth0 for authentication
- Hasura GraphQL Engine for instant GraphQL APIs
Let's deploy Hasura along with postgres to get our GraphQL APIs ready.
Deploy Hasura
Hasura is an open-source engine that gives you realtime GraphQL APIs on new or existing Postgres databases, with built-in support for stitching custom GraphQL APIs and triggering webhooks on database changes.
Follow the instructions in thedocs to deploy Hasura. Note the Heroku URL for GraphQL Endpoint. You will be configuring this in the app later.
Apply the migrations by following the instructions in this section to create the necessary database schema and permissions.
Now the backend is ready! You will be able to instantly query using Hasura GraphQL APIs. The endpoint will look like (https://myapp.herokuapp.com/v1alpha1/graphql). We will come back to this during the integration with the Vue app.
Create an application in Auth0
- Head to Auth0 dashboard and create an application in Single Page Web App type.

2. In the settings of the application, add http://localhost:3000/callback
as "Allowed Callback URLs" and http://localhost:3000
as "Allowed Web Origins" to enable local development of the app

Add rules for custom JWT claims
In the Auth0 dashboard, navigate to "Rules". Add the following rules to add our custom JWT claims:
function (user, context, callback) { const namespace = "https://hasura.io/jwt/claims"; context.idToken[namespace] = { 'x-hasura-default-role': 'user', // do some custom logic to decide allowed roles 'x-hasura-allowed-roles': user.email === '<a href="/cdn-cgi/l/email-protection" data-cfemail="4627222b2f28062029292427346825292b">[email protected]</a>' ? ['user', 'admin'] : ['user'], 'x-hasura-user-id': user.user_id }; callback(null, user, context); }
Get your JWT signing certificate
Head to https://hasura.io/jwt-config and generate the config for your Auth0 domain.

Copy the JWT Config that is generated for the Autho app.
Enable JWT Mode on Hasura
The config generated above needs to be used in the HASURA_GRAPHQL_JWT_SECRET
environment variable. We also need to set the HASURA_GRAPHQL_ADMIN_SECRET
key for the JWT mode to work.

Once you have added this, the GraphQL endpoints can only be queried using Authorization
header or X-Hasura-Admin-Secret
header.
Create Auth0 Rule
Everytime user signups on Auth0, we need to sync that user into our postgres database. This is done using Auth0 rules. Create another Rule and insert the following code:
function (user, context, callback) { const userId = user.user_id; const nickname = user.nickname; request.post({ headers: {'content-type' : 'application/json', 'x-hasura-admin-secret': '<your-admin-secret>'}, url: 'http://myapp.herokuapp.com/v1alpha1/graphql', body: `{\"query\":\"mutation($userId: String!, $nickname: String) {\\n insert_users(\\n objects: [{ auth0_id: $userId, name: $nickname }]\\n on_conflict: {\\n constraint: users_pkey\\n update_columns: [last_seen, name]\\n }\\n ) {\\n affected_rows\\n }\\n }\",\"variables\":{\"userId\":\"${userId}\",\"nickname\":\"${nickname}\"}}` }, function(error, response, body){ console.log(body); callback(null, user, context); }); }
Replace the admin secret
and url
appropriately.
Finally we have the full backend and auth setup ready. Let's configure the Vue.js frontend to make the GraphQL query with the right headers.
Configure Vue-CLI-Apollo-Plugin
We will be using the Auth0's sample app to get started with boilerplate code.
The following command generates apollo client setup for a Vue app.
vue add apollo
This will generate a file called vue-apollo.js
in src
. In this file, we will be configuring the options
object, getAuth
by defining the following:
getAuth: tokenName => { // get the authentication token from local storage if it exists // return the headers to the context so httpLink can read them const token = localStorage.getItem('apollo-token') if (token) { return 'Bearer ' + token } else { return '' } },
This configuration ensures that ApolloClient makes use of the token returned by Auth0 for Authorization
header when making its query or subscription.
Authenticated Query
Apollo Client has been configured with the right headers in the above setup. So let's add a simple query to fetch list of articles written by the user who is logged in.
export default { apollo: { // Simple query that will update the 'article' vue property article: gql`query { article { id title } }`, }, }
Now we would like to show this only if the user is logged in to the app.
So in our <template>
tag of Home.vue
, we will be using the following code snippet to list the articles
<template> ... ... <div v-if="isAuthenticated"> <h1 class="mb-4"> Articles written by me </h1> <div v-for="a in article" :key="a.id"> {{a.id}}. {{ a.title }} </div> </div> ... ... </template>
Note that we are ensuring that this markup has to be rendered only if isAuthenticated
returns true. To implement this, we emit an event after each successful login.
Head to src/auth/authService.js
to see the implementation details of Auth0 login and event emitting.
In this file, an event is emitted once the login is done successfully.
this.emit(loginEvent, { loggedIn: true, profile: authResult.idTokenPayload, state: authResult.appState || {} });
A plugin
has been registered to handle this event in src/plugins
import authService from "../auth/authService"; export default { install(Vue) { Vue.prototype.$auth = authService; Vue.mixin({ created() { if (this.handleLoginEvent) { authService.addListener("loginEvent", this.handleLoginEvent); } }, destroyed() { if (this.handleLoginEvent) { authService.removeListener("loginEvent", this.handleLoginEvent); } } }); } };
So once a loginEvent
occurs, handleLoginEvent
method is called.
And in our Home.vue
component, we handle that method to update isAuthenticated
value. It is false
by default and once login is successful, gets updated to true
.
methods: { handleLoginEvent(data) { this.isAuthenticated = data.loggedIn; this.isLoading = false; } },
The GraphQL query above is sent using the token header returned by Auth0 and this takes care of the Authentication.
Authorization using JWT
Though the user is logged in, we want to show only the articles written by the same user. The permissions have been configured in such a way that only the user who wrote the article will be able to fetch the data.
Head to the Heroku app URL to open Hasura console and navigate to Data->article->Permissions to see the permissions defined for the user
role.

The permission check looks like:
{ "user_id": {"_eq": "X-Hasura-User-Id"}}
This means that when a request is being sent with Authorization: Bearer <token>
from the client, it will look for the X-Hasura-User-Id
value from the token payload and filter it for the user_id
column, ensuring that only logged in users get the data and also get only their data . The user has permissions to access all columns.
Protected Routes using Vue Router
Since we are using Vue Router , we can add Navigation Guards
using a Global Before Guard
. This is called whenever a navigation is triggered and the navigation is considered pending until resolved.
In src/router.js
, we define the beforeEach
guard which checks for the boolean auth.isAuthenticated()
before resolving.
router.beforeEach((to, from, next) => { if (to.path === "/" || to.path === "/callback" || auth.isAuthenticated()){ return next(); } auth.login({ target: to.path }); });
In case, the page is not /
, /callback
or the user is not authenticated, then the user is redirected to Login page using auth.login
method.
Running the App
We need to configure the Hasura GraphQL Endpoint in the Vue.js app. Go to src/vue-apollo.js
and modify the httpEndpoint
and wsEndpoint
values appropriately.
Run the sample app by running the following commands:
npm install npm run serve
You should be seeing a screen like this:

I have put together a boilerplate so that you can get started quickly!
Check it out on github .
Take it for a spin and let us know what you think. If you have any questions or run into any trouble, feel free to reach out to us on twitter , github or on our discord server .
Recommend
-
74
In this article, we're going to explore the Auth0 service, which provides authentication and authorization as a service. Auth0 allows you to set up basic authentication and authorization features for your apps in the blin...
-
4
C# extension methods let you easily add new functionality to existing classes. Learn how you can leverage them to simplify the Auth0 configuration for ASP.NET web apps. ASP.NET Web Apps and Auth0 Adding
-
7
In this post I show how how to add authentication to a sample ASP.NET Core Blazor Server app. The default .NET templates show how to use ASP.NET Identity or Azure for authentication, but in this post I show how to use Auth0 for authentication...
-
11
Bootstrapping the Authentication Layer and Server With Auth0.js and Hasura Aug 25, 2021...
-
12
TL;DR: This article discusses the Backend For Frontend authentication pattern and how it can be used in practice in SPAs implemented with React that use ASP.NET Core 5 as backend. Basic knowledge of the OAuth 2.0 and OpenID C...
-
15
Welcome!In this four-part tutorial, you’ll take a Flutter app and enhance it with Auth0. You’ll start by adding basic username/password authentication to it, followed by social logins, and then enable real-time support chat that make...
-
10
-
10
@rodrigokamadaRodrigo KamadaSoftware developer with experience in Node.js, Java, Angular, Bootstrap, Ionic, MongoDB, MySQL, Redis, Kafka and Docker.
-
7
-
6
As a Blazor developer, you can reuse your Razor components and your skills to create UIs for desktop and mobile applications through .NET MAUI. While you may know how to add authentication to a Blazor application, things are slightly different whe...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK