4 |
5 |
6 | Vue jwt
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-jwt-vueRouter",
3 | "version": "1.0.0",
4 | "description": "a simple jwt use vue component vueRouter vueRouter",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --inline --hot --config build/webpack.dev.config.js",
8 | "build": "webpack --progress --hide-modules --config build/webpack.prod.config.js",
9 | "test": "karma start build/karma.conf.js"
10 | },
11 | "author": "lijiahao",
12 | "license": "MIT",
13 | "dependencies": {
14 | "vue": "^1.0.16",
15 | "vue-router": "^0.7.5",
16 | "vue-resource": "^0.1.17",
17 | "bootstrap": "^3.3.5"
18 | },
19 | "devDependencies": {
20 | "babel-core": "^6.1.2",
21 | "babel-loader": "^6.1.0",
22 | "babel-plugin-transform-runtime": "^6.1.2",
23 | "babel-preset-es2015": "^6.1.2",
24 | "babel-preset-stage-0": "^6.1.2",
25 | "babel-runtime": "^5.8.0",
26 | "css-loader": "^0.23.0",
27 | "eslint": "^1.10.3",
28 | "eslint-loader": "^1.3.0",
29 | "file-loader": "^0.8.4",
30 | "function-bind": "^1.0.2",
31 | "inject-loader": "^2.0.1",
32 | "jade": "^1.11.0",
33 | "jasmine-core": "^2.4.1",
34 | "karma": "^0.13.15",
35 | "karma-jasmine": "^0.3.6",
36 | "karma-phantomjs-launcher": "^0.2.1",
37 | "karma-spec-reporter": "0.0.23",
38 | "karma-webpack": "^1.7.0",
39 | "phantomjs": "^1.9.19",
40 | "stylus-loader": "^1.4.0",
41 | "template-html-loader": "0.0.3",
42 | "url-loader": "^0.5.7",
43 | "vue-hot-reload-api": "^1.2.0",
44 | "vue-html-loader": "^1.0.0",
45 | "vue-loader": "^8.0.0",
46 | "vue-style-loader": "^1.0.0",
47 | "webpack": "^1.12.2",
48 | "webpack-dev-server": "^1.12.0"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .env
--------------------------------------------------------------------------------
/server/README.md:
--------------------------------------------------------------------------------
1 | # NodeJS JWT Authentication sample
2 |
3 | This is a NodeJS API that supports username and password authentication with JWTs and has APIs that return Chuck Norris phrases. How awesome is that?
4 |
5 | ## Available APIs
6 |
7 | ### User APIs
8 |
9 | #### POST `/users`
10 |
11 | You can do a POST to `/users` to create a new user.
12 |
13 | The body must have:
14 |
15 | * `username`: The username
16 | * `password`: The password
17 | * `extra`: Some extra information you want to save from the user (It's a string). This could be a color or anything at all.
18 |
19 | It returns the following:
20 |
21 | ```json
22 | {
23 | "id_token": {jwt}
24 | }
25 | ```
26 |
27 | The JWT is signed with the secret located at the `config.json` file. That JWT will contain the `username` and the `extra` information sent.
28 |
29 | #### POST `/sessions/create`
30 |
31 | You can do a POST to `/sessions/create` to log a user in.
32 |
33 | The body must have:
34 |
35 | * `username`: The username
36 | * `password`: The password
37 |
38 | It returns the following:
39 |
40 | ```json
41 | {
42 | "id_token": {jwt}
43 | }
44 | ```
45 |
46 | The JWT is signed with the secret located at the `config.json` file. That JWT will contain the `username` and the `extra` information that you sent at signup time.
47 |
48 | ### Quotes API
49 |
50 | #### GET `/api/random-quote`
51 |
52 | It returns a String with a Random quote from Chuck Norris. It doesn't require authentication.
53 |
54 | #### GET `/api/protected/random-quote`
55 |
56 | It returns a String with a Random quote from Chuck Norris. It requires authentication.
57 |
58 | The JWT must be sent on the `Authorization` header as follows: `Authorization: Bearer {jwt}`
59 |
60 | ## Running it
61 |
62 | Just clone the repository, run `npm install` and then `node server.js`. That's it :).
63 |
64 | If you want to run it on another port, just run `PORT=3001 node server.js` to run it on port 3001 for example
65 |
66 | ## Issue Reporting
67 |
68 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.
69 |
70 | ## License
71 |
72 | MIT
73 |
74 | ## What is Auth0?
75 |
76 | Auth0 helps you to:
77 |
78 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, amont others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**.
79 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**.
80 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user.
81 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely.
82 | * Analytics of how, when and where users are logging in.
83 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules).
84 |
85 | ## Create a free account in Auth0
86 |
87 | 1. Go to [Auth0](https://auth0.com) and click Sign Up.
88 | 2. Use Google, GitHub or Microsoft Account to login.
89 |
--------------------------------------------------------------------------------
/server/anonymous-routes.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | quoter = require('./quoter');
3 |
4 | var app = module.exports = express.Router();
5 |
6 | app.get('/api/random-quote', function(req, res) {
7 | res.status(200).send(quoter.getRandomOne());
8 | });
9 |
--------------------------------------------------------------------------------
/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "secret": "ngEurope rocks!"
3 | }
4 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "in-memory-todo",
3 | "version": "0.1.0",
4 | "description": "An In memory todo for Logged in and not Logged in users",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/auth0/in-memory-todo.git"
12 | },
13 | "keywords": [
14 | "todo",
15 | "in",
16 | "memory",
17 | "jwt",
18 | "auth0"
19 | ],
20 | "author": "Martin Gontovnikas",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/auth0/in-memory-todo/issues"
24 | },
25 | "homepage": "https://github.com/auth0/in-memory-todo",
26 | "dependencies": {
27 | "body-parser": "^1.6.5",
28 | "compression": "^1.0.11",
29 | "cors": "^2.4.1",
30 | "dotenv": "^0.4.0",
31 | "errorhandler": "^1.1.1",
32 | "express": "^4.8.5",
33 | "express-jwt": "^0.3.1",
34 | "jsonwebtoken": "^5.0.1",
35 | "lodash": "^2.4.1",
36 | "morgan": "^1.2.3"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/server/protected-routes.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | jwt = require('express-jwt'),
3 | config = require('./config'),
4 | quoter = require('./quoter');
5 |
6 | var app = module.exports = express.Router();
7 |
8 | var jwtCheck = jwt({
9 | secret: config.secret
10 | });
11 |
12 | app.use('/api/protected', jwtCheck);
13 |
14 | app.get('/api/protected/random-quote', function(req, res) {
15 | res.status(200).send(quoter.getRandomOne());
16 | });
17 |
--------------------------------------------------------------------------------
/server/quoter.js:
--------------------------------------------------------------------------------
1 | var quotes = require('./quotes.json');
2 |
3 | exports.getRandomOne = function() {
4 | var totalAmount = quotes.length;
5 | var rand = Math.ceil(Math.random() * totalAmount);
6 | return quotes[rand];
7 | }
8 |
--------------------------------------------------------------------------------
/server/quotes.json:
--------------------------------------------------------------------------------
1 | ["Chuck Norris doesn't call the wrong number. You answer the wrong phone.",
2 | "Chuck Norris has already been to Mars; that's why there are no signs of life.",
3 | "Chuck Norris and Superman once fought each other on a bet. The loser had to start wearing his underwear on the outside of his pants.",
4 | "Some magicans can walk on water, Chuck Norris can swim through land.",
5 | "Chuck Norris once urinated in a semi truck's gas tank as a joke....that truck is now known as Optimus Prime.",
6 | "Chuck Norris doesn't flush the toilet, he scares the sh*t out of it",
7 | "Chuck Norris counted to infinity - twice.",
8 | "Chuck Norris can cut through a hot knife with butter",
9 | "Chuck Norris is the reason why Waldo is hiding.",
10 | "Death once had a near-Chuck Norris experience",
11 | "When the Boogeyman goes to sleep every night, he checks his closet for Chuck Norris.",
12 | "Chuck Norris can slam a revolving door.",
13 | "Chuck Norris once kicked a horse in the chin. Its decendants are known today as Giraffes.",
14 | "Chuck Norris will never have a heart attack. His heart isn't nearly foolish enough to attack him.",
15 | "Chuck Norris once got bit by a rattle snake........ After three days of pain and agony ..................the rattle snake died",
16 | "Chuck Norris can win a game of Connect Four in only three moves.",
17 | "When Chuck Norris does a pushup, he isn't lifting himself up, he's pushing the Earth down.",
18 | "There is no theory of evolution. Just a list of animals Chuck Norris allows to live.",
19 | "Chuck Norris can light a fire by rubbing two ice-cubes together.",
20 | "Chuck Norris doesn’t wear a watch. HE decides what time it is.",
21 | "The original title for Alien vs. Predator was Alien and Predator vs Chuck Norris.",
22 | "The film was cancelled shortly after going into preproduction. No one would pay nine dollars to see a movie fourteen seconds long.",
23 | "Chuck Norris doesn't read books. He stares them down until he gets the information he wants.",
24 | "Chuck Norris made a Happy Meal cry.",
25 | "Outer space exists because it's afraid to be on the same planet with Chuck Norris.",
26 | "If you spell Chuck Norris in Scrabble, you win. Forever.",
27 | "Chuck Norris can make snow angels on a concrete slab.",
28 | "Chuck Norris destroyed the periodic table, because Chuck Norris only recognizes the element of surprise.",
29 | "Chuck Norris has to use a stunt double when he does crying scenes.",
30 | "Chuck Norris' hand is the only hand that can beat a Royal Flush.",
31 | "There is no theory of evolution. Just a list of creatures Chuck Norris has allowed to live.",
32 | "Chuck Norris does not sleep. He waits.",
33 | "Chuck Norris tells a GPS which way to go.",
34 | "Some people wear Superman pajamas. Superman wears Chuck Norris pajamas.",
35 | "Chuck Norris's tears cure cancer ..... to bad he has never cried",
36 | "Chuck Norris doesn't breathe, he holds air hostage.",
37 | "Chuck Norris had a staring contest with Medusa, and won.",
38 | "When life hands Chuck Norris lemons, he makes orange juice.",
39 | "When Chuck Norris goes on a picnic, the ants bring him food.",
40 | "Chuck Norris gives Freddy Krueger nightmares.",
41 | "They once made a Chuck Norris toilet paper, but there was a problem: It wouldn't take shit from anybody.",
42 | "Chuck Norris can punch a cyclops between the eyes.",
43 | "Chuck Norris doesn't mow his lawn, he stands on the porch and dares it to grow",
44 | "Chuck Norris put out a forest fire. using only gasoline",
45 | "Chuck Norris CAN believe it's not butter.",
46 | "Custom t-shirts provided by Spreadshirt"]
47 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | var logger = require('morgan'),
2 | cors = require('cors'),
3 | http = require('http'),
4 | express = require('express'),
5 | errorhandler = require('errorhandler'),
6 | cors = require('cors'),
7 | dotenv = require('dotenv'),
8 | bodyParser = require('body-parser');
9 |
10 | var app = express();
11 |
12 | dotenv.load();
13 |
14 | // Parsers
15 | // old version of line
16 | // app.use(bodyParser.urlencoded());
17 | // new version of line
18 | app.use(bodyParser.urlencoded({ extended: true }));
19 | app.use(bodyParser.json());
20 | app.use(cors());
21 |
22 | app.use(function(err, req, res, next) {
23 | if (err.name === 'StatusError') {
24 | res.send(err.status, err.message);
25 | } else {
26 | next(err);
27 | }
28 | });
29 |
30 | if (process.env.NODE_ENV === 'development') {
31 | app.use(logger('dev'));
32 | app.use(errorhandler())
33 | }
34 |
35 | app.use(require('./anonymous-routes'));
36 | app.use(require('./protected-routes'));
37 | app.use(require('./user-routes'));
38 |
39 | var port = process.env.PORT || 3001;
40 |
41 | http.createServer(app).listen(port, function (err) {
42 | console.log('listening in http://localhost:' + port);
43 | });
44 |
45 |
--------------------------------------------------------------------------------
/server/statusError.js:
--------------------------------------------------------------------------------
1 | function StatusError(msg, status) {
2 | var err = Error.call(this, msg);
3 | err.status = status;
4 | err.name = 'StatusError';
5 | return err;
6 | }
7 |
8 |
9 | StatusError.prototype = Object.create(Error.prototype, {
10 | constructor: { value: StatusError }
11 | });
12 |
13 | module.exports = StatusError;
14 |
15 |
--------------------------------------------------------------------------------
/server/user-routes.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | _ = require('lodash'),
3 | config = require('./config'),
4 | jwt = require('jsonwebtoken');
5 |
6 | var app = module.exports = express.Router();
7 |
8 | // XXX: This should be a database of users :).
9 | var users = [{
10 | id: 1,
11 | username: 'gonto',
12 | password: 'gonto'
13 | }];
14 |
15 | function createToken(user) {
16 | return jwt.sign(_.omit(user, 'password'), config.secret, { expiresInMinutes: 60*5 });
17 | }
18 |
19 | function getUserScheme(req) {
20 |
21 | var username;
22 | var type;
23 | var userSearch = {};
24 |
25 | // The POST contains a username and not an email
26 | if(req.body.username) {
27 | username = req.body.username;
28 | type = 'username';
29 | userSearch = { username: username };
30 | }
31 | // The POST contains an email and not an username
32 | else if(req.body.email) {
33 | username = req.body.email;
34 | type = 'email';
35 | userSearch = { email: username };
36 | }
37 |
38 | return {
39 | username: username,
40 | type: type,
41 | userSearch: userSearch
42 | }
43 | }
44 |
45 | app.post('/users', function(req, res) {
46 |
47 | var userScheme = getUserScheme(req);
48 |
49 | if (!userScheme.username || !req.body.password) {
50 | return res.status(400).send("You must send the username and the password");
51 | }
52 |
53 | if (_.find(users, userScheme.userSearch)) {
54 | return res.status(400).send("A user with that username already exists");
55 | }
56 |
57 | var profile = _.pick(req.body, userScheme.type, 'password', 'extra');
58 | profile.id = _.max(users, 'id').id + 1;
59 |
60 | users.push(profile);
61 |
62 | res.status(201).send({
63 | id_token: createToken(profile)
64 | });
65 | });
66 |
67 | app.post('/sessions/create', function(req, res) {
68 |
69 | var userScheme = getUserScheme(req);
70 |
71 | if (!userScheme.username || !req.body.password) {
72 | return res.status(400).send("You must send the username and the password");
73 | }
74 |
75 | var user = _.find(users, userScheme.userSearch);
76 |
77 | if (!user) {
78 | return res.status(401).send({message:"The username or password don't match", user: user});
79 | }
80 |
81 | if (user.password !== req.body.password) {
82 | return res.status(401).send("The username or password don't match");
83 | }
84 |
85 | res.status(201).send({
86 | id_token: createToken(user)
87 | });
88 | });
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |