Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/configuration/django.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,55 @@ Django user. It is not a separate authentication user model. By default,
``UserSocialAuth.user`` references ``settings.AUTH_USER_MODEL``, so social login
and Django's username/password login use the same user model.

.. _django-manual-disconnection:

Disconnecting social accounts in code
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

With the default Django ORM storage, you can remove social account associations
directly through the user's ``social_auth`` related manager. Given a saved
Django ``user`` instance::

# Remove all social account associations for this user.
user.social_auth.all().delete()

# Remove only this user's GitHub associations.
user.social_auth.filter(provider="github").delete()

These operations preserve the Django user and application data related only
to that user. Application models that reference ``UserSocialAuth`` follow
their own relationship's ``on_delete`` behavior: ``CASCADE`` deletes dependent
rows, while ``PROTECT`` or ``RESTRICT`` can prevent deletion. Check those
relationships before removing associations.

To remove a single association using the storage API::

from social_django.models import UserSocialAuth

association = user.social_auth.get(pk=association_id)
UserSocialAuth.disconnect(association)

Direct deletion bypasses the :ref:`disconnection-pipeline`, including the check
that the user has another login method, optional provider token revocation,
and any custom pipeline steps. Use it when your application intentionally
handles these responsibilities itself. For user-facing disconnection, use the
normal disconnection view so the configured pipeline runs.

Deleting a Django user
^^^^^^^^^^^^^^^^^^^^^^

The ``UserSocialAuth.user`` foreign key uses ``on_delete=models.CASCADE``.
Deleting a user through Django's ORM, for example with ``user.delete()``,
automatically deletes their social account associations. You do not need to
disconnect those associations in a user-deletion hook first. Cascading deletion
does not run the disconnection pipeline or revoke provider tokens.

Other application models that reference the user follow their own deletion
rules. If user deletion raises a foreign key error naming another application's
table, inspect that model's relationship, migrations, and deletion code.
Removing social account associations does not remove references from unrelated
tables.

Custom authentication user models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
3 changes: 3 additions & 0 deletions docs/logging_out.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ check that the user account is in a valid state for disconnection (it has at
least one more social account associated, or a password, etc). This behavior
can be overridden by changing the `Disconnection Pipeline`_.

For Django code that removes associations directly, and for user deletion,
see :ref:`django-manual-disconnection`.

.. _logout_user(): https://github.com/maxcountryman/flask-login/blob/a96de342eae560deec008a02179f593c3799b3ba/flask_login.py#L718-L739
.. _Disconnection Pipeline: pipeline.html#disconnection-pipeline
2 changes: 2 additions & 0 deletions docs/pipeline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ such as ``SOCIAL_AUTH_TWITTER_PIPELINE``. Backend-specific pipelines will overri
the default and ``SOCIAL_AUTH_PIPELINE`` settings.


.. _disconnection-pipeline:

Disconnection Pipeline
----------------------

Expand Down
4 changes: 2 additions & 2 deletions docs/storage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ an arbitrary row when stored provider data matches multiple associations.
raise NotImplementedError('Implement in subclass')

@classmethod
def disconnect(cls, name, user, association_id=None):
"""Disconnect the social account for the given user"""
def disconnect(cls, entry):
"""Remove the given social account association"""
raise NotImplementedError('Implement in subclass')


Expand Down
Loading