├── .gitignore
├── README.md
├── index.html
├── package.json
├── src
├── auth
│ └── index.js
├── components
│ ├── App.vue
│ ├── Home.vue
│ ├── Login.vue
│ ├── SecretQuote.vue
│ └── Signup.vue
└── index.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | ### Node template
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 |
13 | # Directory for instrumented libs generated by jscoverage/JSCover
14 | lib-cov
15 |
16 | # Coverage directory used by tools like istanbul
17 | coverage
18 |
19 | # nyc test coverage
20 | .nyc_output
21 |
22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
23 | .grunt
24 |
25 | # node-waf configuration
26 | .lock-wscript
27 |
28 | # Compiled binary addons (http://nodejs.org/api/addons.html)
29 | build/Release
30 |
31 | # Dependency directories
32 | node_modules
33 | jspm_packages
34 |
35 | # Optional npm cache directory
36 | .npm
37 |
38 | # Optional REPL history
39 | .node_repl_history
40 | .idea/
41 | .env
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Vue.js Frontend Authentication
2 | ===
3 |
4 | 
5 |
6 | A frontend codebase for authentication with Vue.js and JWT.
7 |
8 | ## About the app
9 |
10 | To log users in, we'll make an HTTP request to our authentication endpoint and save the JWT that is returned in localStorage.
11 |
12 | **Vue components** allow us to specify a template, a script, and style rules all in one file.
13 |
14 |
15 | ## Setup
16 |
17 | Launch server:
18 |
19 | ```
20 | $ webpack-dev-server --inline --hot
21 | ```
22 |
23 | Sample backend: https://github.com/auth0-blog/nodejs-jwt-authentication-sample. Clone the repo, install dependencies and then we can use it as an api endpoint to hit up `http://localhost:3001/api/random-quote`
24 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello Vue
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuejs-auth-frontend",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "babel-core": "^6.1.2",
13 | "babel-loader": "^6.1.0",
14 | "babel-plugin-transform-runtime": "^6.1.2",
15 | "babel-preset-es2015": "^6.1.2",
16 | "babel-runtime": "^6.0.14",
17 | "css-loader": "^0.21.0",
18 | "style-loader": "^0.13.0",
19 | "vue-hot-reload-api": "^1.2.1",
20 | "vue-html-loader": "^1.0.0",
21 | "vue-loader": "^7.0.1",
22 | "webpack": "^1.12.3",
23 | "webpack-dev-server": "^1.12.1"
24 | },
25 | "dependencies": {
26 | "bootstrap": "^3.3.5",
27 | "vue-resource": "^0.1.17",
28 | "vue-router": "^0.7.5",
29 | "vue": "^1.0.7"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/auth/index.js:
--------------------------------------------------------------------------------
1 | import {router} from '../index'
2 |
3 | // endpoints
4 | const API_URL = 'http://localhost:3001/'
5 | const LOGIN_URL = API_URL + 'sessions/create'
6 | const SIGNUP_URL = API_URL + 'users/'
7 |
8 | export default {
9 | // user object is how we check auth status
10 | user: {
11 | authenticated: false
12 | },
13 |
14 | login(context, creds, redirect){
15 | context.$http.post(LOGIN_URL, creds, (data) => {
16 | localStorage.setItem('id_token', data.id_token)
17 |
18 | this.user.authenticated = true
19 |
20 | // redirect
21 | if(redirect){
22 | router.go(redirect)
23 | }
24 | }).error((err) => {
25 | context.error = err
26 | })
27 | },
28 |
29 | signup(context, creds, redirect){
30 | context.$http.post(SIGNUP_URL, creds, (data) => {
31 | localStorage.setItem('id_token', data.id_token)
32 |
33 | this.user.authenticated = true
34 |
35 | // redirect
36 | if(redirect){
37 | router.go(redirect)
38 | }
39 | }).error((err) => {
40 | context.error = err
41 | })
42 | },
43 |
44 | logout(){
45 | localStorage.removeItem('id_token')
46 | this.user.authenticated = false
47 | },
48 |
49 | checkAuth(){
50 | var jwt = localStorage.getItem('id_token')
51 | if(jwt){
52 | this.user.authenticated = true
53 | } else {
54 | this.user.authenticated = false
55 | }
56 | },
57 |
58 | getAuthHeader(){
59 | return {
60 | 'Authorization': 'Bearer ' + localStorage.getItem('id_token')
61 | }
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/components/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Generate Chuck Norris quote
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Login
4 |
Log in to your account to get some great quotes.
5 |
8 |
9 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/components/SecretQuote.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Get a Secret Chuck Norris Quote!
4 |
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/components/Signup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Signup
4 |
Create an account to get some great quotes.
5 |
8 |
9 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import VueResource from 'vue-resource'
4 |
5 | // components
6 | import App from './components/App.vue'
7 | import Home from './components/Home.vue'
8 | import Login from './components/Login.vue'
9 | import Signup from './components/Signup.vue'
10 | import SecretQuote from './components/SecretQuote.vue'
11 |
12 | // services
13 | import auth from './auth'
14 |
15 | Vue.use(VueResource)
16 | Vue.use(VueRouter)
17 |
18 | // Check the users auth status when the app starts
19 | auth.checkAuth()
20 |
21 | // export so we can use in components
22 | export var router = new VueRouter()
23 |
24 | // define routes
25 | router.map({
26 | '/home': {
27 | component: Home
28 | },
29 | '/login': {
30 | component: Login
31 | },
32 | '/signup': {
33 | component: Signup
34 | },
35 | '/secretquote': {
36 | component: SecretQuote
37 | }
38 | })
39 |
40 | // fallback route
41 | router.redirect({
42 | '*': '/home'
43 | })
44 |
45 | // expose the whole thing on element with 'app' as an id
46 | router.start(App, '#app')
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | // the main entry of our app
4 | entry: ['./src/index.js', './src/auth/index.js'],
5 | // output configuration
6 | output: {
7 | path: __dirname + '/build/',
8 | publicPath: 'build/',
9 | filename: 'build.js'
10 | },
11 |
12 | module: {
13 | loaders: [
14 | // process *.vue files using vue-loader
15 | { test: /\.vue$/, loader: 'vue' },
16 | // process *.js files using babel-loader
17 | // the exclude pattern is important so that we don't
18 | // apply babel transform to all the dependencies!
19 | { test: /\.js$/, loader: 'babel', exclude: /node_modules/ }
20 | ]
21 | },
22 |
23 | babel: {
24 | presets: ['es2015'],
25 | plugins: ['transform-runtime']
26 | }
27 | }
--------------------------------------------------------------------------------