3š
Use this custom backend that sets the username to the personās FACEBOOK_ID.
from social_auth.backends.facebook import FacebookBackend
class IDFacebookBackend(FacebookBackend):
"""Facebook OAuth2 authentication backend"""
def get_user_details(self, response):
"""Return user details from Facebook account"""
return {'username': response.get('id'),
'email': response.get('email', ''),
'fullname': response.get('name', ''),
'first_name': response.get('first_name', ''),
'last_name': response.get('last_name', '')}
Use this version of get_username
in your auth pipleline instead of social_auth.backends.pipeline.user.get_username
def get_username(details, user=None, *args, **kwargs):
" Make Username from User Id "
if user:
return {'username': UserSocialAuth.user_username(user)}
else:
return details['username']
Your pipeline should look like this:
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
'our_custom_auth.get_username', # <= This should be the previous function
'social_auth.backends.pipeline.user.create_user',
'social_auth.backends.pipeline.social.associate_user',
'social_auth.backends.pipeline.social.load_extra_data',
'social_auth.backends.pipeline.user.update_user_details'
)
Then all you need to do is call User.objects.create(username=friends_facebook_id)
and you have a User that cannot login with username/pass, but can be referenced easily through ForeignKey fields.
Also, when that āFriendā comes and joins up with your site at a later date (Using SocialAuth), they will automatically be given this User object and your internal graph will stay accurate.
0š
So I used the idea described above but with less effort and eventually I ended up with the following:
I overrode associate_by_email
stage from SOCIAL_AUTH_PIPELINE
to my own implementation of associate_by_username
. Since username is unique in Django auth we can use that.
So totally changes are
-
Implement
associate_by_username
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from social_auth.exceptions import AuthException
from django.contrib.auth.models import Userdef associate_by_username(details, user=None, *args, **kwargs):
āāāReturn user entry with same email address as one returned on details.āāā
if user:
return Noneusername = details.get('username') if username: try: return {'user': User.objects.get(username=username)} except MultipleObjectsReturned: raise AuthException(kwargs['backend'], 'Not unique email address.') except ObjectDoesNotExist: pass
-
Then I add this method to pipeline
SOCIAL_AUTH_PIPELINE = (
āsocial_auth.backends.pipeline.social.social_auth_userā,
ācore.auth.associate_by_usernameā,
āsocial_auth.backends.pipeline.user.get_usernameā,
āsocial_auth.backends.pipeline.user.create_userā,
āsocial_auth.backends.pipeline.social.associate_userā,
āsocial_auth.backends.pipeline.social.load_extra_dataā,
āsocial_auth.backends.pipeline.user.update_user_detailsā,
) -
And when I need to get user I look it up by facebookId (
recipient = UserSocialAuth.objects.filter(uid=target_facebook_id)
) but create by facebookUsername (
User(username=target_username)
)
- [Django]-How to automatic control uwsgi log size
- [Django]-Django-pipeline throwing ValueError: the file could not be found
- [Django]-How to fix Django error: " 'unicode' object has no attribute 'tzinfo' " on database read
- [Django]-Access denied issue when I try to access a shared drive from Django running in Apache
- [Django]-Django rest framework an always sorting field