Browse Source

Added Persona example

pull/764/head
Armin Ronacher 11 years ago
parent
commit
5f648a8eb8
  1. 59
      examples/persona/persona.py
  2. 50
      examples/persona/static/persona.js
  3. BIN
      examples/persona/static/spinner.png
  4. 39
      examples/persona/static/style.css
  5. 23
      examples/persona/templates/index.html
  6. 27
      examples/persona/templates/layout.html

59
examples/persona/persona.py

@ -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()

50
examples/persona/static/persona.js

@ -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);
}
});
}
});
});

BIN
examples/persona/static/spinner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

39
examples/persona/static/style.css

@ -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;
}

23
examples/persona/templates/index.html

@ -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 %}

27
examples/persona/templates/layout.html

@ -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 %}
Loading…
Cancel
Save