Quickstart¶
Using the flask decorator¶
import flask
from flask import Flask
from ucam_webauth.raven.flask_glue import AuthDecorator
# Werkzeug deduces the hostname from the 'Host' or
# 'X-Forwarded-Host' headers, so we need a whitelist
class R(flask.Request):
trusted_hosts = {'your-domain.com', 'www.your-domain.com'}
app = Flask(__name__)
app.request_class = R
app.secret_key = "a secret key"
auth_decorator = AuthDecorator(desc="My website")
@app.route("/some_url")
@auth_decorator
def my_view():
return "You are " + auth_decorator.principal
if __name__ == '__main__':
app.run()
Requiring all flask requests be authenticated¶
import flask
from flask import Flask
from ucam_webauth.raven.flask_glue import AuthDecorator
# Werkzeug deduces the hostname from the 'Host' or
# 'X-Forwarded-Host' headers, so we need a whitelist
class R(flask.Request):
trusted_hosts = {'your-domain.com', 'www.your-domain.com'}
app = Flask(__name__)
app.request_class = R
app.secret_key = "a secret key"
auth_decorator = AuthDecorator()
app.before_request(auth_decorator.before_request)
@app.route("/")
def home():
return "You are " + auth_decorator.principal
if __name__ == '__main__':
app.run()
Manual request building and response parsing¶
To create requests:
>>> from ucam_webauth.raven import Request, Response
>>> r = Request(url="http://host/response/path", desc="My website")
>>> print str(r)
https://raven.cam.ac.uk/auth/authenticate.html?url=http%3A%2F%2Fhost%2Fresponse%2Fpath&ver=3&desc=My+website
And parse responses:
>>> r = Response("3!200!!20130705T150000Z!1373000000-00000-00!"
"http%3A%2F%2Fhost%2Fpath!djr61!current!pwd!!"
"36000!!2!signature-omitted")
>>> r.success
True
>>> r.principal
"djr61"
>>> r.ptags
set(["current"])
Warning¶
You must check various properties of received responses. See Checking response values
Integrating with existing authentication or session management¶
from ucam_webauth import raven
from datetime import datetime
from flask import Flask, session, flash, url_for, redirect, abort, request
app = Flask(__name__)
app.secret_key = "a secret key"
@app.route("/")
def home():
return "<a href='{0}'>Log in</a>".format(url_for('login'))
@app.route("/login")
def login():
u = url_for("response", _external=True)
r = raven.Request(url=u)
return redirect(str(r))
@app.route("/response")
def response():
r = raven.Response(request.args["WLS-Response"])
# checking url, issue, iact and aauth is very important!
# Werkzeug deduces the hostname from the 'Host' or
# 'X-Forwarded-Host' headers, so we need a whitelist
request.trusted_hosts = {'www.your-domain.com', 'your-domain.com'}
if r.url != request.base_url:
print "Bad url"
abort(400)
issue_delta = (datetime.utcnow() - r.issue).total_seconds()
if not -5 < issue_delta < 15:
print "Bad issue"
abort(403)
if r.success:
# a no-op here, but important if you set iact or aauth
if not r.check_iact_aauth(None, None):
print "check_iact_aauth failed"
abort(403)
session["user"] = r.principal
return redirect(url_for("secrets"))
else:
return redirect(url_for("home"))
@app.route("/secrets")
def secrets():
if session.get("user", None) is None:
abort(401)
return "You are {0}".format(session["user"])
if __name__ == "__main__":
app.run(debug=True)
Warning¶
You must check various properties of received responses. See Checking response values
See also¶
The included simple_demo flask app serves as a far more comprehensive example, including:
- decorator usage
- integration with existing authentication (i.e., user is offered to log in via Raven or some other method)
- full Raven logout
- message flashing