Building Persona: federated and privacy-sensitive identity for the Web (Open Source Days 2013)
Post on 08-May-2015
225 Views
Preview:
DESCRIPTION
Transcript
François Marier – @fmarier
B u i l d i n g P e r s o n afederated & privacy-sensitive identity for the web
solving thepassword problem
on the web
users: reduce number of passwords
users: reduce number of passwords
developers: reduce implementation costs
Username:francois
Password:****************
X
Sign in
security
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt
per-user salt
site secret
password & lockout policies
secure recovery
20132013
passwordpassword
guidelines
guidelines
ALTER TABLE userDROP COLUMN password;
existing solutions
client certificates
“social” authentication
“People want a littledating before marriage.”
Eric Vishria – Rockmelt
so...
storing passwords is hard
so...
storing passwords is hard
no suitable alternatives
decentralized
privacy-sensitivedecentralized
privacy-sensitive
simple
decentralized
privacy-sensitive
simpleopen source
decentralized
in your browser
how does it work?
<digital signatures 101>
private public
public
My name isFrançois Marierand my email istoo long to fiton one line.
My name isFrançois Marierand my email istoo long to fiton one line.private
My name isFrançois Marierand my email istoo long to fiton one line. public
sign verify
</digital signatures 101>
getting a proof of email ownership
authenticate?
authenticate?
public key
authenticate?
public key
signed public key
you have a signed statement from yourprovider that you own your email address
logging into a 3rd party site
Valid for: 2 minutes
linux.conf.au
assertion
Valid for: 2 minutes
linux.conf.au
check audience
assertion
Valid for: 2 minutes
linux.conf.au
check audiencecheck expiry
assertion
Valid for: 2 minutes
linux.conf.au
check audiencecheck expirycheck signature
assertion
assertion
Valid for: 2 minutes
linux.conf.au
public key
assertion
Valid for: 2 minutes
linux.conf.au
assertion
session cookie
achievingthat vision
email providers
browser vendors
email providers
fmarier@gmail.com
fmarier@gmail.com
fallback identity provider
persona.org account
support for all email providers
browser vendors
navigator.id.*
js
support for allmodern browsers
>= 8
support for allmodern browsers
>= 8
live demo
using it on your site
no need to take notesthese slides will be online )(
<script src=”https://login.persona.org/include.js”></script></body></html>
navigator.id.watch({ loggedInEmail: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: “francois@mozilla.com”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.request()
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; }});
def verify_assertion(assertion):
page = requests.post( 'https://verifier.login.persona.org/verify', Data={ "assertion": assertion, "audience": 'http://123done.org'})
data = page.json return data.status == 'okay'
def verify_assertion(assertion):
page = requests.post( 'https://verifier.login.persona.org/verify', Data={ "assertion": assertion, "audience": 'http://123done.org'})
data = page.json return data.status == 'okay'
{ status: “okay”,
audience: “http://123done.org”,
expires: 1344849682560,
email: “francois@mozilla.com”,
issuer: “login.persona.org”}
{ status: “failed”,
reason: “assertion has expired”}
navigator.id.logout()
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; }});
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
<?php
if (!empty($_POST)) { $result = verify_assertion($_POST['assertion']); if ($result->status === 'okay') { print_header(); echo "<p>Logged in as: " . $result->email . "</p>"; echo '<p><a href="javascript:do_logout()">Logout</a></p>'; print_backLink(); print_footer($result->email); } else { print_header(); echo "<p>Error: " . $result->reason . "</p>"; print_backLink(); print_footer(); }} elseif (!empty($_GET['logout'])) { print_header(); echo "<p>You have logged out.</p>"; print_backLink(); print_footer();} else { print_header(); echo "<p><a href=\"javascript:do_login()\">Login</a></p>"; print_footer();}
function print_header() { echo <<<EOF<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><form id="login-form" method="POST"><input id="assertion-field" type="hidden" name="assertion" value=""></form>EOF;}
function print_backLink() { echo "<p><a href=\"persona.php\">Back to login page</a></p>";}
function print_footer($email = 'null') { if ($email !== 'null') { $email = "'$email'"; } echo <<<EOF<script src="http://127.0.0.1:10002/include.orig.js"></script><script>
function do_login() { navigator.id.request();}function do_logout() { navigator.id.logout();}
navigator.id.watch({ loggedInUser: $email, onlogin: function (assertion) { alert("onlogin: $email"); var assertion_field = document.getElementById("assertion-field"); assertion_field.value = assertion; var login_form = document.getElementById("login-form"); login_form.submit(); }, onlogout: function () { alert("onlogout: $email"); window.location = '?logout=1'; }});</script></body></html>EOF;}
function verify_assertion($assertion) { $audience = ($_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT']; $postdata = 'assertion=' . urlencode($assertion) . '&audience=' . urlencode($audience);
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://verifier.login.persona.org/verify"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $json = curl_exec($ch); curl_close($ch);
$res = json_decode($json); $res->status = 'okay'; $res->email = 'francois@mozilla.com'; return $res;}?>
wanna help ussolve the
password problem?
add Persona toyour project/site
tell us about yourexperience
email one siteasking for it
add Persona toyour project/site
tell us about yourexperience
email one siteasking for it
add Persona toyour project/site
tell us about yourexperience
email one siteasking for it
To learn more about Persona:
https://login.persona.org/http://identity.mozilla.com/
https://developer.mozilla.org/docs/Persona/Why_Personahttps://developer.mozilla.org/docs/Persona/Quick_Setup
https://github.com/mozilla/browserid-cookbookhttps://developer.mozilla.org/docs/Persona/Libraries_and_plugins
http://123done.org/https://wiki.mozilla.org/Identity#Get_Involved
@fmarier http://fmarier.org
Who's using Persona?
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"}
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
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
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
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
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
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
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
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
© 2013 François Marier <francois@mozilla.com>This work is licensed under aCreative 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/
Elephant in room: https://secure.flickr.com/photos/bitboy/246805948/
Cookie on tray: https://secure.flickr.com/photos/jamisonjudd/4810986199/
Uncle Sam: https://secure.flickr.com/photos/donkeyhotey/5666065982/
Danish passport: https://en.wikipedia.org/wiki/File:DK_Passport_Cover.jpg
Restaurant dinner: https://secure.flickr.com/photos/yourdon/3977084094/
Photo credits:
top related