-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathauth.py
More file actions
95 lines (77 loc) · 3 KB
/
auth.py
File metadata and controls
95 lines (77 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import urllib.request
import urllib.parse
import re
import flask
from flask import g
from top import app
_CAS_URL = 'https://fed.princeton.edu/cas/'
#-----------------------------------------------------------------------
# Return url after stripping out the "ticket" parameter that was
# added by the CAS server.
def strip_ticket(url):
if url is None:
return "something is badly wrong"
url = re.sub(r'ticket=[^&]*&?', '', url)
url = re.sub(r'\?&?$|&$', '', url)
return url
#-----------------------------------------------------------------------
# Validate a login ticket by contacting the CAS server. If
# valid, return the user's username; otherwise, return None.
def validate(ticket):
val_url = (_CAS_URL + "validate" + '?service='
+ urllib.parse.quote(strip_ticket(flask.request.url))
+ '&ticket=' + urllib.parse.quote(ticket))
lines = []
with urllib.request.urlopen(val_url) as flo:
lines = flo.readlines() # Should return 2 lines.
if len(lines) != 2:
return None
first_line = lines[0].decode('utf-8')
second_line = lines[1].decode('utf-8')
if not first_line.startswith('yes'):
return None
return second_line
#-----------------------------------------------------------------------
# Authenticate the remote user, and return the user's username.
# Do not return unless the user is successfully authenticated.
def authenticate():
# If the username is in the session, then the user was
# authenticated previously. So return the username.
if 'username' in flask.session:
g.username = flask.session['username']
return g.username
# If the request does not contain a login ticket, then redirect
# the browser to the login page to get one.
ticket = flask.request.args.get('ticket')
if ticket is None:
login_url = (_CAS_URL + 'login?service=' +
urllib.parse.quote(flask.request.url))
flask.abort(flask.redirect(login_url))
# If the login ticket is invalid, then redirect the browser
# to the login page to get a new one.
username = validate(ticket)
if username is None:
login_url = (_CAS_URL + 'login?service='
+ urllib.parse.quote(strip_ticket(flask.request.url)))
flask.abort(flask.redirect(login_url))
# The user is authenticated, so store the username in
# the session.
username = username.strip()
flask.session['username'] = username
g.username = username
return username
@app.before_request
def load_user():
# Make username available globally in the request context
g.username = flask.session.get('username')
@app.context_processor
def inject_user():
# Inject username into all templates
return {'username': g.username}
@app.route('/out', methods=['GET'])
def out():
# Log out of the CAS session, and then the application.
logout_url = (_CAS_URL + 'logout?service='
+ urllib.parse.quote(
re.sub('out', 'logout', flask.request.url)))
return flask.redirect(logout_url)