28 Apr, 2010

Django SocialAuth Fix Google Email Open id attribute exchange

Django Social auth is a package that enables login to your django website with Facebook, Google, Yahoo and Twitter. Allowing authentication from 3rd party websites which supports open authentication helps users easy to register to your website without filling too much details. Easier signup makes more registrations and helps you cover your django web hosting charges :D . The package is managed at github here, but it does not have a stable release yet.

One of the issues is the bug in open id attribute exchange of the "email" field when using Google for authentication. The fix is pretty simple, Google requires the type_uri of email to be set to http://axschema.org/contact/email. Thus we have to change the OPENID_AX settings in localsettings.py to

OPENID_AX = [{"type_uri": "http://axschema.org/contact/email",
              "count": 1,
              "required": True,
              "alias": "email"}]

The other change is in the code which reads the openid parameters when login completes in socialauth/auth_backends.py. Here is the complete openid authentication backend code with the fix.

class OpenIdBackend:
    def authenticate(self, openid_key, request, provider):
        try:
            assoc = UserAssociation.objects.get(openid_key = openid_key)
            return assoc.user
        except UserAssociation.DoesNotExist:
            #fetch if openid provider provides any simple registration fields
            nickname = None
            email = None
            if request.openid and request.openid.sreg:
                email = request.openid.sreg.get('email')
                nickname = request.openid.sreg.get('nickname')
            elif request.openid and request.openid.ax:
                if provider == 'Google':
                    email = request.openid.ax.get('http://axschema.org/contact/email')
                    email = email.pop()
                else:
                    email = request.openid.ax.get('email')
                    nickname = request.openid.ax.get('nickname')
            
            if nickname is None :
                nickname =  ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for i in xrange(10)])
            if email is None :
                valid_username = False
                email =  None #'%s@example.openid.com'%(nickname)
            else:
                valid_username = True
            name_count = User.objects.filter(username__startswith = nickname).count()
            if name_count:
                username = '%s%s'%(nickname, name_count + 1)
                user = User.objects.create_user(username,email or '')
            else:
                user = User.objects.create_user(nickname,email or '')
            user.save()
    
            #create openid association
            assoc = UserAssociation()
            assoc.openid_key = openid_key
            assoc.user = user
            if email:
                assoc.email = email
            if nickname:
                assoc.nickname = nickname
            if valid_username:
                assoc.is_username_valid = True
            assoc.save()
            
            #Create AuthMeta
            auth_meta = AuthMeta(user = user, provider = provider)
            auth_meta.save()
            return user
    
    def get_user(self, user_id):
        try:
            user = User.objects.get(pk = user_id)
            return user
        except User.DoesNotExist:
            return None

With these fixes the openid login with google should fetch you the email. :)

Looking for Django Web hosting ?

Try Dreamhost. Get $50 discount off on $114 (ie for 64$) using this promocode ARUN97DISC for unlimited space, bandwidth and django hosting.


Comments (0) Post a comment
You may also like



Email Newsletter
Email:
Popular Posts
Recent Posts
Tags
Random photo
Barefoot Resort Reception Barefoot Resort Reception in Havelock Island Andaman
On Facebook
Recent Comments


digitalpbk