Easy logins for Ruby web applications

Easy logins for Ruby web applications

Users hate picking and having to remember them. Developers hate dealing with and storing them. Why are we still using passwords again? Surely there is a better way to log into websites.

This talk will introduce the technology behind Persona and the BrowserID protocol. Mozilla intends to solve the password problem on the web with a federated cross-browser system that is intensely focused on user experience and privacy.

We may not be able to get rid of all passwords, after all, you probably don’t want to be subjected to a fingerprint check before leaving a comment on someone’s blog, but we can eliminate site-specific passwords and replace them with something better: a decentralized system that’s under the control of users, not a for-profit gatekeeper.

It’s just four easy steps to add it to your Ruby site/app from scratch and there are already plugins for Devise, Omniauth, Rails, Sinatra, and Warden.

0110e86fdb31486c22dd381326d99de9?s=128

Francois Marier

October 15, 2013
Tweet

Transcript

  1. François Marier – @fmarier Easy logins for Ruby web applications

  2. None
  3. None
  4. None
  5. None
  6. None
  7. None
  8. None
  9. None
  10. None
  11. None
  12. problem #1: passwords are hard to secure

  13. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery
  14. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery
  15. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery
  16. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery
  17. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery
  18. bcrypt / scrypt / pbkdf2 per-user salt site secret password

    & lockout policies secure recovery 2013 2013 password password guidelines guidelines
  19. passwords are hard to secure they are a liability

  20. ALTER TABLE user DROP COLUMN password;

  21. problem #2: passwords are hard to remember

  22. pick an easy password

  23. pick an easy password use it everywhere

  24. passwords are hard to remember they need to be reset

  25. None
  26. control email account control all accounts =

  27. None
  28. “People want a little dating before marriage.” Eric Vishria –

    Rockmelt
  29. None
  30. decentralised

  31. myid.com/u/francois

  32. None
  33. None
  34. privacy ®

  35. existing login systems are not good enough

  36. ideal web-wide identity system

  37. ideal web-wide identity system

  38. ideal web-wide identity system

  39. ideal web-wide identity system

  40. what if it were a standard part of the web

    browser?
  41. None
  42. how does it work?

  43. fmarier@gmail.com

  44. fmarier@gmail.com

  45. getting a proof of email ownership

  46. authenticate?

  47. authenticate? public key

  48. authenticate? public key signed public key

  49. you have a signed statement from your provider that you

    own your email address
  50. None
  51. logging into a 3rd party site

  52. Valid for: 2 minutes wikipedia.org assertion

  53. Valid for: 2 minutes wikipedia.org check audience assertion

  54. Valid for: 2 minutes wikipedia.org check audience check expiry assertion

  55. Valid for: 2 minutes wikipedia.org check audience check expiry check

    signature assertion
  56. assertion Valid for: 2 minutes wikipedia.org public key

  57. assertion Valid for: 2 minutes wikipedia.org

  58. assertion session cookie

  59. demo #1: http://www.voo.st/ http://www.debuggex.com fmariertest@eyedee.me

  60. Persona is already a decentralised system

  61. decentralisation is the answer, but it's not a product adoption

    strategy
  62. we can't wait for all domains to adopt Persona

  63. we can't wait for all domains to adopt Persona solution:

    a temporary centralised fallback
  64. demo #2: http://sloblog.io/ fmariertest@aol.com

  65. Persona already works with all email domains

  66. identity bridging

  67. demo #3: http://www.reasonwell.com/ fmariertest@yahoo.com

  68. None
  69. None
  70. None
  71. Persona supports all modern browsers >= 8

  72. Persona is decentralised, simple and cross-browser

  73. it's simple for users, but is it also simple for

    developers?
  74. None
  75. <script src=”https://login.persona.org/include.js”> </script> </body></html>

  76. navigator.id.watch({ loggedInEmail: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  77. navigator.id.watch({ loggedInUser: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  78. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  79. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  80. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  81. None
  82. navigator.id.request()

  83. None
  84. None
  85. None
  86. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  87. eyJhbGciOiJEUzEyOCJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IkRTIiwieSI6ImNhZDg2ZDg yNWU0MjBkMGI4Njk5MjM4ZDM5ZTFjYjIyOGMyMTk1NWFiMzcwOTQ1YzExNzBhMzM4NjcyNDM0ZDJmNGY xZDg5ZjFkZjMzNmU1ZjZjZjk2YjhiOTlmMjgyNmFjNTYxZmI1YWMyYTc4ZjNhMzBkNGYxNTVhYjc3ZGE xYmY3MWU4ZGMzNjQ0MmU2NjQ3MmE5Mjg0N2I2YjFlNDRkMTJlM2IwMjVjOWZmNTFmNDdhMWE5ZWYyMGZ hOTVjMTcxZjBkMTYzNGE4ZTY4YTk5NWU3ZjFjY2FiYTJlOTRjYTI3ODE1ZWVkMTcxYjY1YTJmZGQzNTE 1NjY3OTI0ZjUiLCJwIjoiZmY2MDA0ODNkYjZhYmZjNWI0NWVhYjc4NTk0YjM1MzNkNTUwZDlmMWJmMmE 5OTJhN2E4ZGFhNmRjMzRmODA0NWFkNGU2ZTBjNDI5ZDMzNGVlZWFhZWZkN2UyM2Q0ODEwYmUwMGU0Y2M xNDkyY2JhMzI1YmE4MWZmMmQ1YTViMzA1YThkMTdlYjNiZjRhMDZhMzQ5ZDM5MmUwMGQzMjk3NDRhNTE 3OTM4MDM0NGU4MmExOGM0NzkzMzQzOGY4OTFlMjJhZWVmODEyZDY5YzhmNzVlMzI2Y2I3MGVhMDAwYzN mNzc2ZGZkYmQ2MDQ2MzhjMmVmNzE3ZmMyNmQwMmUxNyIsInEiOiJlMjFlMDRmOTExZDFlZDc5OTEwMDh

    lY2FhYjNiZjc3NTk4NDMwOWMzIiwiZyI6ImM1MmE0YTBmZjNiN2U2MWZkZjE4NjdjZTg0MTM4MzY5YTY xNTRmNGFmYTkyOTY2ZTNjODI3ZTI1Y2ZhNmNmNTA4YjkwZTVkZTQxOWUxMzM3ZTA3YTJlOWUyYTNjZDV kZWE3MDRkMTc1ZjhlYmY2YWYzOTdkNjllMTEwYjk2YWZiMTdjN2EwMzI1OTMyOWU0ODI5YjBkMDNiYmM 3ODk2YjE1YjRhZGU1M2UxMzA4NThjYzM0ZDk2MjY5YWE4OTA0MWY0MDkxMzZjNzI0MmEzODg5NWM5ZDV iY2NhZDRmMzg5YWYxZDdhNGJkMTM5OGJkMDcyZGZmYTg5NjIzMzM5N2EifSwicHJpbmNpcGFsIjp7ImV tYWlsIjoiZm9vQG1vY2tteWlkLmNvbSJ9LCJpYXQiOjEzNzY1MzY0NjM1MTgsImV4cCI6MTM3NjU0MDA 2MzUxOCwiaXNzIjoibW9ja215aWQuY29tIn0.IeUR0_3ayAZkdNSXjF4aaCwSHnHa4X1lzrjX-qkNcPI bXx1hmQQPwg~eyJhbGciOiJEUzEyOCJ9.eyJleHAiOjEzNzY1MzY3MDc2MzUsImF1ZCI6Imh0dHA6Ly9 sb2NhbGhvc3QifQ.NJ8H1qZcWXbXfPJSdgB_mORHQ442ZkY0XYfdQsZZsIjooG7k7qWyVw
  88. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  89. gem install browserid-verifier

  90. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"])

  91. { status: “okay”, audience: “http://123done.org”, expires: 1344849682560, email: “francois@mozilla.com”, issuer:

    “login.persona.org” }
  92. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"]) if response["status"] == "okay"

    session[:email] = response["email"] end
  93. { status: “failed”, reason: “assertion has expired” }

  94. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"]) if response["status"] == "okay"

    session[:email] = response["email"] else session[:email] = nil end
  95. None
  96. None
  97. navigator.id.logout()

  98. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion},

    function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  99. None
  100. 1. load javascript library

  101. 1. load javascript library 2. setup login & logout callbacks

  102. 1. load javascript library 2. setup login & logout callbacks

    3. add login and logout buttons
  103. 1. load javascript library 2. setup login & logout callbacks

    3. add login and logout buttons 4. verify proof of ownership
  104. 1. load javascript library 2. setup login & logout callbacks

    3. add login and logout buttons 4. verify proof of ownership no API key needed
  105. Devise warden

  106. one simple request

  107. None
  108. building a new site: default to Persona

  109. working on an existing site/app: add support for Persona

  110. before

  111. after

  112. after navigator.id.request()

  113. None
  114. ALTER TABLE user DROP COLUMN password;

  115. To learn more about Persona: https://login.persona.org/ http://identity.mozilla.com/ https://developer.mozilla.org/docs/Persona/Why_Persona https://developer.mozilla.org/docs/Persona/Quick_Setup https://github.com/mozilla/browserid-cookbook

    https://developer.mozilla.org/docs/Persona/Libraries_and_plugins http://123done.org/ https://wiki.mozilla.org/Identity#Get_Involved @fmarier http://fmarier.org
  116. identity provider API https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537"

    }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  117. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html",

    "provisioning": "/browserid/provision.html" } identity provider API
  118. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html",

    "provisioning": "/browserid/provision.html" } identity provider API
  119. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html",

    "provisioning": "/browserid/provision.html" } identity provider API
  120. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html",

    "provisioning": "/browserid/provision.html" } identity provider API
  121. identity provider API 1. check for your /.well-known/browserid 2. try

    the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  122. identity provider API 1. check for your /.well-known/browserid 2. try

    the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  123. identity provider API 1. check for your /.well-known/browserid 2. try

    the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  124. identity provider API 1. check for your /.well-known/browserid 2. try

    the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  125. © 2013 François Marier <francois@mozilla.com> This work is licensed under

    a Creative Commons Attribution-ShareAlike 3.0 New Zealand License. Top 500 passwords: http://xato.net/passwords/more-top-worst-passwords/ Parchment: https://secure.flickr.com/photos/27613359@N03/6750396225/ Restaurant dinner: https://secure.flickr.com/photos/yourdon/3977084094/ Stop sign: https://secure.flickr.com/photos/artbystevejohnson/6673406227/ Photo credits: