python-cas Flask Example
python-cas is Python CAS (Central Authentication Server) client library support CAS 1.0/2.0/3.0. It was initially split from django-cas-ng to support any Python app to easily implement a CAS client.
This post is an example project to demo how to integrate python-cas into a Flask app. This should give you idea how to integrate python-cas into any other Python app.
If you are new to CAS, to get started about CAS, please checkout CAS 101 .
Flask Example Project
I created a Flask project and integrated python-cas to support CAS login/logout, The integration is pretty straightforward, the key point is Flask need call some CAS API list below:
Design
/login
/login
to handle client login request and redirect to next
after login successfully.
Accept query parameters:
next
: string. The redirect URL after login successfully. e.g.%2Fprofile
. NOTE: Need URL encoded.ticket
: string. CAS service ticket. When CAS authenticated success, it will have this parameter in callback. e.g.ST-1580754576-qbgmySJHjm
.
After login to CAS successfully, set create a session to local Flask app to save login state. The session var is username
.
/logout
and /logout_callback
/logout
will send logout request to CAS server to logout from CAS server,
after CAS logged out user, CAS will redirect to /logout_callback
,
it will logged user out from Flask app locally by delete session.
/profile
/profile
show logged user info. e.g. username
.
Sequence Diagram
CAS login / logout flow sequence diagram as below:
Code
The code is pretty simple, less than 50 lines of code. All the hard work is done by python-cas.
$ cloc app.py
--------------------------------------------------------------
Language files blank comment code
--------------------------------------------------------------
Python 1 18 0 47
--------------------------------------------------------------
The source code as below, it is self explained:
from flask import Flask, request, session, redirect, url_for
from cas import CASClient
app = Flask(__name__)
app.secret_key = 'V7nlCN90LPHOTA9PGGyf'
cas_client = CASClient(
version=3,
service_url='http://localhost:5000/login?next=%2Fprofile',
server_url='https://django-cas-ng-demo-server.herokuapp.com/cas/'
)
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/profile')
def profile(method=['GET']):
if 'username' in session:
return 'Logged in as %s. <a href="/logout">Logout</a>' % session['username']
return 'Login required. <a href="/login">Login</a>', 403
@app.route('/login')
def login():
if 'username' in session:
# Already logged in
return redirect(url_for('profile'))
next = request.args.get('next')
ticket = request.args.get('ticket')
if not ticket:
# No ticket, the request come from end user, send to CAS login
cas_login_url = cas_client.get_login_url()
app.logger.debug('CAS login URL: %s', cas_login_url)
return redirect(cas_login_url)
# There is a ticket, the request come from CAS as callback.
# need call `verify_ticket()` to validate ticket and get user profile.
app.logger.debug('ticket: %s', ticket)
app.logger.debug('next: %s', next)
user, attributes, pgtiou = cas_client.verify_ticket(ticket)
app.logger.debug(
'CAS verify ticket response: user: %s, attributes: %s, pgtiou: %s', user, attributes, pgtiou)
if not user:
return 'Failed to verify ticket. <a href="/login">Login</a>'
else: # Login successfully, redirect according `next` query parameter.
session['username'] = user
return redirect(next)
@app.route('/logout')
def logout():
redirect_url = url_for('logout_callback', _external=True)
cas_logout_url = cas_client.get_logout_url(redirect_url)
app.logger.debug('CAS logout URL: %s', cas_logout_url)
return redirect(cas_logout_url)
@app.route('/logout_callback')
def logout_callback():
# redirect from CAS logout request after CAS logout successfully
session.pop('username', None)
return 'Logged out from CAS. <a href="/login">Login</a>'
You can clone it from https://github.com/python-cas/flask-example/
Run your local server:
$ git clone git@github.com:python-cas/flask-example.git python-cas-flask-example
$ cd python-cas-flask-example
$ pip install -r requirements.txt
$ sh run_debug_server.sh
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
You may curious the actual CAS flow, Here is the debug for reference, you can get more insight about how CAS redirect and ticket validation.
# Login
"GET /login HTTP/1.1" 302 -
DEBUG in app: CAS login URL: https://django-cas-ng-demo-server.herokuapp.com/cas/login?service=http%3A%2F%2Flocalhost%3A5000%2Flogin%3Fnext%3D%252Fprofile
"GET /login HTTP/1.1" 302 -
DEBUG in app: ticket: ST-1580754576-qbgmySJHjmvdeFjy4ZGwkA1IwxGcZxL4
DEBUG in app: next: /profile
DEBUG in app: user: admin, attributes: {}, pgtiou: None
"GET /login?next=%2Fprofile&ticket=ST-1580754576-qbgmySJHjmvdeFjy4ZGwkA1IwxGcZxL4 HTTP/1.1" 302 -
"GET /profile HTTP/1.1" 200 -
# Logout
DEBUG in app: CAS logout URL: https://django-cas-ng-demo-server.herokuapp.com/cas/logout?service=http%3A%2F%2Flocalhost%3A5000%2Flogout_callback
"GET /logout HTTP/1.1" 302 -
"GET /logout_callback HTTP/1.1" 200 -
Live Demo
If you want to see a live demo, you can click here. The following username/password can be used to login in demo server.
username: admin
password: django-cas-ng
Reference
OmniLock - Block / Hide App on iOS
Block distractive apps from appearing on the Home Screen and App Library, enhance your focus and reduce screen time.
DNS Firewall for iOS and Mac OS
Encrypted your DNS to protect your privacy and firewall to block phishing, malicious domains, block ads in all browsers and apps