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 anauthmiddleware, 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
tokenobject within adataobject. - Similarly, the response from the
/meendpoint will be inside ainformationobject. - Lastly, yous set
logouttofauxsince 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