Permalink
Browse files

Added Persona example

  • Loading branch information...
1 parent e17024e commit 5f648a8eb801e4ee6038a87cec11b416e0763a61 @mitsuhiko mitsuhiko committed Jun 9, 2013
@@ -0,0 +1,59 @@
+from flask import Flask, render_template, session, request, json, abort, g
+
+import requests
+
+
+app = Flask(__name__)
+app.config.update(
+ DEBUG=True,
+ SECRET_KEY='my development key',
+ PERSONA_JS='https://login.persona.org/include.js',
+ PERSONA_VERIFIER='https://verifier.login.persona.org/verify',
+)
+app.config.from_envvar('PERSONA_SETTINGS', silent=True)
+
+
+@app.before_request
+def get_current_user():
+ g.user = None
+ email = session.get('email')
+ if email is not None:
+ g.user = email
+
+
+@app.route('/')
+def index():
+ """Just a generic index page to show."""
+ return render_template('index.html')
+
+
+@app.route('/_auth/login', methods=['GET', 'POST'])
+def login_handler():
+ """This is used by the persona.js file to kick off the
+ verification securely from the server side. If all is okay
+ the email address is remembered on the server.
+ """
+ resp = requests.post(app.config['PERSONA_VERIFIER'], data={
+ 'assertion': request.form['assertion'],
+ 'audience': request.host_url,
+ }, verify=True)
+ if resp.ok:
+ verification_data = json.loads(resp.content)
+ if verification_data['status'] == 'okay':
+ session['email'] = verification_data['email']
+ return 'OK'
+
+ abort(400)
+
+
+@app.route('/_auth/logout', methods=['POST'])
+def logout_handler():
+ """This is what persona.js will call to sign the user
+ out again.
+ """
+ session.clear()
+ return 'OK'
+
+
+if __name__ == '__main__':
+ app.run()
@@ -0,0 +1,50 @@
+$(function() {
+ /* convert the links into clickable buttons that go to the
+ persona service */
+ $('a.signin').on('click', function() {
+ navigator.id.request();
+ return false;
+ });
+
+ $('a.signout').on('click', function() {
+ navigator.id.logout();
+ return false;
+ });
+
+ /* watch persona state changes */
+ navigator.id.watch({
+ loggedInUser: $CURRENT_USER,
+ onlogin: function(assertion) {
+ /* because the login needs to verify the provided assertion
+ with the persona service which requires an HTTP request,
+ this could take a bit. To not confuse the user we show
+ a progress box */
+ var box = $('<div class=signinprogress></div>')
+ .hide()
+ .text('Please wait ...')
+ .appendTo('body')
+ .fadeIn('fast');
+ $.ajax({
+ type: 'POST',
+ url: $URL_ROOT + '_auth/login',
+ data: {assertion: assertion},
+ success: function(res, status, xhr) { window.location.reload(); },
+ error: function(xhr, status, err) {
+ box.remove();
+ navigator.id.logout();
+ alert('Login failure: ' + err);
+ }
+ });
+ },
+ onlogout: function() {
+ $.ajax({
+ type: 'POST',
+ url: $URL_ROOT + '_auth/logout',
+ success: function(res, status, xhr) { window.location.reload(); },
+ error: function(xhr, status, err) {
+ alert('Logout failure: ' + err);
+ }
+ });
+ }
+ });
+});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,39 @@
+html {
+ background: #eee;
+}
+
+body {
+ font-family: 'Verdana', sans-serif;
+ font-size: 15px;
+ margin: 30px auto;
+ width: 720px;
+ background: white;
+ padding: 30px;
+}
+
+h1 {
+ margin: 0;
+}
+
+h1, h2, a {
+ color: #d00;
+}
+
+div.authbar {
+ background: #eee;
+ padding: 0 15px;
+ margin: 10px -15px;
+ line-height: 25px;
+ height: 25px;
+ vertical-align: middle;
+}
+
+div.signinprogress {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(255, 255, 255, 0.8) url(spinner.png) center center no-repeat;
+ font-size: 0;
+}
@@ -0,0 +1,23 @@
+{% extends "layout.html" %}
+{% block title %}Welcome{% endblock %}
+{% block body %}
+ <h2>Welcome</h2>
+ <p>
+ This is a small example application that shows how to integrate
+ Mozilla's persona signin service into a Flask application.
+ <p>
+ The advantage of persona over your own login system is that the
+ password is managed outside of your application and you get
+ a verified mail address as primary identifier for your user.
+ <p>
+ In this example nothing is actually stored on the server, it
+ just takes over the email address from the persona verifier
+ and stores it in a session.
+ {% if g.user %}
+ <p>
+ You are now logged in as <strong>{{ g.user }}</strong>
+ {% else %}
+ <p>
+ To sign in click the sign in button above.
+ {% endif %}
+{% endblock %}
@@ -0,0 +1,27 @@
+<!doctype html>
+<title>{% block title %}{% endblock %} | My Blog</title>
+<meta http-equiv="X-UA-Compatible" content="IE=Edge">
+<script src="{{ config.PERSONA_JS }}"></script>
+<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
+<script>
+ /* the url root is useful for doing HTTP requests */
+ var $URL_ROOT = {{ request.url_root|tojson }};
+
+ /* we store the current user here so that the persona
+ javascript support knows about the current user */
+ var $CURRENT_USER = {{ g.user|tojson }};
+</script>
+<script src="{{ url_for('static', filename='persona.js') }}"></script>
+<link rel=stylesheet href="{{ url_for('static', filename='style.css') }}">
+<header>
+ <h1>Mozilla Persona Example</h1>
+ <div class=authbar>
+ {% if g.user %}
+ Signed in as <em>{{ g.user }}</em>
+ (<a href="#" class=signout>Sign out</a>)
+ {% else %}
+ Not signed in. <a href="#" class=signin>Sign in</a>
+ {% endif %}
+ </div>
+</header>
+{% block body %}{% endblock %}

0 comments on commit 5f648a8

Please sign in to comment.