Skip to content

Instantly share code, notes, and snippets.

@bentedder
Last active June 21, 2017 16:25
Show Gist options
  • Save bentedder/76f3b621fae3e315e1838a46826fa7f5 to your computer and use it in GitHub Desktop.
Save bentedder/76f3b621fae3e315e1838a46826fa7f5 to your computer and use it in GitHub Desktop.
JWT

JSON Web Tokens

What they are

  • an open standard defining a compact and self-contained way for securely transmitting information between parties as a JSON object.

Why to use them

  • stateless sessions (load balancers, separated front and back-end)
  • easy logout
  • save on SQL queries to check user or permissions every request

How to use them

  • server endpoint to create a token on auth
  • client store token in localStorage (or cookie)
  • client sends token back with every request
  • server decodes token and lets request through
  • server can use info in payload to make decision on authorization

Special notes

  • they are not for use in the client, only the API needs the info
  • you should have some other way of checking permissions of the user
  • front end AND api should both be checking for permissions
  • Example
{
  header: {
    typ: "JWT",
    alg: "HS256"
  },
  payload: {
    whatever: 2,
    something: 'hello'
  },
  signature: HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret
  )
}

token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

```
npm init
npm install express jsonwebtoken body-parser
nodemon --watch
```
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require('jsonwebtoken');
const app = express();
app.use(bodyParser.json());
app.get('/api', function api(req, res) {
res.json({
description: 'My API. Please authenticate!'
});
});
app.post('/api/login', (req, res) {
// insert code here to actually authenticate, or fake it
const user = { id: 3 };
// then return a token, secret key should be an env variable
const token = jwt.sign({ user: user.id }, 'secret_key_goes_here');
res.json({
message: 'Authenticated! Use this token in the "Authorization" header',
token: token
});
}
app.get('/api/protected', ensureToken, (req, res) {
jwt.verify(req.token, 'secret_key_goes_here', function(err, data) {
if (error) {
res.sendStatus(403);
} else {
res.json({
description: 'Protected information. Congrats!'
});
}
});
}
function ensureToken(req, res, next) {
const bearerHeader = req.headers["authorization"];
if (typeof bearerHeader !== 'undefined') {
const bearer = bearerHeader.split(" ");
const bearerToken = bearer[1];
req.token = bearerToken;
next();
} else {
res.sendStatus(403);
}
}
app.listen(3000, function () {
console.log('App listening on port 3000!');
});
```
rails new . --api
rails g new controller api
```
gem 'jwt' # add to Gemfile
```
bundle install
rails s
```
class ApiController < ApplicationController
require 'jwt'
# config/routes.rb
get '/api', to: 'api#index'
post '/api/login', to: 'api#login'
get '/api/secret', to: 'api#secret'
# GET /API ROUTE
def index
render json: { message: 'our api!' }
end
# POST /LOGIN ROUTE
def login
current_user = { id: params[:id] }
secret = 'my_secret_key'
token = JWT.encode(current_user, secret, 'HS256')
render json: {
token: token
}
end
# GET /SECRET ROUTE
def secret
secret = 'my_secret_key'
token = bearer_token || nil
begin
decoded_token = JWT.decode(token, secret, true, { :algorithm => 'HS256' })
if decoded_token
render json: { message: 'you found the secret!', current_user: decoded_token[0] }
else
render json: { message: 'get out of here'}, status: 403
end
rescue
render json: { message: 'Error with your token' }, status: 403
end
end
def bearer_token
pattern = /^Bearer /
header = request.headers["Authorization"]
header.gsub(pattern, '') if header && header.match(pattern)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment