FASWho Plugin¶
Authors: | Luke Macken Toshio Kuratomi |
---|---|
Date: | 3 September 2011 |
This plugin provides authentication to the Fedora Account System using the repoze.who WSGI middleware. It is designed for use with TurboGears2 but it may be used with any repoze.who using application. Like TurboGears Identity Provider 2, faswho has builtin CSRF protection. This protection is implemented as a second piece of middleware and may be used with other repoze.who authentication schemes.
Authenticating against FAS with TurboGears2¶
Setting up authentication against FAS in TurboGears2 is very easy. It
requires one change to be made to app/config/app_cfg.py
. This change
will take care of registering faswho as the authentication provider, enabling
CSRF protection, switching tg.url()
to use
fedora.ta2g.utils.url()
instead, and allowing the _csrf_token
parameter to be given to any URL.
-
fedora.wsgi.faswho.faswhoplugin.
make_faswho_middleware
(app, log_stream=None, login_handler='/login_handler', login_form_url='/login', logout_handler='/logout_handler', post_login_url='/post_login', post_logout_url=None, fas_url='https://admin.fedoraproject.org/accounts/', insecure=False, ssl_cookie=True, httponly=True)¶ Parameters: - app – WSGI app that is being wrapped
- log_stream –
logging.Logger
to log auth messages - login_handler – URL where the login form is submitted
- login_form_url – URL where the login form is displayed
- logout_handler – URL where the logout form is submitted
- post_login_url – URL to redirect the user to after login
- post_logout_url – URL to redirect the user to after logout
- fas_url – Base URL to the FAS server
- insecure – Allow connecting to a fas server without checking the server’s SSL certificate. Opens you up to MITM attacks but can be useful when testing. Do not enable this in production
- ssl_cookie – If
True
(default), tell the browser to only send the session cookie back over https. - httponly – If
True
(default), tell the browser that the session cookie should only be read for sending to a server, not for access by JavaScript or other clientside technology. This prevents using the session cookie to pass information to JavaScript clients but also prevents XSS attacks from stealing the session cookie information.
Using CSRF middleware with other Auth Methods¶
This section needs to be made clearer so that apps like mirrormanager can be ported to use this.
Cross-site Request Forgery Protection.
http://en.wikipedia.org/wiki/Cross-site_request_forgery
Module author: John (J5) Palmieri <johnp@redhat.com>
Module author: Luke Macken <lmacken@redhat.com>
New in version 0.3.17.
-
class
fedora.wsgi.csrf.
CSRFProtectionMiddleware
(application, csrf_token_id='_csrf_token', clear_env='repoze.who.identity repoze.what.credentials', token_env='CSRF_TOKEN', auth_state='CSRF_AUTH_STATE')¶ CSRF Protection WSGI Middleware.
A layer of WSGI middleware that is responsible for making sure authenticated requests originated from the user inside of the app’s domain and not a malicious website.
This middleware works with the
repoze.who
middleware, and requires that it is placed belowrepoze.who
in the WSGI stack, since it relies uponrepoze.who.identity
to exist in the environ before it is called.To utilize this middleware, you can just add it to your WSGI stack below the
repoze.who
middleware. Here is an example of utilizing the CSRFProtectionMiddleware within a TurboGears2 application. In yourproject/config/middleware.py
, you would wrap your main application with the CSRFProtectionMiddleware, like so:from fedora.wsgi.csrf import CSRFProtectionMiddleware def make_app(global_conf, full_stack=True, **app_conf): app = make_base_app(global_conf, wrap_app=CSRFProtectionMiddleware, full_stack=full_stack, **app_conf)
You then need to add the CSRF token to every url that you need to be authenticated for. When used with TurboGears2, an overridden version of
tg.url()
is provided. You can use it directly by calling:from fedora.tg2.utils import url [...] url = url('/authentication_needed')
An easier and more portable way to use that is from within TG2 to set this up is to use
fedora.tg2.utils.enable_csrf()
when you setup your application. This function will monkeypatch TurboGears2’stg.url()
so that it adds a csrf token to urls. This way, you can keep the same code in your templates and controller methods whether or not you configure the CSRF middleware to provide you with protection viaenable_csrf()
.
-
class
fedora.wsgi.csrf.
CSRFMetadataProvider
(csrf_token_id='_csrf_token', session_cookie='tg-visit', clear_env='repoze.who.identity repoze.what.credentials', login_handler='/post_login', token_env='CSRF_TOKEN', auth_session_id='CSRF_AUTH_SESSION_ID', auth_state='CSRF_AUTH_STATE')¶ Repoze.who CSRF Metadata Provider Plugin.
This metadata provider is called with an authenticated users identity automatically by repoze.who. It will then take the SHA1 hash of the users session cookie, and set it as the CSRF token in
environ['repoze.who.identity']['_csrf_token']
.This plugin will also set
CSRF_AUTH_STATE
in the environ if the user has just authenticated during this request.To enable this plugin in a TurboGears2 application, you can add the following to your
project/config/app_cfg.py
from fedora.wsgi.csrf import CSRFMetadataProvider base_config.sa_auth.mdproviders = [('csrfmd', CSRFMetadataProvider())]
Note: If you use the faswho plugin, this is turned on automatically.
Templates¶
The fedora.tg2.utils
module contains some templates to help you
write CSRF aware login forms and buttons. You can use the
fedora_template()
function to integrate them into your
templates:
The templates themselves come in two flavors. One set for use with mako and one set for use with genshi.
Mako¶
Mako version of templates to make adding certain Fedora widgets easier.
fedora.tg2.templates.mako.login.mak
¶
Module author: Toshio Kuratomi <tkuratom@redhat.com>
New in version 0.3.25.
Include this using:
<%namespace name="fedora" file="${context['fedora_template']('login.mak')}" />
-
fedora.tg2.templates.mako.login.mak.
loginform
(message='')¶
kwarg message: | Any text or elements contained by the <loginform> tag will be shown as a message to the user. This is generally used to show status of the last login attempt (“Please provide your credentials”, “Supplied credentials were not correct”, etc) |
---|
A function for generating the main login form. This is a CSRF token-aware login form that will prompt for username and password when no session identity is present and ask the user to click a link if they merely lack a token.
Typical usage, given the above import of the login.mak
template would
be:
${fedora.loginform()}
-
fedora.tg2.templates.mako.login.mak.
logintoolitem
(href=None)¶
kwarg href: | If an href is given, when a user is logged in, their username or display_name will be a link to the URL. |
---|
This function creates an entry into a toolbar for logging into a web app. The entry will contain the user’s username and a logout button if the user is logged in, a verify login button if the user has a session cookie but not a CSRF token, or a login button if the user doesn’t have a session cookie.
Typical usage looks like this:
<ul class="toolbar" id="#main-toolbar">
${fedora.logintoolitem(href=tg.url('/users/info'))}
</ul>
fedora.tg2.templates.mako.jsglobals.mak
¶
Module author: Toshio Kuratomi <tkuratom@redhat.com>
New in version 0.3.25.
Include this using:
<%namespace name="jsglobals" file="${context['fedora_template']('jsglobals.mak')}" />
-
fedora.tg2.templates.mako.jsglobals.mak.
jsglobals
()¶
A function to add global variables to a page. Typically, you’d include
this in your master.mak
template and let the javascript variables
defined there propogate to every page on your site (since they all should
inherit from master.mak
). This adds the following variables in the
fedora namespace for other scripts to access:
fedora.baseurl: URL fragment to prepend to any calls to the application. In a TurboGears application, this is the scheme, host, and server.webpath. Example: https://admin.fedoraproject.org/pkgdb/. This may be a relative link. fedora.identity.anonymous: If true
, there will be no other variables in the fedora.identity namespace. Iffalse
, these variables are defined:fedora.identity.userid: Numeric, unique identifier for the user fedora.identity.username: Publically visible unique identifier for the user fedora.identity.display_name: Common human name for the user fedora.identity.token: csrf token for this user’s session to be added to urls that query the server.
Typical usage would be:
${jsglobals.jsglobals()}
Genshi¶
Genshi version of templates to make adding certain Fedora widgets easier.
fedora.tg2.templates.genshi.login.html
¶
Module author: Toshio Kuratomi <tkuratom@redhat.com>
New in version 0.3.26.
- Include this using::
- <xi:include href=”${fedora_template(‘login.html’, template_type=’genshi’)}” />
-
fedora.tg2.templates.genshi.login.html.
loginform
([message])¶
message: | Any text or elements contained by the <loginform> tag will be shown as a message to the user. This is generally used to show status of the last login attempt (“Please provide your credentials”, “Supplied credentials were not correct”, etc) |
---|
A match template for the main login form. This is a CSRF token-aware login form that will prompt for username and password when no session identity is present and ask the user to click a link if they merely lack a token.
Typical usage would be:
<loginform>${message}</loginform>
-
fedora.tg2.templates.genshi.login.html.
logintoolitem
(@href=URL)¶
@href: | If an href attribute is present for this tag, when a user is logged in, their username or display_name will be a link to the URL. |
---|
A match template to add an entry to a toolbar. The entry will contain the user’s username and a logout button if the user is logged in, a verify login button if the user has a session cookie but not a CSRF token, or a login button if the user doesn’t have a session cookie.
Typical usage looks like this:
<ul class="toolbar" id="#main-toolbar">
<logintoolitem href="${tg.url('/users/info')}" />
</ul>
fedora.tg2.templates.genshi.jsglobals.html
¶
Module author: Toshio Kuratomi <tkuratom@redhat.com>
New in version 0.3.26.
- Include this using::
- <xi:include href=”${fedora_template(‘jsglobals.html’, template_type=’genshi’)}” />
-
fedora.tg2.templates.genshi.jsglobals.html.
jsglobals
()¶
A match template to add global variables to a page. Typically, you’d include
this in your master.html
template and let it be added to every other
page from there. This adds the following variables in the fedora namespace
for other scripts to access:
fedora.baseurl: URL fragment to prepend to any calls to the application. In a TurboGears application, this is the scheme, host, and server.webpath. Example: https://admin.fedoraproject.org/pkgdb/. This may be a relative link. fedora.identity.anonymous: If true
, there will be no other variables in the fedora.identity namespace. Iffalse
, these variables are defined:fedora.identity.userid: Numeric, unique identifier for the user fedora.identity.username: Publically visible unique identifier for the user fedora.identity.display_name: Common human name for the user fedora.identity.token: csrf token for this user’s session to be added to urls that query the server.
Typical usage would be:
<jsglobals />