fix issues in example, improve README

This commit is contained in:
Tobias Oberstein
2014-03-11 12:22:10 +01:00
parent 8bd6976e8a
commit ec66afdc04
3 changed files with 57 additions and 14 deletions

View File

@@ -1,9 +1,15 @@
WebSocket Authentication with Mozilla Persona WebSocket Authentication with Mozilla Persona
============================================= =============================================
This example shows how to authenticate WebSocket connections using [Mozilla Persona](http://www.mozilla.org/en-US/persona/) and HTTP Cookies. This example shows how to authenticate WebSocket connections using [Mozilla Persona](http://www.mozilla.org/en-US/persona/) and HTTP Cookies. The example works with purely static Web pages and WebSocket only.
This example works with purely static Web pages and WebSocket only. Tested with:
* Firefox 27
* Chrome 33
* IE11
Note: On IE11, using `localhost` as URL [does NOT work](https://groups.google.com/d/msg/mozilla.dev.identity/keEkVpvfLA8/2WIu7Q1mW10J). You must use `127.0.0.1` instead.
References: References:
@@ -22,3 +28,20 @@ and open
http://localhost:8080/ http://localhost:8080/
in your browser. in your browser.
Here is the log output produced (on server) for a successful login:
oberstet@COREI7 ~/scm/tavendo/autobahn/AutobahnPython/examples/twisted/websocket/auth_persona (master)
$ python server.py
2014-03-11 12:20:05+0100 [-] Log opened.
2014-03-11 12:20:05+0100 [-] Running Autobahn|Python 0.8.4-3
2014-03-11 12:20:05+0100 [-] Site starting on 8080
2014-03-11 12:20:05+0100 [-] Starting factory <twisted.web.server.Site instance at 0x038113C8>
2014-03-11 12:20:23+0100 [HTTPChannel,1,127.0.0.1] Setting new cookie: 82vrA1drjZ_9lcBv
2014-03-11 12:20:36+0100 [HTTPChannel,1,127.0.0.1] Starting factory <HTTPClientFactory: https://verifier.login.persona.o
rg/verify>
2014-03-11 12:20:36+0100 [HTTPChannel,1,127.0.0.1] Authentication request sent.
2014-03-11 12:20:37+0100 [HTTPPageGetter (TLSMemoryBIOProtocol),client] Authenticated user tobias.oberstein@gmail.com
2014-03-11 12:20:37+0100 [HTTPPageGetter (TLSMemoryBIOProtocol),client] Stopping factory <HTTPClientFactory: https://verifier.login.persona.org/verify>
...

View File

@@ -15,6 +15,17 @@
var currentUser = null; var currentUser = null;
var sock = null; var sock = null;
var wsuri;
var persona_audience = null;
if (window.location.protocol === "file:") {
wsuri = "ws://127.0.0.1:8080/ws";
persona_audience = "127.0.0.1";
} else {
wsuri = "ws://" + window.location.hostname + ":8080/ws";
persona_audience = window.location.hostname;
}
var signinLink = document.getElementById('signin'); var signinLink = document.getElementById('signin');
signinLink.onclick = function() { signinLink.onclick = function() {
navigator.id.request(); navigator.id.request();
@@ -37,7 +48,7 @@
// 1. Send the assertion to your backend for verification and to create a session. // 1. Send the assertion to your backend for verification and to create a session.
// 2. Update your UI. // 2. Update your UI.
if (sock) { if (sock) {
sock.send(JSON.stringify({cmd: 'AUTHENTICATE', assertion: assertion})) sock.send(JSON.stringify({cmd: 'AUTHENTICATE', audience: persona_audience, assertion: assertion}))
} }
}, },
onlogout: function() { onlogout: function() {
@@ -52,13 +63,6 @@
}); });
} }
var wsuri;
if (window.location.protocol === "file:") {
wsuri = "ws://127.0.0.1:8080/ws";
} else {
wsuri = "ws://" + window.location.hostname + ":8080/ws";
}
if ("WebSocket" in window) { if ("WebSocket" in window) {
sock = new WebSocket(wsuri); sock = new WebSocket(wsuri);
} else if ("MozWebSocket" in window) { } else if ("MozWebSocket" in window) {
@@ -78,7 +82,9 @@
} }
sock.onmessage = function (e) { sock.onmessage = function (e) {
msg = JSON.parse(e.data); msg = JSON.parse(e.data);
if (msg.cmd === 'AUTHENTICATED') { if (msg.cmd === 'AUTHENTICATED') {
userLabel.innerHTML = 'Authenticated as ' + msg.email; userLabel.innerHTML = 'Authenticated as ' + msg.email;
@@ -96,6 +102,14 @@
watchPersona(); watchPersona();
} else if (msg.cmd === 'AUTHENTICATION_FAILED') {
userLabel.innerHTML = 'Authentication failed: ' + msg.reason;
signinLink.disabled = false;
signoutLink.disabled = true;
watchPersona();
} else if (msg.cmd === 'LOGGED_OUT') { } else if (msg.cmd === 'LOGGED_OUT') {
window.location.reload(); window.location.reload();

View File

@@ -26,6 +26,7 @@ from twisted.python import log
from twisted.web.server import Site from twisted.web.server import Site
from twisted.web.static import File from twisted.web.static import File
import autobahn
from autobahn.util import newid, utcnow from autobahn.util import newid, utcnow
from autobahn.websocket import http from autobahn.websocket import http
@@ -135,6 +136,7 @@ class PersonaServerProtocol(WebSocketServerProtocol):
## The client did it's Mozilla Persona authentication thing ## The client did it's Mozilla Persona authentication thing
## and now wants to verify the authentication and login. ## and now wants to verify the authentication and login.
assertion = msg.get('assertion') assertion = msg.get('assertion')
audience = msg.get('audience');
## To verify the authentication, we need to send a HTTP/POST ## To verify the authentication, we need to send a HTTP/POST
## to Mozilla Persona. When successful, Persona will send us ## to Mozilla Persona. When successful, Persona will send us
@@ -149,7 +151,7 @@ class PersonaServerProtocol(WebSocketServerProtocol):
# } # }
headers = {'Content-Type': 'application/x-www-form-urlencoded'} headers = {'Content-Type': 'application/x-www-form-urlencoded'}
body = urllib.urlencode({'audience': 'http://192.168.1.130:8080/', 'assertion': assertion}) body = urllib.urlencode({'audience': audience, 'assertion': assertion})
from twisted.web.client import getPage from twisted.web.client import getPage
d = getPage(url = "https://verifier.login.persona.org/verify", d = getPage(url = "https://verifier.login.persona.org/verify",
@@ -175,13 +177,13 @@ class PersonaServerProtocol(WebSocketServerProtocol):
log.msg("Authenticated user {}".format(res['email'])) log.msg("Authenticated user {}".format(res['email']))
else: else:
log.msg("Authentication failed!") log.msg("Authentication failed: {}".format(res.get('reason')))
self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED'})) self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED', 'reason': res.get('reason')}))
self.sendClose() self.sendClose()
def error(err): def error(err):
log.msg("Authentication request failed: {}".format(err.value)) log.msg("Authentication request failed: {}".format(err.value))
self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED'})) self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED', 'reason': str(err.value)}))
self.sendClose() self.sendClose()
d.addCallbacks(done, error) d.addCallbacks(done, error)
@@ -221,6 +223,8 @@ if __name__ == '__main__':
log.startLogging(sys.stdout) log.startLogging(sys.stdout)
print("Running Autobahn|Python {}".format(autobahn.version))
## our WebSocket server factory ## our WebSocket server factory
factory = PersonaServerFactory("ws://localhost:8080") factory = PersonaServerFactory("ws://localhost:8080")
@@ -233,6 +237,8 @@ if __name__ == '__main__':
## run both under one Twisted Web Site ## run both under one Twisted Web Site
site = Site(root) site = Site(root)
site.log = lambda _: None # disable any logging
reactor.listenTCP(8080, site) reactor.listenTCP(8080, site)
reactor.run() reactor.run()