Easy logins for Ruby web applications

715 views

Published on

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.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
715
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Easy logins for Ruby web applications

  1. 1. Easy logins for Ruby web applications François Marier – @fmarier
  2. 2. problem #1: passwords are hard to secure
  3. 3. bcrypt / scrypt / pbkdf2 per-user salt site secret password & lockout policies secure recovery
  4. 4. bcrypt / scrypt / pbkdf2 per-user salt site secret password & lockout policies secure recovery
  5. 5. bcrypt / scrypt / pbkdf2 per-user salt site secret password & lockout policies secure recovery
  6. 6. bcrypt / scrypt / pbkdf2 per-user salt site secret password & lockout policies secure recovery
  7. 7. bcrypt / scrypt / pbkdf2 per-user salt site secret password & lockout policies secure recovery
  8. 8. bcrypt / scrypt / pbkdf2 3 1 0 2 per-user salt d r o site secret w s s s a & lockoutne p password li policies e id u secure recovery g
  9. 9. passwords are hard to secure they are a liability
  10. 10. ALTER TABLE user DROP COLUMN password;
  11. 11. problem #2: passwords are hard to remember
  12. 12. pick an easy password
  13. 13. pick an easy password use it everywhere
  14. 14. passwords are hard to remember they need to be reset
  15. 15. control email account = control all accounts
  16. 16. “People want a little dating before marriage.” Eric Vishria – Rockmelt
  17. 17. decentralised
  18. 18. myid.com/u/francois
  19. 19. privacy®
  20. 20. existing login systems are not good enough
  21. 21. ideal web-wide identity system
  22. 22. ideal web-wide identity system
  23. 23. ideal web-wide identity system
  24. 24. ideal web-wide identity system
  25. 25. what if it were a standard part of the web browser?
  26. 26. how does it work?
  27. 27. fmarier@gmail.com
  28. 28. fmarier@gmail.com
  29. 29. getting a proof of email ownership
  30. 30. authenticate?
  31. 31. authenticate? public key
  32. 32. authenticate? public key signed public key
  33. 33. you have a signed statement from your provider that you own your email address
  34. 34. logging into a 3rd party site
  35. 35. assertion wikipedia.org Valid for: 2 minutes
  36. 36. assertion wikipedia.org Valid for: 2 minutes check audience
  37. 37. assertion wikipedia.org Valid for: 2 minutes check audience check expiry
  38. 38. assertion wikipedia.org Valid for: 2 minutes check audience check expiry check signature
  39. 39. assertion public key wikipedia.org Valid for: 2 minutes
  40. 40. assertion wikipedia.org Valid for: 2 minutes
  41. 41. assertion session cookie
  42. 42. demo #1: http://www.voo.st/ http://www.debuggex.com fmariertest@eyedee.me
  43. 43. Persona is already a decentralised system
  44. 44. decentralisation is the answer, but it's not a product adoption strategy
  45. 45. we can't wait for all domains to adopt Persona
  46. 46. we can't wait for all domains to adopt Persona solution: a temporary centralised fallback
  47. 47. demo #2: http://sloblog.io/ fmariertest@aol.com
  48. 48. Persona already works with all email domains
  49. 49. identity bridging
  50. 50. demo #3: http://www.reasonwell.com/ fmariertest@yahoo.com
  51. 51. Persona supports all modern browsers >= 8
  52. 52. Persona is decentralised, simple and cross-browser
  53. 53. it's simple for users, but is it also simple for developers?
  54. 54. <script src=”https://login.persona.org/include.js”> </script> </body></html>
  55. 55. navigator.id.watch({ loggedInEmail: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  56. 56. navigator.id.watch({ loggedInUser: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  57. 57. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  58. 58. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  59. 59. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  60. 60. navigator.id.request()
  61. 61. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  62. 62. 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
  63. 63. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  64. 64. gem install browserid-verifier
  65. 65. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"])
  66. 66. { status: “okay”, audience: “http://123done.org”, expires: 1344849682560, email: “francois@mozilla.com”, } issuer: “login.persona.org”
  67. 67. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"]) if response["status"] == "okay" session[:email] = response["email"] end
  68. 68. { status: “failed”, } reason: “assertion has expired”
  69. 69. require 'browserid/verifier' response = verify("http://123done.org", params["assertion"]) if response["status"] == "okay" session[:email] = response["email"] else session[:email] = nil end
  70. 70. navigator.id.logout()
  71. 71. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  72. 72. 1. load javascript library
  73. 73. 1. load javascript library 2. setup login & logout callbacks
  74. 74. 1. load javascript library 2. setup login & logout callbacks 3. add login and logout buttons
  75. 75. 1. load javascript library 2. setup login & logout callbacks 3. add login and logout buttons 4. verify proof of ownership
  76. 76. no 1. load javascript library API key needed 2. setup login & logout callbacks 3. add login and logout buttons 4. verify proof of ownership
  77. 77. Devise warden
  78. 78. one simple request
  79. 79. building a new site: default to Persona
  80. 80. working on an existing site/app: add support for Persona
  81. 81. before
  82. 82. after
  83. 83. after navigator.id.request()
  84. 84. ALTER TABLE user DROP COLUMN password;
  85. 85. 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
  86. 86. 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" }
  87. 87. 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" }
  88. 88. 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" }
  89. 89. 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" }
  90. 90. 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" }
  91. 91. 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
  92. 92. 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
  93. 93. 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
  94. 94. 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
  95. 95. Photo credits: 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/ © 2013 François Marier <francois@mozilla.com> This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 New Zealand License.

×