├── .gitignore
├── .prettierrc.js
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── assets
│ └── logo.png
├── main.js
├── models
│ └── user.js
├── router.js
├── services
│ ├── auth-header.js
│ ├── auth.service.js
│ └── user.service.js
├── store
│ ├── auth.module.js
│ └── index.js
└── views
│ ├── BoardAdmin.vue
│ ├── BoardModerator.vue
│ ├── BoardUser.vue
│ ├── Home.vue
│ ├── Login.vue
│ ├── Profile.vue
│ └── Register.vue
└── vue.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true
3 | };
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue.js JWT Authentication with Vuex and Vue Router
2 |
3 | For instruction, please visit:
4 | > [Vue 2 JWT Authentication with Vuex and Vue Router](https://bezkoder.com/jwt-vue-vuex-authentication/)
5 |
6 | > [Using Typescript](https://bezkoder.com/vuex-typescript-jwt-auth/)
7 |
8 | > [Vue 3 JWT Authentication with Vuex and Vue Router](https://bezkoder.com/vue-3-authentication-jwt/)
9 |
10 | More Practice:
11 | > [Vue.js CRUD App with Vue Router & Axios](https://bezkoder.com/vue-js-crud-app/)
12 |
13 | > [Vue Pagination with Axios and API example](https://bezkoder.com/vue-pagination-axios/)
14 |
15 | > [Vue File Upload example using Axios](https://bezkoder.com/vue-axios-file-upload/)
16 |
17 | Fullstack with Spring Boot Back-end:
18 | > [Spring Boot + Vue.js: Authentication with JWT & Spring Security Example](https://bezkoder.com/spring-boot-vue-js-authentication-jwt-spring-security/)
19 |
20 | Fullstack with Node.js Express Back-end:
21 | > [Node.js Express + Vue.js: JWT Authentication & Authorization example](https://bezkoder.com/node-express-vue-jwt-auth/)
22 |
23 | Fullstack CRUD:
24 | > [Vue.js + Node.js + Express + MySQL example](https://bezkoder.com/vue-js-node-js-express-mysql-crud-example/)
25 |
26 | > [Vue.js + Node.js + Express + PostgreSQL example](https://bezkoder.com/vue-node-express-postgresql/)
27 |
28 | > [Vue.js + Node.js + Express + MongoDB example](https://bezkoder.com/vue-node-express-mongodb-mevn-crud/)
29 |
30 | > [Vue.js + Spring Boot + MySQL/PostgreSQL example](https://bezkoder.com/spring-boot-vue-js-crud-example/)
31 |
32 | > [Vue.js + Spring Boot + MongoDB example](https://bezkoder.com/spring-boot-vue-mongodb/)
33 |
34 | > [Vue.js + Django example](https://bezkoder.com/django-vue-js-rest-framework/)
35 |
36 | Integration (run back-end & front-end on same server/port)
37 | > [Integrate Vue.js with Spring Boot](https://bezkoder.com/integrate-vue-spring-boot/)
38 |
39 | > [Integrate Vue App with Node.js Express](https://bezkoder.com/serve-vue-app-express/)
40 |
41 | ## Note:
42 | Open `src/services/auth-header.js` and modify `return` statement for appropriate back-end.
43 |
44 | ```js
45 | export default function authHeader() {
46 | let user = JSON.parse(localStorage.getItem('user'));
47 |
48 | if (user && user.accessToken) {
49 | return { Authorization: 'Bearer ' + user.accessToken }; // for Spring Boot back-end
50 | // return { 'x-access-token': user.accessToken }; // for Node.js Express back-end
51 | } else {
52 | return {};
53 | }
54 | }
55 | ```
56 |
57 | ## Project setup
58 | ```
59 | npm install
60 | ```
61 |
62 | ### Compiles and hot-reloads for development
63 | ```
64 | npm run serve
65 | ```
66 |
67 | ### Compiles and minifies for production
68 | ```
69 | npm run build
70 | ```
71 |
72 | ### Run your tests
73 | ```
74 | npm run test
75 | ```
76 |
77 | ### Lints and fixes files
78 | ```
79 | npm run lint
80 | ```
81 |
82 | ### Customize configuration
83 | See [Configuration Reference](https://cli.vuejs.org/config/).
84 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-jwt-example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@fortawesome/fontawesome-svg-core": "^1.2.25",
12 | "@fortawesome/free-solid-svg-icons": "^5.11.2",
13 | "@fortawesome/vue-fontawesome": "^0.1.7",
14 | "axios": "^0.19.0",
15 | "bootstrap": "^4.3.1",
16 | "core-js": "^2.6.5",
17 | "jquery": "^3.4.1",
18 | "popper.js": "^1.15.0",
19 | "vee-validate": "^2.2.15",
20 | "vue": "^2.6.10",
21 | "vue-router": "^3.0.3",
22 | "vuex": "^3.0.1"
23 | },
24 | "devDependencies": {
25 | "@vue/cli-plugin-babel": "^3.11.0",
26 | "@vue/cli-plugin-eslint": "^3.11.0",
27 | "@vue/cli-service": "^3.11.0",
28 | "babel-eslint": "^10.0.1",
29 | "eslint": "^5.16.0",
30 | "eslint-plugin-vue": "^5.0.0",
31 | "vue-template-compiler": "^2.6.10"
32 | },
33 | "eslintConfig": {
34 | "root": true,
35 | "env": {
36 | "node": true
37 | },
38 | "extends": [
39 | "plugin:vue/essential",
40 | "eslint:recommended"
41 | ],
42 | "rules": {},
43 | "parserOptions": {
44 | "parser": "babel-eslint"
45 | }
46 | },
47 | "postcss": {
48 | "plugins": {
49 | "autoprefixer": {}
50 | }
51 | },
52 | "browserslist": [
53 | "> 1%",
54 | "last 2 versions"
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bezkoder/vue-vuex-jwt-auth/0adfefd15700c0ea848a977783e241fcd8cce69e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vuejs jwt auth example
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
85 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bezkoder/vue-vuex-jwt-auth/0adfefd15700c0ea848a977783e241fcd8cce69e/src/assets/logo.png
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import { router } from './router';
4 | import store from './store';
5 | import 'bootstrap';
6 | import 'bootstrap/dist/css/bootstrap.min.css';
7 | import VeeValidate from 'vee-validate';
8 | import Vuex from 'vuex';
9 | import { library } from '@fortawesome/fontawesome-svg-core';
10 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
11 | import {
12 | faHome,
13 | faUser,
14 | faUserPlus,
15 | faSignInAlt,
16 | faSignOutAlt
17 | } from '@fortawesome/free-solid-svg-icons';
18 |
19 | library.add(faHome, faUser, faUserPlus, faSignInAlt, faSignOutAlt);
20 |
21 | Vue.config.productionTip = false;
22 |
23 | Vue.use(VeeValidate);
24 | Vue.component('font-awesome-icon', FontAwesomeIcon);
25 |
26 | Vue.use(Vuex);
27 |
28 | new Vue({
29 | router,
30 | store,
31 | render: h => h(App)
32 | }).$mount('#app');
33 |
--------------------------------------------------------------------------------
/src/models/user.js:
--------------------------------------------------------------------------------
1 | export default class User {
2 | constructor(username, email, password) {
3 | this.username = username;
4 | this.email = email;
5 | this.password = password;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import Home from './views/Home.vue';
4 | import Login from './views/Login.vue';
5 | import Register from './views/Register.vue';
6 |
7 | Vue.use(Router);
8 |
9 | export const router = new Router({
10 | mode: 'history',
11 | routes: [
12 | {
13 | path: '/',
14 | name: 'home',
15 | component: Home
16 | },
17 | {
18 | path: '/home',
19 | component: Home
20 | },
21 | {
22 | path: '/login',
23 | component: Login
24 | },
25 | {
26 | path: '/register',
27 | component: Register
28 | },
29 | {
30 | path: '/profile',
31 | name: 'profile',
32 | // lazy-loaded
33 | component: () => import('./views/Profile.vue')
34 | },
35 | {
36 | path: '/admin',
37 | name: 'admin',
38 | // lazy-loaded
39 | component: () => import('./views/BoardAdmin.vue')
40 | },
41 | {
42 | path: '/mod',
43 | name: 'moderator',
44 | // lazy-loaded
45 | component: () => import('./views/BoardModerator.vue')
46 | },
47 | {
48 | path: '/user',
49 | name: 'user',
50 | // lazy-loaded
51 | component: () => import('./views/BoardUser.vue')
52 | }
53 | ]
54 | });
55 |
56 | // router.beforeEach((to, from, next) => {
57 | // const publicPages = ['/login', '/register', '/home'];
58 | // const authRequired = !publicPages.includes(to.path);
59 | // const loggedIn = localStorage.getItem('user');
60 |
61 | // // trying to access a restricted page + not logged in
62 | // // redirect to login page
63 | // if (authRequired && !loggedIn) {
64 | // next('/login');
65 | // } else {
66 | // next();
67 | // }
68 | // });
69 |
--------------------------------------------------------------------------------
/src/services/auth-header.js:
--------------------------------------------------------------------------------
1 | export default function authHeader() {
2 | let user = JSON.parse(localStorage.getItem('user'));
3 |
4 | if (user && user.accessToken) {
5 | return { Authorization: 'Bearer ' + user.accessToken }; // for Spring Boot back-end
6 | // return { 'x-access-token': user.accessToken }; // for Node.js Express back-end
7 | } else {
8 | return {};
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/services/auth.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const API_URL = 'http://localhost:8080/api/auth/';
4 |
5 | class AuthService {
6 | login(user) {
7 | return axios
8 | .post(API_URL + 'signin', {
9 | username: user.username,
10 | password: user.password
11 | })
12 | .then(response => {
13 | if (response.data.accessToken) {
14 | localStorage.setItem('user', JSON.stringify(response.data));
15 | }
16 |
17 | return response.data;
18 | });
19 | }
20 |
21 | logout() {
22 | localStorage.removeItem('user');
23 | }
24 |
25 | register(user) {
26 | return axios.post(API_URL + 'signup', {
27 | username: user.username,
28 | email: user.email,
29 | password: user.password
30 | });
31 | }
32 | }
33 |
34 | export default new AuthService();
35 |
--------------------------------------------------------------------------------
/src/services/user.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import authHeader from './auth-header';
3 |
4 | const API_URL = 'http://localhost:8080/api/test/';
5 |
6 | class UserService {
7 | getPublicContent() {
8 | return axios.get(API_URL + 'all');
9 | }
10 |
11 | getUserBoard() {
12 | return axios.get(API_URL + 'user', { headers: authHeader() });
13 | }
14 |
15 | getModeratorBoard() {
16 | return axios.get(API_URL + 'mod', { headers: authHeader() });
17 | }
18 |
19 | getAdminBoard() {
20 | return axios.get(API_URL + 'admin', { headers: authHeader() });
21 | }
22 | }
23 |
24 | export default new UserService();
25 |
--------------------------------------------------------------------------------
/src/store/auth.module.js:
--------------------------------------------------------------------------------
1 | import AuthService from '../services/auth.service';
2 |
3 | const user = JSON.parse(localStorage.getItem('user'));
4 | const initialState = user
5 | ? { status: { loggedIn: true }, user }
6 | : { status: { loggedIn: false }, user: null };
7 |
8 | export const auth = {
9 | namespaced: true,
10 | state: initialState,
11 | actions: {
12 | login({ commit }, user) {
13 | return AuthService.login(user).then(
14 | user => {
15 | commit('loginSuccess', user);
16 | return Promise.resolve(user);
17 | },
18 | error => {
19 | commit('loginFailure');
20 | return Promise.reject(error);
21 | }
22 | );
23 | },
24 | logout({ commit }) {
25 | AuthService.logout();
26 | commit('logout');
27 | },
28 | register({ commit }, user) {
29 | return AuthService.register(user).then(
30 | response => {
31 | commit('registerSuccess');
32 | return Promise.resolve(response.data);
33 | },
34 | error => {
35 | commit('registerFailure');
36 | return Promise.reject(error);
37 | }
38 | );
39 | }
40 | },
41 | mutations: {
42 | loginSuccess(state, user) {
43 | state.status.loggedIn = true;
44 | state.user = user;
45 | },
46 | loginFailure(state) {
47 | state.status.loggedIn = false;
48 | state.user = null;
49 | },
50 | logout(state) {
51 | state.status.loggedIn = false;
52 | state.user = null;
53 | },
54 | registerSuccess(state) {
55 | state.status.loggedIn = false;
56 | },
57 | registerFailure(state) {
58 | state.status.loggedIn = false;
59 | }
60 | }
61 | };
62 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import { auth } from './auth.module';
5 |
6 | Vue.use(Vuex);
7 |
8 | export default new Vuex.Store({
9 | modules: {
10 | auth
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/src/views/BoardAdmin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/BoardModerator.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/BoardUser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

9 |
50 |
51 |
52 |
53 |
54 |
104 |
105 |
--------------------------------------------------------------------------------
/src/views/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{currentUser.username}} Profile
6 |
7 |
8 |
9 | Token:
10 | {{currentUser.accessToken.substring(0, 20)}} ... {{currentUser.accessToken.substr(currentUser.accessToken.length - 20)}}
11 |
12 |
13 | Id:
14 | {{currentUser.id}}
15 |
16 |
17 | Email:
18 | {{currentUser.email}}
19 |
20 |
Authorities:
21 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/views/Register.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

9 |
58 |
59 |
{{message}}
64 |
65 |
66 |
67 |
68 |
116 |
117 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | devServer: {
3 | port: 8081
4 | }
5 | }
--------------------------------------------------------------------------------