openid login form redirection

42 views
Skip to first unread message

Oliver

unread,
Sep 10, 2010, 2:35:42 PM9/10/10
to pylons-discuss
hi,

I am using repoze.who.plugins.openid with following configurations:


[plugin:openid]
use = repoze.who.plugins.openid:make_identification_plugin
store = file
store_file_path = %(here)s/sstore
openid_field = openid
came_from_field = came_from
error_field = error
session_name = beaker.session
login_form_url = /account/openid_login

My understanding is if a controller needs authentication (by putting
not_anonymous() predicate before action or controller), the middleware
will try to redirect to login form specified by /account/openid_login.

However, this doesn't seem to have any effect, for whatever reason, it
insists on directing to /account/login, any idea?

TIA

Oliver

Mariano Mara

unread,
Sep 10, 2010, 2:51:48 PM9/10/10
to pylons-discuss
Excerpts from Oliver's message of Fri Sep 10 15:35:42 -0300 2010:

You need to configure repoze.who through repoze.what in order to use
repoze what protectors like not_anonymous. Besides that, remember that
the standard openid plugin has only a dummy authenticator plugin that
does nothing and you might need to extend it to make it talk with your
database or whatever.

In my case instead of using who.ini for configuring the plugin I did all
in middleware.py. Find below my configuration (repdotcom is the name of
my pylons project, everything else is standard repoze what/who).
Feel free to ask any clarification you need to understand the code.


from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin
from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin
from repdotcom.lib.auth import OpenIdMetadata, OpenIdAuthenticator
from repoze.who.classifiers import default_request_classifier
from repoze.who.plugins.openid.classifiers import openid_challenge_decider
from repoze.what.middleware import setup_auth

from repdotcom.config.environment import load_environment

def make_app(global_conf, full_stack=True, static_files=True, **app_conf):

... some code here ...

# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)

openid = OpenIdIdentificationPlugin(
store='file',
openid_field='openid',
session_name='pylons.session',
login_handler_path='/openid_login_handler',
logout_handler_path='/logout_handler',
login_form_url='/login',
error_field='error',
logged_in_url='/welcome_back',
logged_out_url='/see_you_later',
came_from_field='came_from',
store_file_path=app_conf['cache_dir']+'/sstore',
rememberer_name='auth_tkt',
attr_ex='openid.ax.required=email openid.ax.type.email=http://axschema.org/contact/email')
auth_tkt = AuthTktCookiePlugin(secret='xxxxxxxxxx', secure=True,
timeout=86400, reissue_time=3600)
authenticator = OpenIdAuthenticator()
openidmd = OpenIdMetadata()
app = setup_auth(app, None, None,
identifiers=[('openid', openid),
('auth_tkt', auth_tkt)],
authenticators=[('authenticator', authenticator)],
challengers=[('openid', openid)],
mdproviders=[('mdproviders', openidmd)],
classifier=default_request_classifier,
challenge_decider=openid_challenge_decider,
log_stream=app_conf['who.log_file'],
log_level=app_conf['who.log_level'])

Oliver

unread,
Sep 10, 2010, 3:25:11 PM9/10/10
to pylons-discuss
Thanks Mariano,

Would you mind sharing auth.py or specially, the code for
OpenIdAuthenticator()
OpenIdMetadata()

Thanks

Oliver

Mariano Mara

unread,
Sep 10, 2010, 3:48:08 PM9/10/10
to pylons-discuss
Excerpts from Oliver's message of Fri Sep 10 16:25:11 -0300 2010:

> Thanks Mariano,
>
> Would you mind sharing auth.py or specially, the code for
> OpenIdAuthenticator()
> OpenIdMetadata()
>
> Thanks
>
> Oliver
>

I wouldn't mind.
In this particular project I'm developing an application that uses
Google OpenId implementation since this organization is using Apps for
mail so I just need Google's openid to return the user's email (that's
why I'm using attribute exchange and trying to authenticate against the
user email). This means that the user email should exist in my database
or otherwise I cannot grant access to her/him. You might need to
implement other strategy though. Anyway, whatever you do, in
OpenIdAuthenticator you need to return the user's id or None (you cannot
raise exceptions). In OpenIdMetada you can add some extra information to
the identity dictionary, like preferred language, gender, etc.


from zope.interface import implements
from repoze.who.interfaces import IAuthenticator, IMetadataProvider

from repdotcom.model.meta import Session
from repdotcom.model.parameter import User

class OpenIdMetadata(object):

implements(IMetadataProvider)

def add_metadata( self, environ, identity ):
"""Add our stored metadata to given identity if available"""
key = identity.get('repoze.who.userid')
if key:
# as_user_values is a method that returns extra data about
# the authenticated user, such as name, surname, gender and
# language
user = as_user_values(key)
try:
identity['userdata'] = user
except AttributeError:
pass
return identity

class OpenIdAuthenticator(object):

implements(IAuthenticator)

def authenticate(self, environ, identity):
key = identity.get('repoze.who.plugins.openid.openid.ax.type.email')
if key:
try:
user = Session.query(User.id).\
filter(User.email==unicode(key[0])).\
filter(User.active==True).one()
environ['repoze.who.logger'].\
info('authenticated : %s ' % user.id)
return user.id
except NoResultFound:
return None
else:
return None

Reply all
Reply to author
Forward
0 new messages