#!/usr/bin/env python # -*- coding: utf-8 -*- """ BrowserID Authentication for web2py developed by Madhukar R Pai (Copyright 2012) Email License : LGPL thanks and credits to the web2py community This custom authenticator allows web2py to authenticate using browserid (https://login.persona.org/) BrowserID is a project by Mozilla Labs (http://mozillalabs.com/) to Know how browserid works please visit http://identity.mozilla.com/post/7616727542/introducing-browserid-a-better-way-to-sign-in bottom line BrowserID provides a free, secure, de-centralized, easy to use(for users and developers) login solution. You can use any email id as your login id. Browserid just verifys the email id and lets you login with that id. credits for the doPost jquery function - itsadok (http://stackoverflow.com/users/7581/itsadok) """ import time from gluon import * from gluon.storage import Storage from gluon.tools import fetch import json class BrowserID(object): """ from gluon.contrib.login_methods.browserid_account import BrowserID auth.settings.login_form = BrowserID(request, audience = "http://127.0.0.1:8000" assertion_post_url = "http://127.0.0.1:8000/%s/default/user/login" % request.application) """ def __init__(self, request, audience="", assertion_post_url="", prompt="BrowserID Login", issuer="login.persona.org", verify_url="https://login.persona.org/verify", browserid_js="https://login.persona.org/include.js", browserid_button="https://login.persona.org/i/sign_in_red.png", crypto_js="https://crypto-js.googlecode.com/files/2.2.0-crypto-md5.js", on_login_failure=None, ): self.request = request self.audience = audience self.assertion_post_url = assertion_post_url self.prompt = prompt self.issuer = issuer self.verify_url = verify_url self.browserid_js = browserid_js self.browserid_button = browserid_button self.crypto_js = crypto_js self.on_login_failure = on_login_failure self.asertion_js = """ (function($){$.extend({doPost:function(url,params){var $form=$("
").attr("action",url); $.each(params,function(name,value){$("").attr("name",name).attr("value",value).appendTo($form)}); $form.appendTo("body");$form.submit()}})})(jQuery); function gotVerifiedEmail(assertion){if(assertion !== null){$.doPost('%s',{'assertion':assertion});}}""" % self.assertion_post_url def get_user(self): request = self.request if request.vars.assertion: audience = self.audience issuer = self.issuer assertion = XML(request.vars.assertion, sanitize=True) verify_data = {'assertion': assertion, 'audience': audience} auth_info_json = fetch(self.verify_url, data=verify_data) j = json.loads(auth_info_json) epoch_time = int(time.time() * 1000) # we need 13 digit epoch time if j["status"] == "okay" and j["audience"] == audience and j['issuer'].endswith(issuer) and j['expires'] >= epoch_time: return dict(email=j['email']) elif self.on_login_failure: #print "status: ", j["status"]=="okay", j["status"] #print "audience:", j["audience"]==audience, j["audience"], audience #print "issuer: ", j["issuer"]==issuer, j["issuer"], issuer #print "expires: ", j["expires"] >= epoch_time, j["expires"], epoch_time redirect(self.on_login_failure) else: redirect('https://login.persona.org') return None def login_form(self): request = self.request onclick = "javascript:navigator.id.getVerifiedEmail(gotVerifiedEmail) ; return false" form = DIV(SCRIPT(_src=self.browserid_js, _type="text/javascript"), SCRIPT(_src=self.crypto_js, _type="text/javascript"), A(IMG(_src=self.browserid_button, _alt=self.prompt), _href="#", _onclick=onclick, _class="browserid", _title="Login With BrowserID"), SCRIPT(self.asertion_js)) return form