Stateless authentication w/ JSON Web Tokens

Stateless authentication w/ JSON Web Tokens

5f81e2d2889d7642fd84c8b24db7ee17?s=128

DamirSvrtan

October 06, 2017
Tweet

Transcript

  1. Authentication with JSON Web Tokens

  2. 01 API AUTHENTICATION

  3. CLIENT SERVER EMAIL=JOHN@EXAMPLE.COM&PASSWORD=PASS123 AUTH_TOKEN=RAND0M$TR1N6

  4. CLIENT SERVER ARTICLES?AUTH_TOKEN=RAND0M$TR1N6

  5. 02 SINGLE AUTH TOKEN PER USER

  6. id email password_digest auth_token 1 damir@gmail.com $2a$10$5FkD.. 23ZS921a USERS TABLE

  7. GENERATE A RANDOM AUTH TOKEN class User before_save :generate_auth_token def

    generate_auth_token loop do self.auth_token = Devise.friendly_token break if User.find_by_auth_token(auth_token).nil? end end end
  8. PROBLEMS WITH THE SINGLE AUTH TOKEN APPROACH

  9. NAIVE IMPLEMENTATIONS NEVER EXPIRE THEM

  10. STORING IT IN PLAIN TEXT

  11. ISN’T THAT THE SAME AS STORING PASSWORDS IN PLAIN TEXT?

  12. NOT QUITE

  13. • difficult to change • used across several services PASSWORDS

  14. • easy to change • auto-generated, random, unique • not

    used across several services AUTH TOKENS
  15. 03 SINGLE HASHED AUTH TOKEN PER USER

  16. NOT STORING IT IN PLAIN TEXT

  17. BROWSER SERVER EM AIL=DAM IR@ EXAM PLE.COM &PASSW ORD=PASS123 AUTH_TOKEN=RAND0M

    $TR1N6 EM AIL=DAM IR@ EXAM PLE.COM &PASSW ORD=PASS123 MOBILE AUTH_TOKEN=ANOTHER-RAND0M $TR1N6
  18. 04 MULTIPLE HASHED AUTH TOKENS PER USER

  19. user_id token_digest 1 $2a$10$5FkD.. 2 $3R$D9S21$.. 1 $23$2sBPSA.. AUTH TOKENS

    TABLE
  20. ERASE TOKENS PERIODICALLY

  21. 0Rel STORE TOKENS NOWHERE WHAT IF WE DIDN’T STORE THEM

    ANYWHERE?
  22. LET’S DO SOMETHING SIMILAR TO RAILS SESSIONS!

  23. 05 RAILS SESSION STORAGE

  24. CLIENT SERVER EMAIL=JOHN@EXAMPLE.COM&PASSWORD=PASS123 SET-COOKIE: APP_SESSION=23OFSKL932RDASDAFSFJ23

  25. session[:user_id] = current_user.id

  26. sign(encrypt(hash))

  27. CLIENT SERVER APP_SESSION=23OFSKL932RDASDAFSFJ23

  28. decrypt(verify_signature(cookie))

  29. User.find(session[:user_id])

  30. WE COULD DO SOMETHING SIMILAR… … OR FOLLOW AN OPEN

    STANDARD
  31. 06 JSON WEB TOKENS

  32. JSON Web Tokens are an open standard that defines a

    compact and self-contained way to securely share information between parties as a JSON Object.
  33. CLIENT SERVER EMAIL=DAMIR@EXAMPLE.COM&PASSWORD=PASS123 AUTH_TOKEN=33WE.DAS3Q.ADAS

  34. TO THE API CONSUMER IT CAN LOOK RANDOM..

  35. ..BUT IT’S MUCH MORE

  36. IT STORES INFORMATION INSIDE OF IT.

  37. DATA + SIGNATURE

  38. DATA + SIGNATURE data = { "user_id": 231 } token

    = data + sign(data)
  39. ABASASD.U93RJADSF.ASASD

  40. ABASASD.U93RJADSF.ASASD HEADER.PAYLOAD.SIGNATURE

  41. THE JWT HEADER

  42. { "typ": "JWT", "alg": "HS256" } HEADER

  43. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 BASE64 ENCODED HEADER

  44. THE JWT BODY

  45. { “user_id": 231, "exp": 1300819380, } BODY

  46. eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjE BASE64 ENCODED BODY

  47. THE JWT SIGNATURE

  48. encoded_string = Base64.encode64(header) + "." + Base64.encode64(payload); OpenSSL::HMAC.hexdigest( OpenSSL::Digest.new(‘sha256'), Rails.application.secrets.secret_key_base,

    encoded_string ) GENERATE A SIGNATURE
  49. SIGNATURE 03f329983b86f7d9a9f5fef85305880101d

  50. JSON WEB TOKEN eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e yJpc3MiOiJzY290Y2guaW8iLCJleHAiOjE. 03f329983b86f7d9a9f5fef85305880101d

  51. iss: The issuer of the token sub: The subject of

    the token exp: This will define the expiration in NumericDate value. nbf: Defines the time before which the JWT MUST NOT be accepted for processing iat: The time the JWT was issued. Can be used to determine the age of the JWT BODY CLAIMS
  52. 08 JWT <> RAILS SESSIONS

  53. RAILS SESSIONS ARE ENCRYPTED JWT’S ARE SIGNED

  54. RAILS SESSIONS CAN’T BE READ ON THE CLIENT SIDE JWT’S

    CAN BE READ ON THE CLIENT SIDE
  55. SECRET INFORMATION IN JWT’S MUST BE EXPLICITLY ENCRYPTED

  56. 09 STATELESS AUTH

  57. { “user_id": 231 } BODY

  58. FORCE LOGOUT / ACCOUNT HIJACKING

  59. 10 REVOCATION

  60. HOW DOES DEVISE HANDLE THIS?

  61. INSERT A PART OF THE USERS PASSWORD HASH INTO THE

    PAYLOAD
  62. SESSION['WARDEN.USER.KEY'] [[1], "$2A$11$NNJPSD1Q36CG.PSQKPBU/U"]

  63. { "exp": 1300819380, “user_id": 1, “pwd_start": $2a$11$nnjPSD1q36Cg.PSqKPBU }

  64. DISABLE TOKENS WITH AN IAT CLAIM OLDER THAN 6.10.2017

  65. { “user_id": 231, "exp": 1300819380, "iat": 1300700011, } BODY

  66. id email password min_issued_at 1 damir@gmail.com $2a$10$5FkD.. 2017-09-09 08:59:06.750087

  67. JTI JSON TOKEN IDENTIFIER

  68. { "exp": 1300819380, "jti": 0A212BXC12, } BODY

  69. id email password jti 1 damir@gmail.com $2a$10$5FkD.. DSAY039R21S

  70. LOGOUTS DON’T INVALIDATE TOKENS

  71. 10 JWT ADVANTAGES

  72. SAFELY SHARE DATA WITH THE CLIENT APP

  73. { “user_id": 231, "admin": true, “permissions”: [‘read’, ‘write’] }

  74. SELF CONTAINED TIME-BASED EXPIRATION HANDLING

  75. SCALABILITY

  76. MICROSERVICES INFORMATION SHARING

  77. NOT REINVENTING THE WHEEL - USING AN OPEN STANDARD.

  78. LANGUAGE SUPPORT

  79. JWT.IO RUBY, ELIXIR, GO, PYTHON, JAVA, RUST..

  80. 11 RAILS IMPLEMENTATIONS

  81. None
  82. None
  83. None
  84. CONCLUSIONS

  85. SCALABILITY. SIMPLICITY. STANDARDIZATION.

  86. ALWAYS IMPLEMENT A REVOCATION TECHNIQUE

  87. NO SILVER BULLET.

  88. None
  89. Damir Svrtan Rails Team Lead @ infinum.co Organizer @ Ruby

    Zagreb Hit me up on twitter @DamirSvrtan