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