0
You’re still using
passwords on your
site?

François Marier – @fmarier
problem #1:
passwords are hard to secure
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
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
se...
passwords are hard to secure

they are a liability
ALTER TABLE user
DROP COLUMN password;
problem #2:
passwords are hard to remember
pick an easy password
pick an easy password

use it everywhere
passwords are hard to remember

they need to be reset
control
email
account

=

control
all
accounts
“People want
a little dating
before marriage.”
Eric Vishria – Rockmelt
decentralised
myid.com/u/francois
privacy®
existing login systems
are not good enough
ideal web-wide identity system
ideal web-wide identity system
ideal web-wide identity system
ideal web-wide identity system
what if it were a standard
part of the web browser?
how does it work?
fmarier@gmail.com
why email addresses?
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
why email addresses?
already federated
people know their email
natural association between person & email
easy to have sep...
fmarier@gmail.com
demo #1:
http://www.voo.st/
http://bornthiswayfoundation.org
fmariertest@eyedee.me
Persona is already a
decentralised system
SMS with PIN codes
SMS with PIN codes
Jabber / XMPP
SMS with PIN codes
Jabber / XMPP
Yubikeys
SMS with PIN codes
Jabber / XMPP
Yubikeys
LDAP accounts
SMS with PIN codes
Jabber / XMPP
Yubikeys
LDAP accounts
Client certificates
SMS with PIN codes

{

Jabber / XMPP
Yubikeys
LDAP accounts
Client certificates

}

"public-key": {
"algorithm":
"RS",
"n"...
decentralisation is the answer, but it's not

a product adoption strategy
we can't wait for all browsers
to adopt Persona
navigator.id.*
we can't wait for all browsers
to adopt Persona

solution: a temporary
javascript shim
goal: trusted code
running in the browser
login.persona.org
localStorage
localStorage.setItem("key", serializedKey);
var serializedKey = localStorage.getItem("key");
storage tied to
login.persona.org
window.postMessage()
postMessage
localStorage
https://login.persona.org
Persona supports

all modern browsers

>= 8
we can't wait for all domains
to adopt Persona
we can't wait for all domains
to adopt Persona

solution: a temporary
centralised fallback
demo #2:
http://sloblog.io/
fmariertest@aol.com
Persona already works
with all email domains
identity bridging
demo #3:
http://www.reasonwell.com/
fmariertest@yahoo.com
Persona works everywhere
lessons learned
#1

user testing
is critical
#2

nobody wants
to be first
“how many users
does Persona have?”
700,000,000
#3

if a problem has
been around for a
while, it's probably
a hard one
see if you can solve
part of the problem
$ ssh francois@myserver.com
francois@myserver.com's password:
Persona is a simple
sign-in solution
for the web
how simple is it

for developers?
<script src=”https://login.persona.org/include.js”>
</script>
</body></html>
navigator.id.watch({
loggedInEmail: “francois@mozilla.com”,
onlogin: function (assertion) {
$.post('/login',
{assertion: a...
navigator.id.watch({
loggedInUser: “francois@mozilla.com”,
onlogin: function (assertion) {
$.post('/login',
{assertion: as...
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
navigator.id.request()
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
eyJhbGciOiJEUzEyOCJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IkRTIiwieSI6ImNhZDg2ZDg
yNWU0MjBkMGI4Njk5MjM4ZDM5ZTFjYjIyOGMyMTk1...
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');
$result = $verifier->verifyAsser...
{
status: “okay”,
audience: “http://123done.org”,
expires: 1344849682560,
email: “francois@mozilla.com”,
}

issuer: “login...
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');
$result = $verifier->verifyAsser...
{
status: “failed”,
}

reason: “assertion has expired”
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');
$result = $verifier->verifyAsser...
navigator.id.logout()
navigator.id.watch({
loggedInUser: null,
onlogin: function (assertion) {
$.post('/login',
{assertion: assertion},
function...
1. load javascript library
1. load javascript library
2. setup login & logout callbacks
1. load javascript library
2. setup login & logout callbacks
3. add login and logout buttons
1. load javascript library
2. setup login & logout callbacks
3. add login and logout buttons
4. verify proof of ownership
no
1. load javascript library API key
needed
2. setup login & logout callbacks
3. add login and logout buttons
4. verify p...
how simple is it

for domain owners?
https://eyedee.me/.well-known/browserid:
{
"public-key": {
"algorithm":"RS",
"n":"8606...",
"e":"65537"
},
"authentication...
https://eyedee.me/.well-known/browserid:
{
"public-key": {
"algorithm":"RS",
"n":"8606...",
"e":"65537"
},
"authentication...
https://eyedee.me/.well-known/browserid:
{
"public-key": {
"algorithm":"RS",
"n":"8606...",
"e":"65537"
},
"authentication...
https://eyedee.me/.well-known/browserid:
{
"public-key": {
"algorithm":"RS",
"n":"8606...",
"e":"65537"
},
"authentication...
https://eyedee.me/.well-known/browserid:
{
"public-key": {
"algorithm":"RS",
"n":"8606...",
"e":"65537"
},
"authentication...
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the prov...
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the prov...
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the prov...
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the prov...
one small request
building a new site:

default to Persona
working on an existing site/app:

add support for Persona
before
after
after

navigator.id.request()
ALTER TABLE user
DROP COLUMN password;
To learn more about Persona:
https://login.persona.org/
http://identity.mozilla.com/
https://developer.mozilla.org/docs/Pe...
Photo credits:
Laptop password: https://secure.flickr.com/photos/reidrac/4696900602/
Top 500 passwords: http://xato.net/pa...
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
You're still using passwords on your site?
Upcoming SlideShare
Loading in...5
×

You're still using passwords on your site?

241

Published on

A few people like to say that passwords are dead, but the reality is far from it. First of all, we can't get rid of passwords entirely, because the alternatives all suck: physical tokens are easy to lose and retina scans are pretty creepy. What we should focus on is eliminating site-specific passwords.

Mozilla Persona was introduced at OSDC last year, but a number of new things have been added to it since. But more importantly, it's still the best shot we have at a decentralized web-wide identity system that works for average users and doesn't violate their privacy.

So I'm back to show you what's new and to talk about what organizations can gain from adding native support on their domain. It's time to solve the password problem on the web.

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
241
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "You're still using passwords on your site?"

  1. 1. You’re still using passwords on your site? 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. why email addresses?
  29. 29. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  30. 30. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  31. 31. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  32. 32. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  33. 33. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  34. 34. why email addresses? already federated people know their email natural association between person & email easy to have separate identities most sites need a way to contact users no lock-in
  35. 35. fmarier@gmail.com
  36. 36. demo #1: http://www.voo.st/ http://bornthiswayfoundation.org fmariertest@eyedee.me
  37. 37. Persona is already a decentralised system
  38. 38. SMS with PIN codes
  39. 39. SMS with PIN codes Jabber / XMPP
  40. 40. SMS with PIN codes Jabber / XMPP Yubikeys
  41. 41. SMS with PIN codes Jabber / XMPP Yubikeys LDAP accounts
  42. 42. SMS with PIN codes Jabber / XMPP Yubikeys LDAP accounts Client certificates
  43. 43. SMS with PIN codes { Jabber / XMPP Yubikeys LDAP accounts Client certificates } "public-key": { "algorithm": "RS", "n":"685484565272...", "e":"65537" }, "encrypted-private-key": { "iv": "tmg7gztUQT...", "salt": "JMtGwlF5UWY", "ct": "8DdOjD1IA1..." }, "authentication": "...", "provisioning": "..." Password-wrapped secret key
  44. 44. decentralisation is the answer, but it's not a product adoption strategy
  45. 45. we can't wait for all browsers to adopt Persona
  46. 46. navigator.id.*
  47. 47. we can't wait for all browsers to adopt Persona solution: a temporary javascript shim
  48. 48. goal: trusted code running in the browser
  49. 49. login.persona.org
  50. 50. localStorage localStorage.setItem("key", serializedKey); var serializedKey = localStorage.getItem("key");
  51. 51. storage tied to login.persona.org
  52. 52. window.postMessage()
  53. 53. postMessage localStorage https://login.persona.org
  54. 54. Persona supports all modern browsers >= 8
  55. 55. we can't wait for all domains to adopt Persona
  56. 56. we can't wait for all domains to adopt Persona solution: a temporary centralised fallback
  57. 57. demo #2: http://sloblog.io/ fmariertest@aol.com
  58. 58. Persona already works with all email domains
  59. 59. identity bridging
  60. 60. demo #3: http://www.reasonwell.com/ fmariertest@yahoo.com
  61. 61. Persona works everywhere
  62. 62. lessons learned
  63. 63. #1 user testing is critical
  64. 64. #2 nobody wants to be first
  65. 65. “how many users does Persona have?”
  66. 66. 700,000,000
  67. 67. #3 if a problem has been around for a while, it's probably a hard one
  68. 68. see if you can solve part of the problem
  69. 69. $ ssh francois@myserver.com francois@myserver.com's password:
  70. 70. Persona is a simple sign-in solution for the web
  71. 71. how simple is it for developers?
  72. 72. <script src=”https://login.persona.org/include.js”> </script> </body></html>
  73. 73. navigator.id.watch({ loggedInEmail: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  74. 74. navigator.id.watch({ loggedInUser: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  75. 75. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  76. 76. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; } });
  77. 77. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  78. 78. navigator.id.request()
  79. 79. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; } });
  80. 80. 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
  81. 81. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  82. 82. require_once('Auth/BrowserID.php'); $verifier = new Auth_BrowserID('http://123done.org'); $result = $verifier->verifyAssertion($_POST['assertion']);
  83. 83. { status: “okay”, audience: “http://123done.org”, expires: 1344849682560, email: “francois@mozilla.com”, } issuer: “login.persona.org”
  84. 84. require_once('Auth/BrowserID.php'); $verifier = new Auth_BrowserID('http://123done.org'); $result = $verifier->verifyAssertion($_POST['assertion']); if ($result->status === 'okay') { echo "Hi " . $result->email; } else { echo "Error: " . $result->reason; }
  85. 85. { status: “failed”, } reason: “assertion has expired”
  86. 86. require_once('Auth/BrowserID.php'); $verifier = new Auth_BrowserID('http://123done.org'); $result = $verifier->verifyAssertion($_POST['assertion']); if ($result->status === 'okay') { echo "Hi " . $result->email; } else { echo "Error: " . $result->reason; }
  87. 87. navigator.id.logout()
  88. 88. navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; } });
  89. 89. 1. load javascript library
  90. 90. 1. load javascript library 2. setup login & logout callbacks
  91. 91. 1. load javascript library 2. setup login & logout callbacks 3. add login and logout buttons
  92. 92. 1. load javascript library 2. setup login & logout callbacks 3. add login and logout buttons 4. verify proof of ownership
  93. 93. no 1. load javascript library API key needed 2. setup login & logout callbacks 3. add login and logout buttons 4. verify proof of ownership
  94. 94. how simple is it for domain owners?
  95. 95. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  96. 96. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  97. 97. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  98. 98. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  99. 99. https://eyedee.me/.well-known/browserid: { "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html" }
  100. 100. 1. check for your /.well-known/browserid 2. try the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  101. 101. 1. check for your /.well-known/browserid 2. try the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  102. 102. 1. check for your /.well-known/browserid 2. try the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  103. 103. 1. check for your /.well-known/browserid 2. try the provisioning endpoint 3. show the authentication page 4. call the provisioning endpoint again
  104. 104. one small request
  105. 105. building a new site: default to Persona
  106. 106. working on an existing site/app: add support for Persona
  107. 107. before
  108. 108. after
  109. 109. after navigator.id.request()
  110. 110. ALTER TABLE user DROP COLUMN password;
  111. 111. 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 https://wiki.mozilla.org/Identity#Get_Involved @fmarier http://fmarier.org
  112. 112. Photo credits: Laptop password: https://secure.flickr.com/photos/reidrac/4696900602/ Top 500 passwords: http://xato.net/passwords/more-top-worst-passwords/ Restaurant dinner: https://secure.flickr.com/photos/yourdon/3977084094/ Parchment: https://secure.flickr.com/photos/27613359@N03/6750396225/ Yubikey: https://secure.flickr.com/photos/knk/3379897261/ 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.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×