Cannot Read Property 'headers' of Undefined Nuxt
Introduction
In this tutorial, you'll implement hallmark in a Nuxt.js app using the Auth
module.
For the purpose of this tutorial, you'll be using JWT
for authentication.
Beneath is a quick demo of what you'll be edifice in this tutorial:
You can find the source code for this application at GitHub.
Warning: Several of the packages in this tutorial now comprise dependencies with known vulnerabilities. In a production setting, you would resolve these issues by upgrading these packages, finding alternatives, or creating forked versions with patched fixes. However, within the express context of a tutorial, it provides educational value as-is.
Prerequisites
To complete this tutorial, you will demand:
- Node.js installed locally, which you can do past following How to Install Node.js and Create a Local Evolution Environment.
- A valid Git installation is optionally required for cloning the API, consult Getting Started with Git.
Some familiarity with Vue.js and Nuxt.js may be benign. You can refer to this mail if you're getting started with Nuxt.js.
This tutorial was verified with Node v13.thirteen.0, npm v6.xiv.4, vue
v2.half dozen.11, and nuxt
v2.12.2.
Step one — Spinning upwardly a Sample API
You are free to use whatever framework that works best for you. Notwithstanding, for quick development, this tutorial will clone an API built with AdonisJs.
The API utilizes:
- JWT (JSON Web Tokens) for hallmark
- SQLite
- CORS enabled
The API has three endpoints:
-
/annals
: endpoint for user registration -
/login
: endpoint for authenticating users -
/me
: endpoint for getting details for the currently authenticated user and information technology is protected by anauth
middleware, which means a user must be authenticated to access the endpoint
First, run the following command in your terminal window:
- git clone https://github.com/do-community/jwt-auth-api.git
Then, navigate to the projection directory:
- cd jwt-auth-api
And install the API dependencies:
- npm install
Annotation: When running install, you may encounter issues with sqlite3
version 4.0.one
depending on the version of Node you are running. Refer to the changelog to decide compatibility with your environment.
At the fourth dimension of original publication, the latest version of Node was 10. I option is to downgrade your version of Node to x.20.1
(with the agreement that it is nearing terminate-of-life support). And so, run npm install
.
A second option is to remove the package-lock.json
file which volition cause the organization to look for 4.2.0
which is supported upwardly to Node 13. You may need to besides downgrade your version of Node to thirteen.13.0
. Then, run npm install
.
A third option would be to modify parcel.json
to a version of sqlite3
supported by your current version of Node, remove package-lock.json
, and run npm install
. However, at the fourth dimension of testing, v.0.0
is not yet released to handle Node 14+ support.
Other symptoms of incompatibility include the post-obit errors: TypeError: Cannot read property 'information' of undefined
and Error: Cannot find module '[...]/node_modules/sqlite3/lib/bounden/[...]/node_sqlite3.node'
.
Next, rename .env.example
to .env
:
- mv .env.case .env
And generate an APP_KEY
:
- npx @adonisjs/cli@4.0.12 key:generate
You should see:
-
Output
generated: unique APP_KEY
Once that'southward coomplete, allow'south run the migrations:
- npx @adonisjs/cli@4.0.12 migration:run
Now, you can outset the API:
- # ensure that you are in the `jwt-auth-api` project directory
- npm start
Y'all tin can access the API on http://127.0.0.ane:3333/api
. Go out this running in a terminal window for the residual of the duration of the tutorial.
Step two — Creating a Nuxt.js App
Now, y'all can create a Nuxt.js app. Open up a new terminal window and utilize vue-cli
to initialize a new Vue project with the Nuxt starter template:
- npx vue-cli@ii.9.6 init nuxt/starter nuxt-auth
Note: At the fourth dimension of testing, vue-cli
is deprecated. @vue/cli
is the current command line tool for Vue projects. And @vue/cli-init
is the recommended arroyo for legacy vue-cli
projects. Yet, create-nuxt-app
is the recommended approach for modern Nuxt projects.
Adjacent, you demand to navigate to the project directory:
- cd nuxt-auth
And install the dependencies:
npm install
And then, you lot tin launch the app:
- npm run dev
The app should be running on http://localhost:3000
. Y'all can view the application in a web browser to see the default Vue application created by vue-cli
.
Step 3 — Installing Necessary Nuxt.js Modules
At present, let'south install the Nuxt.js modules that you'll be needing for your app. Yous'll be using the Nuxt Auth module and the Nuxt Axios module, since the auth
module makes use of Axios internally:
- # ensure that you are in the `nuxt-auth` projection directory
- npm install @nuxtjs/auth@iv.5.1 @nuxtjs/axios@five.3.one --save
Once that'due south completed, open nuxt.config.js
:
- nano nuxt.config.js
Add the code beneath to nuxt.config.js
:
nuxt.config.js
module.exports = { // ... modules : [ '@nuxtjs/axios' , '@nuxtjs/auth' ] , }
Side by side, y'all need to set up the modules. Paste the code below into nuxt.config.js
:
nuxt.config.js
module.exports = { // ... axios : { baseURL : 'http://127.0.0.1:3333/api' } , auth : { strategies : { local : { endpoints : { login : { url : 'login' , method : 'post' , propertyName : 'information.token' } , user : { url : 'me' , method : 'get' , propertyName : 'data' } , logout : false } } } } }
Here, yous set the base URL that Axios will utilise when making requests. In our example, we are referencing the sample API we set up before.
And then, you lot define the authentication endpoints for the local
strategy corresponding to those on your API:
- On successful authentication, the token will be bachelor in the response as a
token
object within adata
object. - Similarly, the response from the
/me
endpoint will be inside ainformation
object. - Lastly, yous set
logout
tofaux
since your API doesn't have an endpoint for logout. Y'all'll simply remove the token from localStorage when a user logs out.
Step 4 — Creating a Navbar Component
To style your app, you lot can make use of Bulma.
Open nuxt.config.js
and paste the code beneath within the link
object that is inside the caput
object:
nuxt.config.js
module.exports = { // ... head : { // ... link [ // ... { rel : 'stylesheet' , href : 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css' } ] } , // ... }
At present, let'southward create the Navbar component:
- nano components/Navbar.vue
And add together the following code:
components/Navbar.vue
<template> <nav class = "navbar is-light" > <div class = "container" > <div grade = "navbar-make" > <nuxt-link form = "navbar-item" to= "/" >Nuxt Auth< /nuxt-link> <button course = "button navbar-burger" > <bridge> < /bridge> <span> < /span> <span> < /span> < /push button> < /div> <div class = "navbar-bill of fare" > <div course = "navbar-finish" > <div class = "navbar-particular has-dropdown is-hoverable" > <a class = "navbar-link" > My Business relationship < /a> <div class = "navbar-dropdown" > <nuxt-link form = "navbar-particular" to= "/profile" >My Profile< /nuxt-link> <60 minutes class = "navbar-divider" / > <a class = "navbar-particular" >Logout< /a> < /div> < /div> <template> <nuxt-link class = "navbar-item" to= "/register" >Annals< /nuxt-link> <nuxt-link class = "navbar-particular" to= "/login" >Log In< /nuxt-link> < /template> < /div> < /div> < /div> < /nav> < /template>
The Navbar component contains links to login
, register
, profile
, and logout
.
Next, let's update the default layout to make use of the Navbar
component.
Open default.vue
:
- nano layouts/default.vue
And supplant the content with the following:
layouts/default.vue
<template> <div> <Navbar/ > <nuxt/ > < /div> < /template> <script> import Navbar from '~/components/Navbar' export default { components : { Navbar } } < /script>
Too, let'southward update the homepage.
Open index.vue
:
- nano pages/alphabetize.vue
And supercede the content with the following:
pages/index.vue
<template> <department form = "section" > <div form = "container" > <h1 grade = "title" >Nuxt Auth< /h1> < /div> < /section> < /template>
At this point, you should take an application that displays a title of "Nuxt Auth"
with a header bar with navigation links:
Stride v — Treatment User Registration
Inside the pages
directory, create a new register.vue
file:
- nano pages/register.vue
And add the following lawmaking:
pages/annals.vue
<template> <section grade = "department" > <div grade = "container" > <div class = "columns" > <div grade = "column is-4 is-offset-4" > <h2 class = "title has-text-centered" >Register! < /h2> <Notification :bulletin= "error" v- if = "fault" / > <form method= "post" @submit.forestall= "register" > <div form = "field" > <label course = "label" >Username< /label> <div grade = "control" > <input type= "text" class = "input" proper noun= "username" v-model= "username" required / > < /div> < /div> <div class = "field" > <label grade = "label" >Email< /label> <div class = "control" > <input type= "email" class = "input" name= "email" v-model= "email" required / > < /div> < /div> <div class = "field" > <label class = "label" >Password< /label> <div class = "command" > <input type= "countersign" course = "input" proper name= "password" v-model= "password" required / > < /div> < /div> <div class = "command" > <button type= "submit" class = "button is-nighttime is-fullwidth" >Register< /push> < /div> < /form> <div class = "has-text-centered" manner= "margin-tiptop: 20px" > Already got an account? <nuxt-link to= "/login" >Login< /nuxt-link> < /div> < /div> < /div> < /div> < /section> < /template> <script> import Notification from '~/components/Notification' export default { components : { Notification, } , data ( ) { return { username : '' , electronic mail : '' , password : '' , error : null } } , methods : { async register ( ) { endeavour { look this .$axios. postal service ( 'register' , { username : this .username, electronic mail : this .email, password : this .password } ) expect this .$auth. loginWith ( 'local' , { data : { electronic mail : this .email, password : this .password } , } ) this .$router. push ( '/' ) } catch (e) { this .error = due east.response.data.bulletin } } } } < /script>
This contains a grade with three fields: username
, e-mail
, and countersign
. Each field is bound to respective information on the component. When the class is submitted, a register
method will be called. Using the Axios module, you make a postal service request to the /register
endpoint, passing forth the user data. If the registration was successful, you lot make use of the Auth module'south loginWith()
, using the local
strategy and passing the user data to log the user in. Then, yous redirect the user to the homepage. If in that location is an error during the registration, you set the error
data as the error message gotten from the API response.
If there is an error, the error message is displayed by a Notification component.
Create a new Notification.vue
file inside components
:
- nano components/Notifaction.vue
And paste the lawmaking below in information technology:
components/Notification.vue
<template> <div class = "notification is-danger" > { { message } } < /div> < /template> <script> consign default { name : 'Notification' , props : [ 'bulletin' ] } < /script>
The Notification component accepts a bulletin
props, which is the fault message.
Now, you can exam out user registration:
Step 6 — Handling LoggedUsers Logged In and Logged Out
Upon successful registration, users should be logged in but there is currently no way for the app to know whether users are logged in or not. And so permit's fix that past updating the Navbar component and adding some computed backdrop.
Earlier you do just that, allow's first actuate the Vuex store by creating an index.js
file inside the store
directory. The Auth module stores user hallmark condition too as user details inside Vuex country in an auth
object. So you can check if a user is logged in or not with this.$store.state.auth.loggedIn
, which will either return truthful
or false
. Similarly, you tin get a user'south details with this.$store.state.auth.user
, which will be null
if no user is logged in.
Note: You can too access the user authentication condition as well every bit the user details direct with the Auth module using this.$auth.loggedIn
and this.$auth.user
respectively.
Since you might want to use the computed properties in multiple places in your app, permit'due south create store getters.
Open index.js
:
- nano shop/index.js
And paste the code below in it:
store/index.js
export const getters = { isAuthenticated ( state ) { return country.auth.loggedIn } , loggedInUser ( country ) { return state.auth.user } }
Here, you create two getters. The first one (isAuthenticated
) will render the authentication status of a user and the second (loggedInUser
) will render the details or the logged in user.
Next, let's update the Navbar component to brand utilise of the getters. Replace the content of components/Navbar.vue
with the following:
components/Navbar.vue
<template> <nav grade = "navbar is-low-cal" > <div form = "container" > <div form = "navbar-make" > <nuxt-link form = "navbar-item" to= "/" >Nuxt Auth< /nuxt-link> <button class = "button navbar-burger" > <bridge> < /span> <span> < /span> <span> < /span> < /button> < /div> <div class = "navbar-menu" > <div grade = "navbar-end" > <div class = "navbar-detail has-dropdown is-hoverable" v- if = "isAuthenticated" > <a class = "navbar-link" > { { loggedInUser.username } } < /a> <div form = "navbar-dropdown" > <nuxt-link class = "navbar-item" to= "/profile" >My Profile< /nuxt-link> <hour class = "navbar-divider" / > <a class = "navbar-item" >Logout< /a> < /div> < /div> <template v- else > <nuxt-link class = "navbar-item" to= "/annals" >Register< /nuxt-link> <nuxt-link class = "navbar-detail" to= "/login" >Log In< /nuxt-link> < /template> < /div> < /div> < /div> < /nav> < /template> <script> import { mapGetters } from 'vuex' export default { computed : { ... mapGetters ( [ 'isAuthenticated' , 'loggedInUser' ] ) } } < /script>
You lot create the computed properties past using the spread operator (...
) to extract the getters from mapGetters
. Then using isAuthenticated
, you display the user carte du jour or links to login
or register
depending on whether the user is logged in or not. Likewise, yous utilise loggedInUser
to display the authenticated user username.
Now, if you give your app a refresh, yous should see something similar to below:
Footstep 7 — Handling User Log In
Now, let'southward permit returning users the ability to log in.
Create a new login.vue
file inside the pages
directory:
nano pages/login.vue
And paste the code beneath in it:
pages/login.vue
<template> <section form = "department" > <div class = "container" > <div class = "columns" > <div class = "column is-4 is-kickoff-4" > <h2 course = "title has-text-centered" >Welcome back! < /h2> <Notification :message= "mistake" v- if = "error" / > <form method= "postal service" @submit.forbid= "login" > <div class = "field" > <label class = "label" >Email< /label> <div class = "control" > <input type= "e-mail" class = "input" proper name= "email" 5-model= "electronic mail" / > < /div> < /div> <div class = "field" > <label grade = "label" >Password< /label> <div class = "control" > <input blazon= "password" form = "input" name= "password" v-model= "password" / > < /div> < /div> <div class = "control" > <push button type= "submit" grade = "push is-nighttime is-fullwidth" >Log In< /button> < /div> < /grade> <div class = "has-text-centered" style= "margin-height: 20px" > <p> Don't take an account? <nuxt-link to= "/register" >Register< /nuxt-link> < /p> < /div> < /div> < /div> < /div> < /section> < /template> <script> import Notification from '~/components/Notification' consign default { components : { Notification, } , data ( ) { render { email : '' , countersign : '' , error : aught } } , methods : { async login ( ) { endeavour { await this .$auth. loginWith ( 'local' , { information : { e-mail : this .e-mail, countersign : this .password } } ) this .$router. push ( '/' ) } catch (e) { this .mistake = e.response.data.message } } } } < /script>
This is quite similar to the annals
page. The form contains two fields: email
and password
. When the course is submitted, a login
method will exist chosen. Using the Auth module loginWith()
and passing along the user information, you log the user in. If the authentication was successful, you redirect the user to the homepage. Otherwise, set error
to the error message gotten from the API response. Again, you are using the Notification component from earlier on to display the error message.
Step 8 — Displaying the User Profile
Let'due south allow logged in users to view their profile.
Create a new profile.vue
file inside the pages
directory:
- nano pages/profile.vue
And paste the code below in information technology:
pages/profile.vue
<template> <section class = "department" > <div form = "container" > <h2 class = "title" >My Profile< /h2> <div course = "content" > <p> <strong>Username: < /potent> { { loggedInUser.username } } < /p> <p> <strong>E-mail: < /strong> { { loggedInUser.email } } < /p> < /div> < /div> < /section> < /template> <script> import { mapGetters } from 'vuex' export default { computed : { ... mapGetters ( [ 'loggedInUser' ] ) } } < /script>
Notice how you lot are using the loggedInUser
getter from before on to display the user details.
Clicking on the My Contour link should issue in a My Profile folio being displayed.
Step 9 — Logging Users Out
Update the logout link inside the Navbar component.
Open Navbar.vue
:
- nano components/Navbar.vue
Alter the logout link to use @click="logout"
:
components/Navbar.vue
// ... <div class = "navbar-dropdown" > <nuxt-link class = "navbar-particular" to= "/profile" >My Profile< /nuxt-link> <hr class = "navbar-divider" / > <a class = "navbar-item" @click= "logout" >Logout< /a> < /div> // ...
When the logout link is clicked, it volition trigger a logout
method.
Side by side, allow'south add the logout
method inside the script department of the Navbar component:
components/Navbar.vue
// ... export default { // ... methods : { async logout ( ) { wait this .$auth. logout ( ) ; } , } , }
You lot phone call the logout()
of the Auth module. This will delete the user's token from localstorage and redirect the user to the homepage.
Step 10 — Restricting the Profile Page
As information technology stands at present, anybody can visit the profile
page. And if the user is not logged in, it volition consequence in an error.
To prepare this, you need to restrict the profile folio to only logged in users. Luckily for u.s., you tin can achieve that with the Auth module. The Auth module comes with an auth
middleware, which you tin utilise in this scenario.
So let'south add the auth
middleware to the profile
page. Update the script
section as below:
pages/contour.vue
// ... export default { middleware : 'auth' , // ... }
Now when a user that is not logged in tries to visit the profile
page, the user will exist redirected to the login
page.
Step 11 — Creating a Guest Middleware
Again as information technology stands, even as a logged in user, you can still access the login and annals pages. One way to prepare that is to restrict login and register pages to only users that are non logged in. Yous can do that past creating a guest middleware.
Inside the middleware
directory, create a new guest.js
file:
- nano middleware/guest.js
And paste the code beneath in it:
middleware/invitee.js
export default function ( { store, redirect } ) { if (store.state.auth.loggedIn) { return redirect ( '/' ) } }
A middleware accepts the context as its kickoff argument. And so y'all extract store
and redirect
from the context. Then, yous check if the user is logged in then redirect the user to the homepage. Otherwise, you lot allow the normal execution of the request.
Adjacent, permit'due south make utilize of this middleware. Update the script
department of both login
and register
as below:
pages/login.vue and pages/annals.vue
// ... consign default { middleware : 'guest' , // ... }
Now, everything will be working equally expected.
Determination
In this tutorial, you looked at how to implement hallmark in a Nuxt.js application using the Auth module. Yous besides saw how to continue the authentication flow sleek by making use of middleware.
To larn more near the Auth module, cheque out the docs.
If you lot'd like to learn more than near Vue.js, check out our Vue.js topic page for exercises and programming projects.
mcdowellseestrocces.blogspot.com
Source: https://www.digitalocean.com/community/tutorials/implementing-authentication-in-nuxtjs-app
0 Response to "Cannot Read Property 'headers' of Undefined Nuxt"
Postar um comentário