Skip to content

fishman/jwt-example

Repository files navigation

Architecture

v1.0

Rails API

  • devise login
  • react + apollo frontend
  • graphql API, because state management in react is easier that way
  • synchronous grpc or rest call. asynchronous call in fiber would be nice, but then we would need to have a push to the client

Greeting API

  • grpc go greeting service. responds with Hello, + Name. The name is stored in the JWT
  • alternatively there is a sinatra http server for the greeter in lib/api_server, you can toggle them in the Procfile. The backend will automatically fallback to rest when the grpc server is not found

Deployment

Security

  • XSS: The message from the greeting service (even though this is not necessary) as well as the users name are sanitized
  • self.new(h(message))
  • self.name = sanitize(self.name)
  • In theory sanitizing either one of these two would be enough, but since we pass the name to the client as well, we should do both
  • JWT had a security bug where specifying the algo none would cause it to accept bad tokens, ruby doesn’t allow that
  • I’m use HS256 default JWT tokens with shared keys.
  • For more security we can rotate the shared keys and store them in Vault rather than config files
  • There’s no TLS between the services, so someone could MITM the go greeting service
  • cypress deps are insecure, but cypress is added to pkg.json for convenience of this example
  • ansible deployment, secrets should be encrypted with ansible-vault
  • the database password should not be stored in the default database.yml
  • fail2ban for web and ssh is always a good idea

Privileges

  • The applications run as www-data but have too many privileges right now

v1 Shared Secret

Mitigation

Rotate shared secret, and distribute it with vault

Pub Key

  • Either there is a pub key store somewhere
  • Or apps are deployed with each others pub keys - this is an issue

GDPR Why google analytics?

Cause I want to know when you check out the page

Install

Ruby on Rails

This application requires:

  • Ruby 2.4.2
  • Rails 5.2.0

Learn more about [Installing Rails](http://railsapps.github.io/installing-rails.html).

Other dependencies

  • Go
  • Node.js + npm (I guess this is a security issue all by itself)

Preparations

We need to make sure the go grpc tools are available. And the ruby and go protobuf services are generated.

./prep.sh
./gen.sh  # this will also set the correct GOPATH and build the greeter
(cd frontend ; yarn install)
(cd backend ; bundle install)

Launch

Launching the services happens through foreman or docker.

cd backend
bundle exec rake db:create
bundle exec rake db:migrate
bundle exec rake db:seed
bundle exec foreman start

Testing

Rails

(cd backend ; bundle exe rake spec)

e2e Testing

There is a simple cypress e2e test in /frontend/cypress/integration/simple_spec.js

It checks for successful login.

(cd frontend ; npm install cypress; cypress ) # javascript e2e tests

Ansible

HAProxy

haproxy_frontends:
  - name: https-in
    mode: http
    options:
      - httplog
    bind:
      - '127.0.0.1:19443 ssl crt {{ certbot_dest_bundle }}'
    acl:
      - name: letsencrypt-acl
        condition: path_beg /.well-known/acme-challenge/
      - name: host_demo3
        condition: hdr(host) -i demo3.xxx.com
    use_backend:
      - name: demo3_cluster
        condition: if host_demo3

haproxy_backends:
  - name: demo3_cluster
    balance: leastconn
    options:
      - forwardfor
    servers:
      - name: node1
        ip: x.x.x.x
        port: 80

nginx

configured automatically with ansible

Todo

  • [X] set static shared key
  • [X] create ruby greeter client
  • [X] add JWT to go server
  • [X] add expiration on JWT token
  • [X] javascript e2e testing
  • [o] ansible deployment
  • [X] deploy to my server
  • [X] fix ssl
  • [ ] version the API
  • [ ] stub faraday client in rails model
  • [ ] fix the go mock
  • [ ] add some ruby specs
  • [ ] write test for greeting model
  • [ ] setup fail2ban
  • [ ] add docker compose
  • [ ] make sure client properly cleans up token if it expires earlier or was invalidated
  • [ ] Move const config from greeter_server to config files
  • [ ] add TLS for service communication
  • [ ] add openid_connect and auth proxy
  • [ ] add something like linkerd for service communication

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors