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

A Deep Dive into Sessions

A Deep Dive into Sessions

What if your Rails app couldn’t tell who was visiting it? If you had no idea that the same person requested two different pages? If all the data you stored vanished as soon as you returned a response? The session is the perfect place to put this kind of data.

But sessions can be a little magical. What is a session? How does Rails know to show the right data to the right person? And how do you decide where you keep your session data?

Justin Weiss

April 25, 2017
Tweet

More Decks by Justin Weiss

Other Decks in Programming

Transcript

  1. @justinweiss
    #deep-sessions
    A Deep Dive into Sessions
    Justin Weiss

    View Slide

  2. @justinweiss
    #deep-sessions

    View Slide

  3. justinweiss.com

    View Slide

  4. @justinweiss
    #deep-sessions
    A Deep Dive into Sessions
    Justin Weiss

    View Slide

  5. View Slide

  6. @justinweiss
    #deep-sessions
    We need to know our users

    View Slide

  7. View Slide

  8. @justinweiss
    #deep-sessions
    http: //catphotos.com/?breed=Persian&
    location=Seattle&user=justin

    View Slide

  9. @justinweiss
    #deep-sessions
    http: //catphotos.com/?breed=Persian&
    location=Seattle&user=admin

    View Slide

  10. @justinweiss
    #deep-sessions
    session[:current_user_id] = @user.id

    View Slide

  11. @justinweiss
    #deep-sessions
    Thank you!

    View Slide

  12. @justinweiss
    #deep-sessions
    session[:current_user_id] = @user.id

    View Slide

  13. @justinweiss
    #deep-sessions
    Always?

    View Slide

  14. View Slide

  15. @justinweiss
    #deep-sessions
    My Three Phases of
    Understanding
    1. Do more of the thing that isn’t working

    View Slide

  16. View Slide

  17. @justinweiss
    #deep-sessions
    My Three Phases of
    Understanding
    1. Do more of the thing that isn’t working
    2. Avoid the thing that isn’t working

    View Slide

  18. @justinweiss
    #deep-sessions
    My Three Phases of
    Understanding
    1. Do more of the thing that isn’t working
    2. Avoid the thing that isn’t working
    3. Learn the thing! (And use it correctly)

    View Slide

  19. @justinweiss
    #deep-sessions
    Know about a user,
    securely,
    until they leave.

    View Slide

  20. View Slide

  21. @justinweiss
    #deep-sessions
    http: //catphotos.com/?breed=Persian&
    location=Seattle&user=justin

    View Slide

  22. @justinweiss
    #deep-sessions
    HTTP/1.1 200 OK
    Date: Wed, 08 Mar 2017 22:57:05 GMT
    ...
    X-Params-Breed: Persian
    ...

    View Slide

  23. @justinweiss
    #deep-sessions
    HTTP/1.1 200 OK
    Date: Wed, 08 Mar 2017 22:57:05 GMT
    ...
    X-Params-Breed: Persian
    ...

    View Slide

  24. View Slide

  25. @justinweiss
    #deep-sessions
    It’s managed by the browser,
    not the server

    View Slide

  26. @justinweiss
    #deep-sessions
    What does a cookie
    look like?

    View Slide

  27. @justinweiss
    #deep-sessions
    $ curl -I http: // www.google.com
    HTTP/1.1 200 OK
    Date: Wed, 08 Mar 2017 22:57:05 GMT
    Expires: -1
    Cache-Control: private, max-age=0
    Content-Type: text/html; charset=ISO-8859-1
    Server: gws
    X-XSS-Protection: 1; mode=block
    X-Frame-Options: SAMEORIGIN
    Set-Cookie: NID=98=T ...
    Transfer-Encoding: chunked
    Accept-Ranges: none

    View Slide

  28. @justinweiss
    #deep-sessions
    $ curl -I http: // www.google.com
    HTTP/1.1 200 OK
    Date: Wed, 08 Mar 2017 22:57:05 GMT
    Expires: -1
    Cache-Control: private, max-age=0
    Content-Type: text/html; charset=ISO-8859-1
    Server: gws
    X-XSS-Protection: 1; mode=block
    X-Frame-Options: SAMEORIGIN
    Set-Cookie: NID=98=T ...
    Transfer-Encoding: chunked
    Accept-Ranges: none

    View Slide

  29. @justinweiss
    #deep-sessions
    GET / HTTP/1.1
    User-Agent: curl/7.37.1
    Host: www.google.com
    ...
    Cookie: NID=98=T ...

    View Slide

  30. @justinweiss
    #deep-sessions
    < HTTP/1.1 200 OK
    < …
    < Set-Cookie: NID=98=T ...
    > GET / HTTP/1.1
    > Host: www.google.com
    > ...
    > Cookie: NID=98=T ...

    View Slide

  31. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep-2017 22:57:05 GMT; \
    path=/; domain=.google.com; HttpOnly

    View Slide

  32. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep-2017 22:57:05 GMT; \
    path=/; domain=.google.com; HttpOnly

    View Slide

  33. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep-2017 22:57:05 GMT; \
    path=/; domain=.google.com; HttpOnly

    View Slide

  34. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep-2017 22:57:05 GMT; \
    path=/; domain=.google.com; HttpOnly

    View Slide

  35. @justinweiss
    #deep-sessions
    okie: name=justin; expi
    th=/; domain=.google.co

    View Slide

  36. @justinweiss
    #deep-sessions
    ; expires=Thu, 07-Sep-2017 22:57:05 GMT;
    gle.com; HttpOnly

    View Slide

  37. @justinweiss
    #deep-sessions
    Cookie: name=justin; path=/; domain=.google.com; HttpOnly

    View Slide

  38. View Slide

  39. @justinweiss
    #deep-sessions
    ; expires=Thu, 07-Sep-2017 22:57:05 GMT;
    gle.com; HttpOnly

    View Slide

  40. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep
    path=/; domain=.google.com; HttpOnly

    View Slide

  41. @justinweiss
    #deep-sessions
    Cookie: name=justin; expires=Thu, 07-Sep
    path=/; domain=.google.com; HttpOnly
    @justinweiss
    #deep-sessions

    View Slide

  42. @justinweiss
    #deep-sessions
    =justin; expires=Thu, 07-Sep-2017 22:57:0
    in=.google.com; HttpOnly

    View Slide

  43. @justinweiss
    #deep-sessions
    What does this have to do
    with sessions?

    View Slide

  44. @justinweiss
    #deep-sessions
    –Archimedes, Junior Web Developer
    Give a programmer a hash table
    and they will move the earth.

    View Slide

  45. @justinweiss
    #deep-sessions
    Set-Cookie: name=Justin;
    Set-Cookie: favorite_color=Blue;
    Set-Cookie: preferred_language=Ruby;

    View Slide

  46. @justinweiss
    #deep-sessions
    Set-Cookie: username=justin; path=/; HttpOnly

    View Slide

  47. @justinweiss
    #deep-sessions
    Set-Cookie: username=admin; path=/; HttpOnly

    View Slide

  48. @justinweiss
    #deep-sessions
    class UsersController < ApplicationController
    def greet
    session[:name] = params[:name] if params[:name]
    render plain: "Hello, #{session[:name]}!"
    end
    end

    View Slide

  49. @justinweiss
    #deep-sessions
    class UsersController < ApplicationController
    def greet
    session[:name] = params[:name] if params[:name]
    render plain: "Hello, #{session[:name]}!"
    end
    end

    View Slide

  50. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie:
    _session_my_app=OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3
    bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjdTlueEo1
    Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGhxYjFEWjZjb2Y3ZWln
    PT0%3D --533f89e5525959c122e31ff7eae5b886b2ed7fe9; path=/;
    HttpOnly

    View Slide

  51. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie:
    _session_my_app=OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3
    bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjdTlueEo1
    Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGhxYjFEWjZjb2Y3ZWln
    PT0%3D --533f89e5525959c122e31ff7eae5b886b2ed7fe9; path=/;
    HttpOnly

    View Slide

  52. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie:
    _session_my_app=OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3
    bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjdTlueEo1
    Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGhxYjFEWjZjb2Y3ZWln
    PT0%3D --533f89e5525959c122e31ff7eae5b886b2ed7fe9; path=/;
    HttpOnly

    View Slide

  53. @justinweiss
    #deep-sessions
    Rails.application.config.session_store :cookie_store,
    key: '_session_my_app'
    config/initializers/session_store.rb

    View Slide

  54. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie:
    _session_my_app=OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3
    bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjdTlueEo1
    Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGhxYjFEWjZjb2Y3ZWln
    PT0%3D --533f89e5525959c122e31ff7eae5b886b2ed7fe9; path=/;
    HttpOnly

    View Slide

  55. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie:
    _session_my_app=OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3
    bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjdTlueEo1
    Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGhxYjFEWjZjb2Y3ZWln
    PT0%3D --533f89e5525959c122e31ff7eae5b886b2ed7fe9; path=/;
    HttpOnly

    View Slide

  56. View Slide

  57. @justinweiss
    #deep-sessions
    production:
    secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
    config/secrets.yml

    View Slide

  58. @justinweiss
    #deep-sessions
    Rails.application.key_generator

    View Slide

  59. @justinweiss
    #deep-sessions
    secret = Rails.application.key_generator
    .generate_key("encrypted cookie")
    sign_secret = Rails.application.key_generator
    .generate_key("signed encrypted cookie")
    encryptor = ActiveSupport ::MessageEncryptor.new(
    secret,
    sign_secret,
    serializer: ActiveSupport ::MessageEncryptor ::NullSerializer)

    View Slide

  60. @justinweiss
    #deep-sessions
    encryptor.decrypt_and_verify("OXJ2SkhNaFZBWDd1eDU3djhSekZRdmN6W
    jNKUjN4dlBiMWt3bW9sVjM0OERIZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0
    S3AvMVNjdTlueEo1Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21SL2tIMGh
    xYjFEWjZjb2Y3ZWlnPT0= --533f89e5525959c122e31ff7eae5b886b2ed7fe9
    ")

    View Slide

  61. @justinweiss
    #deep-sessions
    {
    "session_id":"35481e34ef3c0d0ac83e4dccf8520120",
    "name":"Justin"
    }

    View Slide

  62. @justinweiss
    #deep-sessions
    Rails.application.config.
    action_dispatch.cookies_serializer = :json
    config/initializers/cookies_serializer.rb

    View Slide

  63. @justinweiss
    #deep-sessions
    • Rails stores session data inside a single cookie
    • By default, the session data is turned into
    JSON
    • Rails signs and encrypts the cookie
    • The session key and serializer can be
    configured to be something different

    View Slide

  64. @justinweiss
    #deep-sessions
    {
    "session_id":"35481e34ef3c0d0ac83e4dccf8520120",
    "name":"Justin"
    }

    View Slide

  65. @justinweiss
    #deep-sessions
    class UsersController < ApplicationController
    def greet
    session[:name] = params[:name] if params[:name]
    render plain: "Hello, #{session[:name]}!"
    end
    end

    View Slide

  66. @justinweiss
    #deep-sessions
    curl -H "Cookie: _session_my_app=OXJ2SkhNaFZBW
    Dd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3bW9sVjM0OER
    IZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjd
    TlueEo1Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21
    SL2tIMGhxYjFEWjZjb2Y3ZWlnPT0=—533f89e5525959c
    122e31ff7eae5b886b2ed7fe9; path=/; HttpOnly"
    "http: //localhost:3000/users/greet"
    Hello, Justin!

    View Slide

  67. @justinweiss
    #deep-sessions
    curl -H "Cookie: _session_my_app=OXJ2SkhNaFZBW
    Dd1eDU3djhSekZRdmN6WjNKUjN4dlBiMWt3bW9sVjM0OER
    IZ3lPUmV1UFB2MmlySzI0OXJtbTRDdmI3TGd0S3AvMVNjd
    TlueEo1Y05zMnE3NTdsMVVmWWFVSXA5NVFOT0U9LS1tM21
    SL2tIMGhxYjFEWjZjb2Y3ZWlnPT0=—533f89e5525959c
    122e31ff7eae5b886b2ed7fe9; path=/; HttpOnly"
    "http: //localhost:3000/users/greet"
    Hello, Justin!

    View Slide

  68. @justinweiss
    #deep-sessions

    View Slide

  69. @justinweiss
    #deep-sessions

    View Slide

  70. @justinweiss
    #deep-sessions

    View Slide

  71. @justinweiss
    #deep-sessions

    View Slide

  72. @justinweiss
    #deep-sessions

    View Slide

  73. @justinweiss
    #deep-sessions
    Sessions beyond cookies

    View Slide

  74. @justinweiss
    #deep-sessions
    curl -H "Cookie: _session_my_app={\"book\": Call me Ishmael. Some years
    ago—never mind how long precisely—having little or no money in my purse,
    and nothing particular to interest me on shore, I thought I would sail
    about a little and see the watery part of the world. It is a way I have
    of driving off the spleen and regulating the circulation. Whenever I
    find myself growing grim about the mouth; whenever it is a damp, drizzly
    November in my soul; whenever I find myself involuntarily pausing before
    coffin warehouses, and bringing up the rear of every funeral I meet; and
    especially whenever my hypos get such an upper hand of me, that it
    requires a strong moral principle to prevent me from deliberately
    stepping into the street, and methodically knocking people’s hats off—
    then, I account it high time to get to sea as soon as I can. This is my
    substitute for pistol and ball. With a philosophical flourish Cato
    throws himself upon his sword; I quietly take to the ship. There is
    nothing surprising in this. If they but knew it, almost all men in their
    degree, some time or other, cherish very nearly the same feelings
    towards the ocean with me. There now is your insular city of the
    Manhattoes, belted round by wharves as Indian isles by coral reefs—
    commerce surrounds it with her surf. Right and left, the streets take

    View Slide

  75. @justinweiss
    #deep-sessions
    curl -H "Cookie: _session_my_app={\"book\": Call me Ishmael. Some years
    ago—never mind how long precisely—having little or no money in my purse,
    and nothing particular to interest me on shore, I thought I would sail
    about a little and see the watery part of the world. It is a way I have
    of driving off the spleen and regulating the circulation. Whenever I
    find myself growing grim about the mouth; whenever it is a damp, drizzly
    November in my soul; whenever I find myself involuntarily pausing before
    coffin warehouses, and bringing up the rear of every funeral I meet; and
    especially whenever my hypos get such an upper hand of me, that it
    requires a strong moral principle to prevent me from deliberately
    stepping into the street, and methodically knocking people’s hats off—
    then, I account it high time to get to sea as soon as I can. This is my
    substitute for pistol and ball. With a philosophical flourish Cato
    throws himself upon his sword; I quietly take to the ship. There is
    nothing surprising in this. If they but knew it, almost all men in their
    degree, some time or other, cherish very nearly the same feelings
    towards the ocean with me. There now is your insular city of the
    Manhattoes, belted round by wharves as Indian isles by coral reefs—
    commerce surrounds it with her surf. Right and left, the streets take

    View Slide

  76. @justinweiss
    #deep-sessions
    ActionDispatch::Cookies::CookieOverflow

    View Slide

  77. COOKIE
    OVERFLOW

    View Slide

  78. @justinweiss
    #deep-sessions
    How do you keep your
    cookies small?

    View Slide

  79. @justinweiss
    #deep-sessions
    user_id=1; expires=Thu, 07-Sep-2017 22:57:05 GMT; path=/;
    domain=.google.com; HttpOnly

    View Slide

  80. @justinweiss
    #deep-sessions
    What if you don't have
    an account?

    View Slide

  81. @justinweiss
    #deep-sessions
    user_id=35481e34ef3c0d0ac83e4dccf8520120; expires=Thu, 07-
    Sep-2017 22:57:05 GMT; path=/; domain=.google.com; HttpOnly

    View Slide

  82. @justinweiss
    #deep-sessions
    session_id=35481e34ef3c0d0ac83e4dccf8520120; expires=Thu, 07-
    Sep-2017 22:57:05 GMT; path=/; domain=.google.com; HttpOnly

    View Slide

  83. @justinweiss
    #deep-sessions
    1. Store the data in the cookie
    2. Store a reference to the data in the cookie

    View Slide

  84. @justinweiss
    #deep-sessions
    session[:name] = "Justin"

    View Slide

  85. @justinweiss
    #deep-sessions
    Creating an ActiveRecord session
    1. Generate a new random session id
    2. Turn the session hash into a string
    3. Save the id and data to a sessions table in
    your database
    4. Return the session id with Set-Cookie:

    View Slide

  86. @justinweiss
    #deep-sessions
    Rails.application.config.session_store :cookie_store,
    key: '_session_my_app'

    View Slide

  87. @justinweiss
    #deep-sessions
    Rails.application.config.session_store :active_record_store,
    key: '_session_my_app'

    View Slide

  88. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie: _session_my_app=a6c4946995fe1a7fe0e472610c368858;
    path=/; HttpOnly
    Hello, Justin!

    View Slide

  89. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie: _session_my_app=a6c4946995fe1a7fe0e472610c368858;
    path=/; HttpOnly
    Hello, Justin!

    View Slide

  90. @justinweiss
    #deep-sessions
    $ curl -i "http: //localhost:3000/users/greet?name=Justin"
    HTTP/1.1 200 OK
    ...
    Set-Cookie: _session_my_app=a6c4946995fe1a7fe0e472610c368858; path=/;
    HttpOnly
    Hello, Justin!
    session_id | data
    a6c4946995fe1a7fe0e472610c368858 | BAh7BkkiCW5hbWUGOgZFRkkiC0p1c3RpbgY7AFQ=

    View Slide

  91. @justinweiss
    #deep-sessions
    curl -H "Cookie: _session_my_app=a6c4946995fe1a7fe0e472610c368858; path=/; HttpOnly"
    "http: //localhost:3000/users/greet"
    Hello, Justin!

    View Slide

  92. @justinweiss
    #deep-sessions
    Finding an ActiveRecord session
    1. Grab the session id out of the cookie
    2. Look up the session id in the database
    3. Grab the data associated with that id
    4. Turn that data back into the sessions hash

    View Slide

  93. @justinweiss
    #deep-sessions
    CacheStore
    ActiveRecordStore
    RedisSessionStore
    MongoSessionStore

    View Slide

  94. @justinweiss
    #deep-sessions
    Your Very Own Session Store
    • find_session
    • write_session
    • delete_session

    View Slide

  95. @justinweiss
    #deep-sessions
    Two kinds of session store
    • CookieStore: store all data in the cookie
    • Everything Else: store a pointer to data in
    the cookie

    View Slide

  96. @justinweiss
    #deep-sessions
    Two kinds of session store
    • CookieStore: store all data in the cookie
    • Everything Else: store a pointer to data in
    the cookie

    View Slide

  97. @justinweiss
    #deep-sessions
    Which session store is
    right for you?

    View Slide

  98. @justinweiss
    #deep-sessions
    Cookie Store
    • No extra setup
    • Syncs with the browser lifecycle
    • Can only store 4kb of data
    • Risk of session replay attacks

    View Slide

  99. @justinweiss
    #deep-sessions
    Cookie Store
    • No extra setup
    • Syncs with the browser lifecycle
    • Can only store 4kb of data
    • Risk of session replay attacks

    View Slide

  100. @justinweiss
    #deep-sessions
    CacheStore
    • You probably already have a cache
    • Built into Rails
    • Fast -- usually kept in memory
    • Sessions and cache fight for space - sessions can
    get kicked out
    • Resetting your cache expires all sessions

    View Slide

  101. @justinweiss
    #deep-sessions
    CacheStore
    • You probably already have a cache
    • Built into Rails
    • Fast -- usually kept in memory
    • Sessions and cache fight for space - sessions can
    get kicked out
    • Resetting your cache expires all sessions

    View Slide

  102. @justinweiss
    #deep-sessions
    CacheStore
    • You probably already have a cache
    • Built into Rails
    • Fast -- usually kept in memory
    • Sessions and cache fight for space - sessions can
    get kicked out
    • Resetting your cache expires all sessions

    View Slide

  103. @justinweiss
    #deep-sessions
    CacheStore
    • You probably already have a cache
    • Built into Rails
    • Fast -- usually kept in memory
    • Sessions and cache fight for space - sessions can
    get kicked out
    • Resetting your cache expires all sessions

    View Slide

  104. @justinweiss
    #deep-sessions
    DatabaseStore
    • Keeps session data around until expiration
    • Need to clean up expired sessions
    • Might have capacity issues as session data
    grows

    View Slide

  105. @justinweiss
    #deep-sessions
    DatabaseStore
    • Keeps session data around until expiration
    • Need to clean up expired sessions
    • Might have capacity issues as session data
    grows

    View Slide

  106. @justinweiss
    #deep-sessions
    DatabaseStore
    • Keeps session data around until expiration
    • Need to clean up expired sessions
    • Might have capacity issues as session data
    grows

    View Slide

  107. @justinweiss
    #deep-sessions
    What’s the best session store?
    • CookieStore
    • CacheStore
    • Database Store

    View Slide

  108. View Slide

  109. @justinweiss
    #deep-sessions
    Leaking Session IDs

    View Slide

  110. View Slide

  111. View Slide

  112. @justinweiss
    #deep-sessions
    Use HTTPS!

    View Slide

  113. @justinweiss
    #deep-sessions
    config.force_ssl = true
    config/environments/production.rb

    View Slide

  114. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=d01b4e1c3d9238e82452c678d0660cf4;
    path=/; secure; HttpOnly

    View Slide

  115. @justinweiss
    #deep-sessions
    JavaScript
    and
    Cross-site Scripting

    View Slide

  116. @justinweiss
    #deep-sessions
    document.cookie

    View Slide

  117. View Slide

  118. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=d01b4e1c3d9238e82452c678d0660cf4;
    path=/; HttpOnly

    View Slide

  119. @justinweiss
    #deep-sessions
    Replay Attacks

    View Slide

  120. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=
    '{"session_id":"35481e34ef3c0d0ac83e4dccf8520120",
    "credit":"400"}'

    View Slide

  121. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=
    '{"session_id":"35481e34ef3c0d0ac83e4dccf8520120",
    "credit":"9999999"}'

    View Slide

  122. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=encrypted-string-with-value-400
    Cookie: _session_my_app=encrypted-string-with-value-400
    Set-Cookie: _session_my_app=encrypted-string-with-value-300
    Cookie: _session_my_app=encrypted-string-with-value-400

    View Slide

  123. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=encrypted-string-with-value-400
    Cookie: _session_my_app=encrypted-string-with-value-400
    Set-Cookie: _session_my_app=encrypted-string-with-value-300
    Cookie: _session_my_app=encrypted-string-with-value-400

    View Slide

  124. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=encrypted-string-with-value-400
    Cookie: _session_my_app=encrypted-string-with-value-400
    Set-Cookie: _session_my_app=encrypted-string-with-value-300
    Cookie: _session_my_app=encrypted-string-with-value-400

    View Slide

  125. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=encrypted-string-with-value-400
    Cookie: _session_my_app=encrypted-string-with-value-400
    Set-Cookie: _session_my_app=encrypted-string-with-value-300
    Cookie: _session_my_app=encrypted-string-with-value-400

    View Slide

  126. @justinweiss
    #deep-sessions
    Set-Cookie: _session_my_app=encrypted-string-with-value-400
    Cookie: _session_my_app=encrypted-string-with-value-400
    Set-Cookie: _session_my_app=encrypted-string-with-value-300
    Cookie: _session_my_app=encrypted-string-with-value-400

    View Slide

  127. @justinweiss
    #deep-sessions
    Session Best Practices

    View Slide

  128. @justinweiss
    #deep-sessions
    Prepare for the session
    to go away at any time

    View Slide

  129. @justinweiss
    #deep-sessions
    Don’t store
    complex objects

    View Slide

  130. @justinweiss
    #deep-sessions
    # == Schema Information
    #
    # Table name: cart_items
    #
    # id :integer not null, primary key
    # title :string
    # quantity :integer
    # created_at :datetime
    # updated_at :datetime
    #
    class CartItem < ActiveRecord ::Base
    ...
    end

    View Slide

  131. @justinweiss
    #deep-sessions
    # == Schema Information
    #
    # Table name: cart_items
    #
    # id :integer not null, primary key
    # name :string
    # quantity :integer
    # created_at :datetime
    # updated_at :datetime
    #
    class CartItem < ActiveRecord ::Base
    ...
    end

    View Slide

  132. View Slide

  133. @justinweiss
    #deep-sessions

    ❌ Reverse the change

    ❌ Delete all sessions

    ✅ Go into the corner and cry

    View Slide

  134. @justinweiss
    #deep-sessions

    ❌ Reverse the change

    ❌ Delete all sessions

    ✅ Go into the corner and cry

    View Slide

  135. @justinweiss
    #deep-sessions
    Store references
    to objects,
    not objects themselves.

    View Slide

  136. @justinweiss
    #deep-sessions
    Use sessions
    with intent

    View Slide

  137. @justinweiss
    #deep-sessions
    Use sessions
    with intent

    View Slide

  138. @justinweiss
    #deep-sessions
    Use sessions
    with intent

    View Slide

  139. @justinweiss
    #deep-sessions
    How to debug
    session problems

    View Slide

  140. @justinweiss
    #deep-sessions
    Isolate the problem

    View Slide

  141. @justinweiss
    #deep-sessions
    expected input

    problem area

    expected output

    View Slide

  142. View Slide

  143. @justinweiss
    #deep-sessions
    What if your server’s
    working fine?

    View Slide

  144. @justinweiss
    #deep-sessions
    mitmproxy

    View Slide

  145. View Slide

  146. @justinweiss
    #deep-sessions
    Check your domain settings!
    path=/; domain=.google.com;

    View Slide

  147. @justinweiss
    #deep-sessions
    Decrypt your cookies
    CookieDecryptor.decrypt("OXJ2SkhN…")

    View Slide

  148. @justinweiss
    #deep-sessions
    Sessions are core to
    the modern web

    View Slide

  149. View Slide

  150. @justinweiss
    #deep-sessions
    Complexity layered on
    • More data? Serialize it / Store a pointer.
    • Tampering? Add encryption.
    • Cross-site Scripting? Add HttpOnly.
    • Snooping? Add Secure.

    View Slide

  151. It’s just code

    View Slide

  152. It’s just code

    View Slide

  153. @justinweiss
    #deep-sessions
    My Three Phases of
    Understanding
    1. Do more of the thing that isn’t working
    2. Avoid the thing that isn’t working
    3. Learn the thing! (And use it correctly)

    View Slide

  154. View Slide

  155. @justinweiss
    #deep-sessions
    Justin Weiss
    @justinweiss
    https://www.avvo.com
    [email protected]
    https://www.justinweiss.com/railsconf-2017
    Thank you!

    View Slide

  156. @justinweiss
    #deep-sessions
    Justin Weiss
    @justinweiss
    https://www.avvo.com
    [email protected]
    https://www.justinweiss.com/railsconf-2017
    Thank you!

    View Slide

  157. @justinweiss
    #deep-sessions
    Justin Weiss
    @justinweiss
    https://www.avvo.com
    [email protected]
    https://www.justinweiss.com/railsconf-2017
    Thank you!

    View Slide

  158. @justinweiss
    #deep-sessions
    Justin Weiss
    @justinweiss
    https://www.avvo.com
    [email protected]
    https://www.justinweiss.com/railsconf-2017
    Thank you!

    View Slide

  159. @justinweiss
    #deep-sessions
    Image Credits

    View Slide