In this tutorial, we will be using Vuex and ApolloClient connected to a GraphQL API to handle authentication in our Vuejs app.
Authentication and Authorization
Authentication and Authorization are most often used interchangeably, but they’re different concepts entirely. Authentication identifies or verifies who a user is while Authorization is validating the routes (or parts of the app) the authenticated user can have access to. In this tutorial, we would just be dealing with local authentication. The most popular way for handling authentication in most modern apps is by using username and password. The flow for implementing this is:
- User signs up using password and email
- The user credentials are stored in a database
- When registration is successful, the user is redirected to the login
- On successful authentication, the user is granted access to specific resources
- The user state is stored in any one of the browser storage mediums (localStorage, cookies, session) or JWT.
Prerequisites
You need to have some of the following to work through this tutorial:
- Node 6 or higher (download here)
- Yarn (recommended) or NPM (install yarn here)
- Vue CLI
- GraphQL Playground app. Download here
- Knowledge of GraphQL and VueJS and State Management with Vuex
- …and a very inquisitive mind.
Before we kick off
Learn Vue.js and modern, cutting-edge front-end technologies from core-team members and industry experts with our premium tutorials and video courses on VueSchool.io.
Dependencies
Vuex – Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated predictably.
GraphQL – GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.
Vue-Apollo – This library integrates apollo in your Vue components with declarative queries. Apollo is a set of tools and community efforts to help you use GraphQL in your apps.
The GraphQL API
The API was built with
- Apollo Server for the server
- GraphQL Schema Definition language for the schema
- Nodejs, bcrypt and jwt were used to create the resolvers (Mutations, Queries)
- Sequelize ORM for the database relationships
- and so on…
This is the repo: Jolaolu/graphql-blog-API. This is the API deployed to Heroku: https://bloggr-api.herokuapp.com/ We would use Vue-Apollo to connect to the API very soon.
Project Setup
Open your terminal and type this commands
This command would create the vue project and add the apollo graphql plugins.
Choose Manually select features.(use arrow keys for navigation and spacebar to select).Select Babel, Router(vue-router), Vuex and Linter/Formatter.
The apollo plugin would continue installing immediately after the project installation is complete. Apollo plugin would add apollo.config.js
to the project root folder and vue-apollo to the src folder of the project. It also adds Apollo Provider in the main.js
; Apollo provider would allow our components access to the Apollo client instance.
During Apollo installation, you would be prompted to answer some questions, you can use my config or just No to everything (it would still work properly).
The Code
Let’s work on the User Interface for our app. We would need 3 views in our app;
- Dashboard,
- Login form
- SignUp form
First, let’s setup the page layout.
Go to the src
folder and open App.vue
delete and add this:
Let’s write functionality for login, logout and sign up.
Create Login.vue
and SignUp.vue
files in the view folder
Login.vue
In the login.vue component, we are importing vuex mapActions
and passing login
to it. Later in our Vuex store actions, we would create a login action. The loginUser()
get our authentication details from the store and if it resolves, redirects the user to the dashboard route.
SignUp.vue
Our signup.vue , we have similar functionality with login.vue, just pulling register
from our store actions and invoking it in our registerUser
method.
Let’s create the dashboard component. Go to views and create a Home.vue
file.
Home.vue
Here, we are simply importing getters from our vuex
store. MapGetters simply store getters to local computed properties. In our vuex store, the getters
has our authenticated user object.
Integrating GraphQL API using Vue Apollo
In this section we integrate the authentication API and just inject the URL to vue apollo.
Firstly, let’s write queries and mutations we would use later in our vuex store.
Mutation.js
In our mutation.js
, we would export two graphql functions, LOGIN_USER
and REGISTER_USER
. Login user accepts user email and password and returns the toke, Register user accepts username, email, and password and returns a token too. Let’s try it out with GraphQL Playground.
The API endpoint is https://bloggr-api.herokuapp.com/
.
queries.js
Now let’s set up our Vue Apollo
You should have vue-apollo.config.js
and apollo-config.js
in your project directory, if you installed the vue-apollo plugin.
Let’s begin with setContext
In graphql, a context is value which is provided to every resolver and holds important contextual information like the currently logged in user, or access to a database.
The setContext()
takes a function that returns either an object or a promise that returns an object to set the new context of a request. Simply, we use it to add authorization header to our HTTP request.
Next is the defaultOptions
object.
We are passing the httpEndpoint
, the tokenName
, setting server-side rendering to false and overriding the apollo link.
Then we have these two functions, onLogin
and onLogOut
.
In the onLogin()
, we are passing apolloClient and token as parameters and saying that if localStorage
is not undefined and there’s a token
, it will append the token to AUTH_TOKEN (the token name in our defaultOptions object).
In the onLogout
, we are just removing the token we set in onLogin
.
Setup Routing of Views
Open the router folder and replace the code with this in index.js
.
Let’s now go through the moving parts in this snippet.
Firstly, we are importing our vuex store, we would need it later for accessing the getters isAuthenticated
state.
Secondly, we included a meta
field in our route to /dashboard
, we want to ensure that the user won’t be able to access /dashboard
without getting authenticated. That’s what meta: {requiresAuth: true}
is doing.
Finally, we access the meta object by iterating over $route.matched
to check for meta fields in route records. Then we get the isAuthenticated state from our getters.
State Management with VueX
Open the store folder and add this to index.js
Let’s go through the moving parts of the this code snippet.
Firstly, we import, onLogout
and apolloClient
from our vue-apollo config, then we get the loggedIn user query from our graphql queries and the mutations for login and register user.
Next, we define initial state values.
Then, set up some useful getters:
The isAuthenticated
field here is just a way to seperate data from app logic and making our getter future proof. It’s just best practice.
Next, we would write mutations:
SET_TOKEN
mutation has token
as the payload and assigns the token to state.token
. LOGIN_USER
sets authStatus to true and LOGOUT_USER
removes the localStorage item. Pretty straight forward. New to mutations, check here.
Finally, we write our actions for register
, login
and setUser
:
You probably already know that actions commit mutations and contain async operations. Check here.
In our register function, we pass authDetails as an argument here. AuthDetails is actually an object that has the username, email and password and we use the spread operator to get the content of that object and assign it to the variables object of our apolloClient mutation. To learn more about apolloClient mutations, check here. The login function has similar functionality.
Summary
Screenshots of the working App
You can go ahead and deploy it to Netlify or any other CDN provider. The full source code is on Github. If you’re new to client-side graphql with vue, check my previous article here.