FAS Authentication for TG2 apps

While working on ResultsDB’s frontend, I’ve finally hit the “We need authentication/authorisation!” spot.  As this is a Fedora effort, FAS was an immediate thought. After some random googling, I found the FASWho Plugin page. So I decided to get my hands dirty, and read through the documentation, browsing all the random hyperlinks, and found no examples whatsoever. Few hours of pointless experimentation (yes, I’m no TurboGears2 pro ;)), I finally pinged lmacken, and asked for help.

He was so kind to point me to the source code for the Fedora Tagger (cool app, btw!), so I can see, test and play around with working code.

In the end, it is way easier, than I’d thought it is. If you have quickstarted TG2 project, these are the minimal changes (in pseudo-diff format) to make it FAS-Login-able.

setup.py

 install_requires=[
    "TurboGears2 >= 2.1.5",
     "Genshi",
     "zope.sqlalchemy >= 0.4",                                                              
     "repoze.tm2 >= 1.0a5",                                                                 
     "sqlalchemy",
     "sqlalchemy-migrate",                                                                  
     "tw.forms",                                                                            
+    
+    "kitchen",
+    "python-fedora",                                                                       
+    "pycurl",                                                                              
+
+    "repoze.who==1.0.19",
+    "repoze.what >= 1.0.8",
+    "repoze.who-friendlyform >= 1.0.4",                                                    
+    "repoze.what-pylons >= 1.0",                                                           
+    "repoze.what-quickstart",
+    "repoze.what.plugins.sql>=1.0.1",                                                      
+    "tgext.admin >= 0.3.11",                                                               
+    
     ]

development.ini

[loggers]
-keys = root, matrix2, sqlalchemy
+keys = root, matrix2, sqlalchemy, auth

+# A logger for authentication, identification and authorization -- this is
+# repoze.who and repoze.what:
+[logger_auth]
+level = WARN
+handlers =
+qualname = auth

config/app_cfg.py

-base_config = AppConfig()
+from fedora.tg2.utils import add_fas_auth_middleware
+
+class MyAppConfig(AppConfig):
+    fas_auth = dict(ssl_cookie = False)
+    add_auth_middleware = add_fas_auth_middleware
+
+base_config = MyAppConfig()
+base_config.sa_auth.cookie_secret = "ChangeME" 
+base_config.auth_backend = 'sqlalchemy'
+base_config.sa_auth.form_plugin = None
+base_config.sa_auth.charset = 'utf-8'
+base_config.sa_auth.post_login_url = '/post_login'
+base_config.sa_auth.post_logout_url = '/post_logout'

controllers/root.py

+from repoze.what import predicates
+from repoze.what.predicates import not_anonymous


+    @expose('matrix2.templates.login')
+    def login(self, came_from=url('/')):
+        """Start the user login."""
+        login_counter = request.environ['repoze.who.logins']
+        if login_counter > 0:
+            flash(_('Wrong credentials'), 'warning')
+        return dict(page='login', login_counter=str(login_counter),
+                    came_from=came_from)
+
+    @expose()
+    def post_login(self, came_from=url('/')):
+        """
+        Redirect the user to the initially requested page on successful
+        authentication or redirect her back to the login page if login failed.
+
+        """
+        if not request.identity:
+            login_counter = request.environ['repoze.who.logins'] + 1
+            redirect('/login',
+                params=dict(came_from=came_from, __logins=login_counter))
+        userid = request.identity['repoze.who.userid']
+        flash(_('Welcome back, %s!') % userid)
+        redirect(came_from)
+
+    @expose()
+    def post_logout(self, came_from=url('/')):
+        """
+        Redirect the user to the initially requested page on logout and say
+        goodbye as well.
+
+        """
+        flash(_('We hope to see you soon!'))
+        redirect(came_from)

lib/base.py

+from tg import request

class BaseController(TGController):
    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # TGController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']

+        request.identity = request.environ.get('repoze.who.identity')
+        tmpl_context.identity = request.identity

If you then want to mark some published method, in your (root) controller, as accessible only for logged-in users, add this decorator under the @expose decorator:

@require(not_anonymous(msg="Login with your FAS credentials."))
Advertisements

About jskladan

Ginger to the bone!
This entry was posted in Fedora. Bookmark the permalink.

One Response to FAS Authentication for TG2 apps

  1. Good day I am so thrilled I found your webpage, I really found you by
    error, while I was searching on Google for something else,
    Nonetheless I am here now and would just like to say kudos for a marvelous post and
    a all round interesting blog (I also love the theme/design), I don’t have time to browse it all at the minute but I have book-marked it and also added your RSS feeds, so when I have time I will be back to read a great deal more, Please do keep up the fantastic work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s