diff --git a/examples/twisted/websocket/auth_persona/README.md b/examples/twisted/websocket/auth_persona/README.md index 6f7a9074..bb3737d7 100644 --- a/examples/twisted/websocket/auth_persona/README.md +++ b/examples/twisted/websocket/auth_persona/README.md @@ -1,9 +1,15 @@ 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: @@ -22,3 +28,20 @@ and open http://localhost:8080/ 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 + 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 + 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 + ... + diff --git a/examples/twisted/websocket/auth_persona/index.html b/examples/twisted/websocket/auth_persona/index.html index 497e342a..47fd62c6 100644 --- a/examples/twisted/websocket/auth_persona/index.html +++ b/examples/twisted/websocket/auth_persona/index.html @@ -15,6 +15,17 @@ var currentUser = 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'); signinLink.onclick = function() { navigator.id.request(); @@ -37,7 +48,7 @@ // 1. Send the assertion to your backend for verification and to create a session. // 2. Update your UI. if (sock) { - sock.send(JSON.stringify({cmd: 'AUTHENTICATE', assertion: assertion})) + sock.send(JSON.stringify({cmd: 'AUTHENTICATE', audience: persona_audience, assertion: assertion})) } }, 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) { sock = new WebSocket(wsuri); } else if ("MozWebSocket" in window) { @@ -78,7 +82,9 @@ } sock.onmessage = function (e) { + msg = JSON.parse(e.data); + if (msg.cmd === 'AUTHENTICATED') { userLabel.innerHTML = 'Authenticated as ' + msg.email; @@ -96,6 +102,14 @@ 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') { window.location.reload(); diff --git a/examples/twisted/websocket/auth_persona/server.py b/examples/twisted/websocket/auth_persona/server.py index 0c85a0a3..d4d2efbe 100644 --- a/examples/twisted/websocket/auth_persona/server.py +++ b/examples/twisted/websocket/auth_persona/server.py @@ -26,6 +26,7 @@ from twisted.python import log from twisted.web.server import Site from twisted.web.static import File +import autobahn from autobahn.util import newid, utcnow from autobahn.websocket import http @@ -135,6 +136,7 @@ class PersonaServerProtocol(WebSocketServerProtocol): ## The client did it's Mozilla Persona authentication thing ## and now wants to verify the authentication and login. assertion = msg.get('assertion') + audience = msg.get('audience'); ## To verify the authentication, we need to send a HTTP/POST ## to Mozilla Persona. When successful, Persona will send us @@ -149,7 +151,7 @@ class PersonaServerProtocol(WebSocketServerProtocol): # } 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 d = getPage(url = "https://verifier.login.persona.org/verify", @@ -175,13 +177,13 @@ class PersonaServerProtocol(WebSocketServerProtocol): log.msg("Authenticated user {}".format(res['email'])) else: - log.msg("Authentication failed!") - self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED'})) + log.msg("Authentication failed: {}".format(res.get('reason'))) + self.sendMessage(json.dumps({'cmd': 'AUTHENTICATION_FAILED', 'reason': res.get('reason')})) self.sendClose() def error(err): 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() d.addCallbacks(done, error) @@ -221,6 +223,8 @@ if __name__ == '__main__': log.startLogging(sys.stdout) + print("Running Autobahn|Python {}".format(autobahn.version)) + ## our WebSocket server factory factory = PersonaServerFactory("ws://localhost:8080") @@ -233,6 +237,8 @@ if __name__ == '__main__': ## run both under one Twisted Web Site site = Site(root) + site.log = lambda _: None # disable any logging + reactor.listenTCP(8080, site) reactor.run()