1
0

views.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. from django.conf import settings
  2. from django.contrib.auth import login, REDIRECT_FIELD_NAME
  3. from django.contrib.auth.decorators import login_required
  4. from django.views.decorators.csrf import csrf_exempt, csrf_protect
  5. from django.views.decorators.http import require_POST
  6. from django.views.decorators.cache import never_cache
  7. from social_core.utils import setting_name
  8. from social_core.actions import do_auth, do_complete, do_disconnect
  9. from .utils import psa
  10. NAMESPACE = getattr(settings, setting_name('URL_NAMESPACE'), None) or 'social'
  11. # Calling `session.set_expiry(None)` results in a session lifetime equal to
  12. # platform default session lifetime.
  13. DEFAULT_SESSION_TIMEOUT = None
  14. @never_cache
  15. @psa('{0}:complete'.format(NAMESPACE))
  16. def auth(request, backend):
  17. return do_auth(request.backend, redirect_name=REDIRECT_FIELD_NAME)
  18. @never_cache
  19. @csrf_exempt
  20. @psa('{0}:complete'.format(NAMESPACE))
  21. def complete(request, backend, *args, **kwargs):
  22. """Authentication complete view"""
  23. return do_complete(request.backend, _do_login, user=request.user,
  24. redirect_name=REDIRECT_FIELD_NAME, request=request,
  25. *args, **kwargs)
  26. @never_cache
  27. @login_required
  28. @psa()
  29. @require_POST
  30. @csrf_protect
  31. def disconnect(request, backend, association_id=None):
  32. """Disconnects given backend from current logged in user."""
  33. return do_disconnect(request.backend, request.user, association_id,
  34. redirect_name=REDIRECT_FIELD_NAME)
  35. def get_session_timeout(social_user, enable_session_expiration=False,
  36. max_session_length=None):
  37. if enable_session_expiration:
  38. # Retrieve an expiration date from the social user who just finished
  39. # logging in; this value was set by the social auth backend, and was
  40. # typically received from the server.
  41. expiration = social_user.expiration_datetime()
  42. # We've enabled session expiration. Check to see if we got
  43. # a specific expiration time from the provider for this user;
  44. # if not, use the platform default expiration.
  45. if expiration:
  46. received_expiration_time = expiration.total_seconds()
  47. else:
  48. received_expiration_time = DEFAULT_SESSION_TIMEOUT
  49. # Check to see if the backend set a value as a maximum length
  50. # that a session may be; if they did, then we should use the minimum
  51. # of that and the received session expiration time, if any, to
  52. # set the session length.
  53. if received_expiration_time is None and max_session_length is None:
  54. # We neither received an expiration length, nor have a maximum
  55. # session length. Use the platform default.
  56. session_expiry = DEFAULT_SESSION_TIMEOUT
  57. elif received_expiration_time is None and max_session_length is not None:
  58. # We only have a maximum session length; use that.
  59. session_expiry = max_session_length
  60. elif received_expiration_time is not None and max_session_length is None:
  61. # We only have an expiration time received by the backend
  62. # from the provider, with no set maximum. Use that.
  63. session_expiry = received_expiration_time
  64. else:
  65. # We received an expiration time from the backend, and we also
  66. # have a set maximum session length. Use the smaller of the two.
  67. session_expiry = min(received_expiration_time, max_session_length)
  68. else:
  69. # If there's an explicitly-set maximum session length, use that
  70. # even if we don't want to retrieve session expiry times from
  71. # the backend. If there isn't, then use the platform default.
  72. if max_session_length is None:
  73. session_expiry = DEFAULT_SESSION_TIMEOUT
  74. else:
  75. session_expiry = max_session_length
  76. return session_expiry
  77. def _do_login(backend, user, social_user):
  78. user.backend = '{0}.{1}'.format(backend.__module__,
  79. backend.__class__.__name__)
  80. # Get these details early to avoid any issues involved in the
  81. # session switch that happens when we call login().
  82. enable_session_expiration = backend.setting('SESSION_EXPIRATION', False)
  83. max_session_length_setting = backend.setting('MAX_SESSION_LENGTH', None)
  84. # Log the user in, creating a new session.
  85. login(backend.strategy.request, user)
  86. # Make sure that the max_session_length value is either an integer or
  87. # None. Because we get this as a setting from the backend, it can be set
  88. # to whatever the backend creator wants; we want to be resilient against
  89. # unexpected types being presented to us.
  90. try:
  91. max_session_length = int(max_session_length_setting)
  92. except (TypeError, ValueError):
  93. # We got a response that doesn't look like a number; use the default.
  94. max_session_length = None
  95. # Get the session expiration length based on the maximum session length
  96. # setting, combined with any session length received from the backend.
  97. session_expiry = get_session_timeout(
  98. social_user,
  99. enable_session_expiration=enable_session_expiration,
  100. max_session_length=max_session_length,
  101. )
  102. try:
  103. # Set the session length to our previously determined expiry length.
  104. backend.strategy.request.session.set_expiry(session_expiry)
  105. except OverflowError:
  106. # The timestamp we used wasn't in the range of values supported by
  107. # Django for session length; use the platform default. We tried.
  108. backend.strategy.request.session.set_expiry(DEFAULT_SESSION_TIMEOUT)