Skip to content

wellsst/jwt-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jwt-template

JWT by example/starter template with Grails, Angular

Why JWT?

JSON Web Tokens can provide a simple form of authentication that is an alternative to passwords, 2FA or using an OpenAuth provider.

The method of authorisation proposed by this piece of work is quite simple and is based on the ideas of others.

It has a particular use-case and will not suit all scenarios. Typically it would be suitable for general scale web based systems. A user needs to register to use the system using this by entering their email, after a short process they will be provided a token for future authentication. Thus it may not suit for example in large scale enterprise systems, in this case you could still use JWT but with something like an OAuth authorization server such as by Auth0. The nice advantage with this proposal is simplicity (no passwords), thus also making it easier to manage.

Advantages:

  • Simplicity
  • User does not write down or store or forget yet another password - cumbersome and unsafe
  • Password re-use is evil
  • Less vulnerable to keystroke loggers
  • Less vulnerable to phishing attacks
  • Can hold any information, just don't make it sensitive unless using JSON Web Encryption (JWE).
  • Flexible and interoperable - JSON based
  • Tokens can contain other tokens - a token chain (my thought only, I have seen anyone mention this yet)
  • JWT can be can be cryptographically signed and encrypted to prevent tampering on the client side
  • Server side can verify JWT without needing to store data (typically you would, depending on use-case)
  • More compact and easier to work with than SAML (JSON vs XML)

Current framework versions used

  • Grails 3.x
  • Angular 8.x

Starting up locally

This profile has created a multi-project build where the "server" module contains the Grails application and the "client" module contains the Angular 6 application.

To start the Grails application: ./gradlew server:bootRun To start the client application: ./gradlew client:bootRun To start both client and Grails applications: ./gradlew bootRun --parallel

Run the frontend unit tests and Grails unit tests: ./gradlew test Run the frontend e2e and grails integration tests: ./gradlew integrationTest

Node.js/npm is not required when using the Gradle tasks above, but is supported if installed. E.g., from the client directory, start the client application: npm start

Deploy (to Heroku)

Follow this: https://github.com/wellsst/diceware

Note: You should enable a secure HTTPS connection, this may help: https://letsencrypt.org/getting-started/

Currently this stores in localStorage this is vulnerable to XSS unless running https (see: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage)

Check:

  1. Your signing algorithm is strong enough for your purposes
  2. The signing key is stored safely, at least needing only a specific user that can read the contents, or store this in a different external location that is locked down and/or encrypted, currently this is config 'app.jwt.key' in application.yml

Note: Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide, and the simplicity of protecting against CSRF with modern web frameworks. HTML5 Web Storage is vulnerable to XSS, has a larger attack surface area, and can impact all application users on a successful attack.

"Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP."

Getting started

After startup go to: http://localhost:8080/util, this will generate a random signing key. Copy and paste this into application.yml under the app.jwt.key

For this to work in a production environment the whole thing hinges on running over a secure HTTPS connection. THere are a couple of ways to do this Start from the server-side This might help as well: https://docs.rundeck.com/docs/administration/security/configuring-ssl.html

Consider running a local mail server such as https://mailslurper.com or point to your development one by editing application.yml

Basic 'Happy path'...

Landing page

A user will see this public unsecured page as an entry point to your app, with a warning if it is not running over a secure connection

Landing page

Registration request

User wants to signup with the service

Reg Request

Registration acceptance

Server has sent an email to the user with a unique and expiring link, they are shown a challengeId that they must soon enter

Reg accept

The basic email for the next steps

Email

User clicks on the link in the email and enters the challengeId

Enter challenge ID

Registration complete

Reg complete

On the server you can currently see this via the graphql browser, it looks like:

{
  "data": {
    "userList": [
      {
        "id": 1,
        "username": "[email protected]",
        "loginToken": "eyJhbGciOlJIUzM4NCJ9.eyJpc3MiOiJqd3QsdGVtcGxhdGUiLCJzdWIiOiJ3ZWxsc3N0QDdtYWlsLmNvbSIsImlhdCI6MTU2MDk4Nzg2MiwibmJmIjoxNTYwOTg3ODYyLCJleHAiOjE1OTI1MjM4NjN9.uvMFlPaUzBJY3EgnP5QR-4kG8HZchT7h98pPKUZQ-XJjH86aTnDDtZ6K5k_XOB4b",
        "registrationRequest": {
          "requestId": "2b39117a-ad62-431d-a250-e15308723524",
          "dateCreated": "2019-06-19T23:43:49Z",
          "challengeId": "8886"
        }
      }
    ]
  }
}

User can now view the previously guarded page

View guarded page

TODO

  • Server should also warn of non-secure connection when exchanging JWT
  • User can expire their own tokens
  • Improve unit tests on client and server
  • Add admin type/util features such as list users token, expire tokens
  • User login history
  • Lockdown the grails graphQL service

Dependencies

GraphQL

References and inspiration

About

JWT by example with Grails, Angular and a peppering of GraphQL

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published