CAS Client (SP) for Bottle
Project description
botCasSP - A CAS Client for Bottle Web Apps
Description
botCasSP is a CAS (Central Authentication Service) client module for Bottle web framework applications. The CasSP instance allows bottle apps to be CAS Service Providers (SP's), authenticating users to a CAS server, and use any assertions the CAS server provides within the client session.
CAS is a legacy single sign-on (SSO) protocol, still in not uncommon use, especially in academia. CAS uses back channel verification and is simple to add to applications.
botCasSP Getting started
from botCasSP import CasSP
from BottleSession import BottleSession
from bottle import Bottle
from config import sess_config, cas_config
app = Bottle()
ses = BottleSession(*sess_config)
cas_config ={
'cas_server_base_url': 'https://cas.example.com/cas/',
'cas_attr_list' : ['sn', 'givenName', 'uid', 'groups']
}
casc = CasSP(app=app, config=cas_config)
@app.route('/login')
@casc.require_login
def hello():
return f'Hello {request.session['username']}'
@app.route('/bobAndAlice')
@casc.require_user(['bob','alice'])
def only():
return 'Hello bob or alice'
@app.route('/sysadmins')
@casc.require_attr('groups': ['sysadmin', 'netadmin'])
def admins():
return "Hello admin"
@app.route('/logoff')
def bye():
if casc.is_authenticated:
casc.initiate_logoff(next=request.url)
return 'bye'
if __name__ == '__main__':
app.run()
botCasSP uses BottleSessions for session management. Install BottleSessions before CasSP. (BottleSessions is based on Pallets project cachelib, providing numerous caching back-ends including filesystem, redis, and memcached back-ends.)
At the minimum (cas v1) the CAS server will just authenticate the user. Most v1 and all v2/v3 servers provide the username. With botCasSP this can be accessed as request.session.get('username')
or casc.my_username
.
Other Information provided with CAS v2/v3 server authentication is matched against the cas_attr_list
in the configuration. Attributes with matching names are added to the users session. This is ['sn', 'givenName', 'uid', 'groups']
in the example. If the CAS servers provides these attributes, they are included in the users session and are accessible in a dict
as request.session['attributes']
or casc.my_attrs
.
The username
and attributes
data are available both to views and to any middleware installed in the request stack after BottleSessions. This data can be used by Bottle apps to pre-populate forms, used for identifcation to other systems, etc.
botCasSP CasSP Class
botCasSP is the module, CasSP is the class implementing CAS Service Provider function.
CasSP Class Signature:
from botCasSP import CasSP
casc = CasSP(app=app,
config=cas_config,
sess_username='username',
sess_attr='attributes', logger=None,
)
CasSP Parameters and Configuration:
app:
- Required: the Bottle app instance
sess_username='username':
- Optional: Name of the session entry to contain username (default:
username
as insession['username']
) It's unlikely this needs to be changed.
sess_attr='attributes':
- Optional: Name of the session entry to contain assertion attributes (default:
attributes
as insession['attributes']['email']
) It's unlikely this needs to be changed.
config={}:
-
Required: A Python
dict
of CAS configuration parameters. The most important is the base url and the attribute list:-
cas_server_base_url
: API base URL of the CAS server (required) Typically this is in the form of https://cas.example.org/cas/. CasSP builds out the remainder of the server API from the base url. -
cas_version
: CAS protocol version:v1
,v2
, orv3
(default:v2
) There isn't much benefit to v3, and v1 generally only provides the username. -
cas_attr_list
: Pythonlist
of attributes. These are the assertions from a v2 or v3 server to be kept in a users session from a successful CAS validation response.- e.g. ['email', 'sn', 'givenname', 'groups']
- It's up to the CAS server to provide parameters.
- default is [ ]
Example cas_config
cas_config = { "cas_server_base_url": "https://cas.example.com/cas", "cas_attr_list" : ["sn", "given", "email","groups", "dept"] }
-
logger=None:
- Optional: Python
logger
object. CasSP defaults logging tostderr
if no logger is provided.
Properties:
casc.is_authenticated
: True
if the current session is authenticated.
casc.my_username
Returns username or None
if not authenticated.
casc.my_attrs
Returns dict
of retrieved attrs or {} if not authenticated.
Methods:
Login management
casc.initiate_login(next,**kwargs) => redirect
- Returns SAML (302) redirect to the CAS server to authenticate via username/password or SSO.
next=None
- URL to redirect after login completed (optional)- Use this in your login view, or decorate with
@casc.require_login
- it does the same thing.
casc.initiate_logout(next) => redirect | str
- Initiate Logout from iDP by redirecting to the CAS servers logout.
next=None
- URL to redirect after logout completed (optional) Some CAS servers ignore this.
casc._finish_login() => Response | str
- route:
/casc/finish
- Standard service ticket endpoint from
casc.initiate_login()
- Validates the ticket and runs login hooks
- Construct user session data from validation response.
- redirects user to route that triggered the login.
Login Hooks Decorator
@casc.add_login_hook
or
casc.add_login_hook(f)
- Decorates a function
f
that runs after SAML authentication is completed - each login hook is run in order of additon
- data can be updated before being added to the session with login_hooks
@casc.add_login_hook
def my_login_hook(username, attributes):
# massage or transform attributes
username = username.tolower()
# standaradize naming
attributes['surname'] = attributes['sn']
del attributes['sn']
# supplement data from other sources
attributes['graph'] = get_graph_data_api(username)
# raise exception to thwart login
if attributes['affiliation'] != 'employee':
raise Exception('Employees only')
# return both username and attributes for the next hook to use.
return username, attributes
View Decorators
@casc.login_required
or
casc.login_required(f)
- route decorator
- Decorates a view function
f
to require unauthenticated users to login. - After authentication the user is redirected to the view that initaited the login.
- Order after @app.route decorators:
@app.route('/login')
@casc.login_required
def myview():
return 'All logged in!'
@casc.require_user(user_or_list)
or
casc.require_user(f, user_or_list)
- Decorates a function
f
to require session user to be listed - a single user or a list of users can be provided
- Returns 403 Unauthorized if session username is not in the list
- Order after @app.route decorators:
@app.route('/onlybob')
@casc.require_user('bob')
def view():
return 'Hi bob'
@app.route('/boboralice')
@casc.require_user(['bob', 'alice'])
def view2():
return 'Hi alice or bob'
@casc.require_attr(attr, value)
or
casc.require_user(f, attr, value)
- Decorates a function
f
to require session to have attr with value listed - a single attribute value or a list of values can be provided
- Returns 403 Unauthorized if session does not have the required attr/value.
- Order after @app.route decorators:
@app.route('/dbstuff')
@casc.require_attr('role', 'dba')
def dba_view():
...
@app.route('/infrastructure')
@casc.require_attr('groups', ['sysadmin', 'netadmin','storageadmin', 'cloudadmin'])
def infra_view():
...
Proxy Mode Methods
These are helpers for assembling a CAS proxy service, allowing an SP to request resources from another CAS server on a users behalf.
casc.get_proxy_session(service, resource_urn)
- Acquire and authorize a proxy ticket for
resource_urn
viaservice
- Returns a Python Requests
Session
object orNone
for application use. - Requests
Session
object will have any of the service cookies for theresource_urn
resource_urn
is optional (will use service)
casc.acquire_proxy_ticket(service)
- Returns Proxy Ticket for a
service
proxy_api
mode only.
casc.service_proxy()
- route:
/casc/proxy
- Available only in
proxy_api
mode. - Returns redirect for service with attached proxy_ticket
- route front end for
casc.acquire_proxy_ticket
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
File details
Details for the file botCasClient-21.9.22-py3-none-any.whl
.
File metadata
- Download URL: botCasClient-21.9.22-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | eb826687363c12331cae25ca9944912d6302f024f89ef1f7fef3495809417462 |
|
MD5 | 552e1b6d43a0edd24c21e50f03e3541a |
|
BLAKE2b-256 | 465beee699e07ad6e9dfa80f1e1fa9acbf82bfc60d532b812b9c3a3663badd20 |