10
votes

I am using django social-auth (http://django-social-auth.readthedocs.org/en/latest/index.html) and trying to create a user profile where the user can associate multiple accounts (like here on Stackoverflow).

Currently I am at the point where single user can login using different authentication providers, but for each login a new user is created. How can I associate all user accounts into single one (like user profile)?

Also, what is the best practice for creating user profile page when using django social-auth?

2

2 Answers

11
votes

DSA already supports multiple account association, the trick is to it is that the user must be logged in, otherwise DSA doesn't know it should be associated with an already existing account.

Regarding your profile, the recommended way to add functionality to DSA is by extending the pipeline, you can create an entry like this:

def create_profile(user, is_new=False, *args, **kwargs):
    if is_new:
        # create a profile instance for the given user
        create_user_profile(user)

Then register it in the settings like this:

SOCIAL_AUTH_PIPELINE = (
    'social_auth.backends.pipeline.social.social_auth_user',
    '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',
    'myapp.pipeline.create_profile'
)

Where the entry is the import path to get that function.

Edit: linking to docs and setting explanation.

1
votes

I see 2 alterntive when you want to handle with multiple account association:

    1. Find a unique attribute that all identity provider has.
    1. Keep a base authentication and link all the rest identity providers to its.

The first approach has 2 disadvantages

  • Is possible that does not exist any attibute that is present in all the identity provider. One common implementatios that people did in the past is to use the email as this attribute to identity the user, but for example Twitter does not share the email anymore.

  • Is posible to find a non consistent problem. For example people can set differents values for an username or for a email in the differents providers.

I recommend you to implement the second approach. Set a primary identity provider (ldap, database or an authentication closed and secure for you). And each time a user want link a "X identity provider to your account", look for the attribute that this provider use and save in a table this relation between your primary identity and that new identity.

Keep also aware about the data colision. Set what provider will have preference when setting the data for your local account, in order to not turn your data wrong or expired. (Read somethig about "Level of assurance)

This is an old debate so first of implement something, start to read. There are many interesting documentation about this issues

Related to the specific problem in django. Read this comparation between the differents djago social-auth apps. Also check django-socialprofile and this old thread