parent
17d4cb3828
commit
1e5746bb2b
7 changed files with 0 additions and 199 deletions
|
|
@ -1,3 +0,0 @@
|
|||
A simple example for integrating [Persona](https://login.persona.org/) into a
|
||||
Flask application. In addition to Flask, it requires the
|
||||
[requests](www.python-requests.org/) library.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
from flask import Flask, render_template, session, request, 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 = resp.json()
|
||||
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'
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
$(function() {
|
||||
/* convert the links into clickable buttons that go to the
|
||||
persona service */
|
||||
$('a.signin').on('click', function() {
|
||||
navigator.id.request({
|
||||
siteName: 'Flask Persona Example'
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
|
|
@ -1,39 +0,0 @@
|
|||
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;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{% 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 %}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>{% block title %}{% endblock %} | Flask Persona Example</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…
Add table
Add a link
Reference in a new issue