Web development & API design
07: "Sessions" with JWT
Problem: we need to identify clients (users)
Create user

-
Find user by email
-
Compare passwords
-
Generate token
-
Respond with token

Send authenticated request

- Verify token from Authorization header
- Decode token, identify user
- (Authorize user to see their own todos)
- Fetch all todos for the user
Cookies & tokens

Tokens <3
- Play nice across domains
- Stateless (if you want)
- Decoupled from specific auth scheme
- No need for session store
- Cookies are for browsers
Tokens…
- Client requests a token with…
- Username
- Password
- Server…
- generates
- signs
- (encrypts)
- sends
- Can store data (not just an ID)

JSON web token (JWT) "jot"
- A handy token definition
- Standard: https://tools.ietf.org/html/rfc7519
- Standard: https://tools.ietf.org/html/rfc7519
- Signed with a "secret" known only to the server
- Faster than session stores (decoded using math)
- Not encrypted by default—just signed
JWT under the hood
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InZhbGlkVXNlcm5hbWUifQ.N5ppD4k72pbST4_DESbHzqjrFCZK4QEzhGHI0H49GtM
header: { "typ": "JWT", "alg": "HS256" }
payload: { "username": "validUsername" }
<signature>
signature = HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload) +
<secret>)
JWT with Node
const jwt = require('jwt-simple');
const secret = 'some top secret string';
const payload = {
username: 'theneva',
};
// Token for sending
const signedToken = jwt.encode(payload, secret);
console.log(signedToken); // eyJ0eXAiOiJKV1QiLC…
// Decode the token using the secret
const decodedPayload = jwt.decode(signedToken, secret);
console.log(decodedPayload); // { username: 'theneva' }There's a package for that!
jwt-simple to the rescue
JWT with Express
const app = require('express')();
const jwt = require('jwt-simple');
app.post('/sessions', (req, res) => {
// get and validate login info
if (invalid) {
// respond with 401 unauthorized
} else {
// encode jwt with payload & sign with secret
// return the jwt
}
});
app.get('/user', (req, res) => {
// verify & decode jwt
// get jwt payload username
// retrieve user by username from DB
// return user info
});
app.listen(1234, () => console.log('listening on port 1234'));Example
Client: LocalStorage
// Store
localStorage.token = 'something';
// Get
const token = localStorage.token;- window.localStorage
- or just localStorage
- or just localStorage
- A "plain" object!
JWT + Client
function authenticate() {
const url = api + '/authenticate';
const body = {
username: 'blah',
password: 'glola'
};
fetch(url, {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body),
})
.then(res => res.text())
.then(token => localStorage.token = token);
}
function getWithToken(url) {
return fetch(url, {
headers: {
'X-Token': localStorage.token
}
});
}THIS IS PLAIN JS!
Bcrypt
const bcrypt = require('bcryptjs');
const password = 'ananas';
const passwordHash = bcrypt.hashSync(password, 10);
console.log(password + ' -> ' + passwordHash);
const isMatch = bcrypt.compareSync(password, passwordHash);
console.log(isMatch);
- Password in plaintext?
- Encrypted?
Demo!
Assignment 10
- Continue from A01—or start over!
- Database connection (MongoDB)
- Login (db, users stored in DB, bcrypt)
- Assignment text later today
- Deadline Oct 29
Exercise
- Build an API for creating users
- Use bcrypt to hash passwords
- Allow authentication
- Make forms in React for
- Registering
- Signing in
PG6300-17-07 "Sessions" with JWT
By theneva
PG6300-17-07 "Sessions" with JWT
- 543