Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Stateless authentication w/ JSON Web Tokens

Stateless authentication w/ JSON Web Tokens

DamirSvrtan

October 06, 2017
Tweet

More Decks by DamirSvrtan

Other Decks in Programming

Transcript

  1. Authentication with
    JSON Web Tokens

    View Slide

  2. 01
    API AUTHENTICATION

    View Slide

  3. CLIENT
    SERVER
    [email protected]&PASSWORD=PASS123
    AUTH_TOKEN=RAND0M$TR1N6

    View Slide

  4. CLIENT
    SERVER
    ARTICLES?AUTH_TOKEN=RAND0M$TR1N6

    View Slide

  5. 02
    SINGLE AUTH TOKEN PER
    USER

    View Slide

  6. id email password_digest auth_token
    1 [email protected] $2a$10$5FkD.. 23ZS921a
    USERS TABLE

    View Slide

  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

    View Slide

  8. PROBLEMS WITH THE SINGLE
    AUTH TOKEN APPROACH

    View Slide

  9. NAIVE IMPLEMENTATIONS NEVER EXPIRE THEM

    View Slide

  10. STORING IT IN PLAIN TEXT

    View Slide

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

    View Slide

  12. NOT QUITE

    View Slide

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

    View Slide

  14. • easy to change
    • auto-generated, random, unique
    • not used across several services
    AUTH TOKENS

    View Slide

  15. 03
    SINGLE HASHED AUTH TOKEN
    PER USER

    View Slide

  16. NOT STORING IT IN PLAIN
    TEXT

    View Slide

  17. BROWSER
    SERVER
    EM
    AIL=DAM
    [email protected]
    EXAM
    PLE.COM
    &PASSW
    ORD=PASS123
    AUTH_TOKEN=RAND0M
    $TR1N6
    EM
    AIL=DAM
    [email protected]
    EXAM
    PLE.COM
    &PASSW
    ORD=PASS123
    MOBILE
    AUTH_TOKEN=ANOTHER-RAND0M
    $TR1N6

    View Slide

  18. 04
    MULTIPLE HASHED AUTH
    TOKENS PER USER

    View Slide

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

    View Slide

  20. ERASE TOKENS PERIODICALLY

    View Slide

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

    View Slide

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

    View Slide

  23. 05
    RAILS SESSION STORAGE

    View Slide

  24. CLIENT
    SERVER
    [email protected]&PASSWORD=PASS123
    SET-COOKIE: APP_SESSION=23OFSKL932RDASDAFSFJ23

    View Slide

  25. session[:user_id] = current_user.id

    View Slide

  26. sign(encrypt(hash))

    View Slide

  27. CLIENT
    SERVER
    APP_SESSION=23OFSKL932RDASDAFSFJ23

    View Slide

  28. decrypt(verify_signature(cookie))

    View Slide

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

    View Slide

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

    View Slide

  31. 06
    JSON WEB TOKENS

    View Slide

  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.

    View Slide

  33. CLIENT
    SERVER
    [email protected]&PASSWORD=PASS123
    AUTH_TOKEN=33WE.DAS3Q.ADAS

    View Slide

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

    View Slide

  35. ..BUT IT’S MUCH MORE

    View Slide

  36. IT STORES INFORMATION
    INSIDE OF IT.

    View Slide

  37. DATA + SIGNATURE

    View Slide

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

    View Slide

  39. ABASASD.U93RJADSF.ASASD

    View Slide

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

    View Slide

  41. THE JWT HEADER

    View Slide

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

    View Slide

  43. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    BASE64 ENCODED HEADER

    View Slide

  44. THE JWT BODY

    View Slide

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

    View Slide

  46. eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjE
    BASE64 ENCODED BODY

    View Slide

  47. THE JWT SIGNATURE

    View Slide

  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

    View Slide

  49. SIGNATURE
    03f329983b86f7d9a9f5fef85305880101d

    View Slide

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

    View Slide

  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

    View Slide

  52. 08
    JWT <> RAILS SESSIONS

    View Slide

  53. RAILS SESSIONS ARE
    ENCRYPTED
    JWT’S ARE SIGNED

    View Slide

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

    View Slide

  55. SECRET INFORMATION IN
    JWT’S MUST BE EXPLICITLY
    ENCRYPTED

    View Slide

  56. 09
    STATELESS AUTH

    View Slide

  57. { “user_id": 231 }
    BODY

    View Slide

  58. FORCE LOGOUT
    /
    ACCOUNT HIJACKING

    View Slide

  59. 10
    REVOCATION

    View Slide

  60. HOW DOES DEVISE HANDLE
    THIS?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  64. DISABLE TOKENS WITH AN
    IAT CLAIM OLDER THAN
    6.10.2017

    View Slide

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

    View Slide

  66. id email password min_issued_at
    1 [email protected] $2a$10$5FkD..
    2017-09-09
    08:59:06.750087

    View Slide

  67. JTI
    JSON TOKEN IDENTIFIER

    View Slide

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

    View Slide

  69. id email password jti
    1 [email protected] $2a$10$5FkD.. DSAY039R21S

    View Slide

  70. LOGOUTS DON’T INVALIDATE
    TOKENS

    View Slide

  71. 10
    JWT ADVANTAGES

    View Slide

  72. SAFELY SHARE DATA WITH
    THE CLIENT APP

    View Slide

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

    View Slide

  74. SELF CONTAINED TIME-BASED
    EXPIRATION HANDLING

    View Slide

  75. SCALABILITY

    View Slide

  76. MICROSERVICES
    INFORMATION SHARING

    View Slide

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

    View Slide

  78. LANGUAGE SUPPORT

    View Slide

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

    View Slide

  80. 11
    RAILS IMPLEMENTATIONS

    View Slide

  81. View Slide

  82. View Slide

  83. View Slide

  84. CONCLUSIONS

    View Slide

  85. SCALABILITY.
    SIMPLICITY.
    STANDARDIZATION.

    View Slide

  86. ALWAYS
    IMPLEMENT A
    REVOCATION
    TECHNIQUE

    View Slide

  87. NO SILVER BULLET.

    View Slide

  88. View Slide

  89. Damir Svrtan
    Rails Team Lead @ infinum.co
    Organizer @ Ruby Zagreb
    Hit me up on twitter @DamirSvrtan

    View Slide