PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/openid_consumer/views.py

http://github.com/agiliq/Django-Socialauth
Python | 224 lines | 193 code | 24 blank | 7 comment | 34 complexity | d23ed7c86aa4235704e82ce08a54216d MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
  1. from django.http import HttpResponse, HttpResponseRedirect
  2. from django.shortcuts import render_to_response as render
  3. from django.template import RequestContext
  4. from django.conf import settings
  5. from django.utils.translation import ugettext_lazy as _
  6. import re, time, urllib
  7. import openid
  8. if openid.__version__ < '2.0.0':
  9. raise ImportError, 'You need python-openid 2.0.0 or newer'
  10. elif openid.__version__ < '2.1.0':
  11. from openid.sreg import SRegRequest
  12. else:
  13. from openid.extensions.sreg import SRegRequest
  14. try:
  15. from openid.extensions.pape import Request as PapeRequest
  16. except ImportError:
  17. from openid.extensions import pape as openid_pape
  18. PapeRequest = openid_pape.Request
  19. from openid.extensions.ax import FetchRequest as AXFetchRequest
  20. from openid.extensions.ax import AttrInfo
  21. from openid.consumer.consumer import Consumer, \
  22. SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
  23. from openid.consumer.discover import DiscoveryFailure
  24. from openid.yadis import xri
  25. from util import OpenID, DjangoOpenIDStore, from_openid_response
  26. from middleware import OpenIDMiddleware
  27. from django.utils.html import escape
  28. def get_url_host(request):
  29. if request.is_secure():
  30. protocol = 'https'
  31. else:
  32. protocol = 'http'
  33. host = escape(request.get_host())
  34. return '%s://%s' % (protocol, host)
  35. def get_full_url(request):
  36. return get_url_host(request) + request.get_full_path()
  37. next_url_re = re.compile('^/[-\w/]+$')
  38. def is_valid_next_url(next):
  39. # When we allow this:
  40. # /openid/?next=/welcome/
  41. # For security reasons we want to restrict the next= bit to being a local
  42. # path, not a complete URL.
  43. return bool(next_url_re.match(next))
  44. def begin(request, redirect_to=None, on_failure=None, user_url=None,
  45. template_name='openid_consumer/signin.html'):
  46. on_failure = on_failure or default_on_failure
  47. trust_root = getattr(
  48. settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'
  49. )
  50. # foo derbis.
  51. redirect_to = redirect_to or getattr(
  52. settings, 'OPENID_REDIRECT_TO',
  53. # If not explicitly set, assume current URL with complete/ appended
  54. get_full_url(request).split('?')[0] + 'complete/'
  55. )
  56. # In case they were lazy...
  57. if not (
  58. redirect_to.startswith('http://')
  59. or
  60. redirect_to.startswith('https://')):
  61. redirect_to = get_url_host(request) + redirect_to
  62. if request.GET.get('next') and is_valid_next_url(request.GET['next']):
  63. if '?' in redirect_to:
  64. join = '&'
  65. else:
  66. join = '?'
  67. redirect_to += join + urllib.urlencode({
  68. 'next': request.GET['next']
  69. })
  70. if not user_url:
  71. user_url = request.REQUEST.get('openid_url', None)
  72. if not user_url:
  73. request_path = request.path
  74. if request.GET.get('next'):
  75. request_path += '?' + urllib.urlencode({
  76. 'next': request.GET['next']
  77. })
  78. return render(template_name, {
  79. 'action': request_path,
  80. }, RequestContext(request))
  81. if xri.identifierScheme(user_url) == 'XRI' and getattr(
  82. settings, 'OPENID_DISALLOW_INAMES', False
  83. ):
  84. return on_failure(request, _('i-names are not supported'))
  85. consumer = Consumer(request.session, DjangoOpenIDStore())
  86. try:
  87. auth_request = consumer.begin(user_url)
  88. except DiscoveryFailure:
  89. return on_failure(request, _('The OpenID was invalid'))
  90. sreg = getattr(settings, 'OPENID_SREG', False)
  91. if sreg:
  92. s = SRegRequest()
  93. for sarg in sreg:
  94. if sarg.lower().lstrip() == "policy_url":
  95. s.policy_url = sreg[sarg]
  96. else:
  97. for v in sreg[sarg].split(','):
  98. s.requestField(field_name=v.lower().lstrip(),
  99. required=(sarg.lower().lstrip() ==
  100. "required"))
  101. auth_request.addExtension(s)
  102. pape = getattr(settings, 'OPENID_PAPE', False)
  103. if pape:
  104. if openid.__version__ <= '2.0.0' and openid.__version__ >= '2.1.0':
  105. raise (ImportError,
  106. 'For pape extension you need python-openid 2.1.0 or newer')
  107. p = PapeRequest()
  108. for parg in pape:
  109. if parg.lower().strip() == 'policy_list':
  110. for v in pape[parg].split(','):
  111. p.addPolicyURI(v)
  112. elif parg.lower().strip() == 'max_auth_age':
  113. p.max_auth_age = pape[parg]
  114. auth_request.addExtension(p)
  115. OPENID_AX_PROVIDER_MAP = getattr(settings, 'OPENID_AX_PROVIDER_MAP', {})
  116. openid_provider = ('Google' if
  117. 'google' in request.session.get('openid_provider', '')
  118. else 'Default')
  119. ax = OPENID_AX_PROVIDER_MAP.get(openid_provider)
  120. if ax:
  121. axr = AXFetchRequest()
  122. for attr_name, attr_url in ax.items():
  123. # axr.add(AttrInfo(i['type_uri'],
  124. # i['count'], i['required'],
  125. # i['alias']))
  126. # setting all as required attrs
  127. axr.add(AttrInfo(attr_url, required=True))
  128. auth_request.addExtension(axr)
  129. redirect_url = auth_request.redirectURL(trust_root, redirect_to)
  130. return HttpResponseRedirect(redirect_url)
  131. def complete(request, on_success=None, on_failure=None,
  132. failure_template='openid_consumer/failure.html'):
  133. on_success = on_success or default_on_success
  134. on_failure = on_failure or default_on_failure
  135. consumer = Consumer(request.session, DjangoOpenIDStore())
  136. #dummydebug
  137. #for r in request.GET.items():
  138. # print r
  139. # JanRain library raises a warning if passed unicode objects as the keys,
  140. # so we convert to bytestrings before passing to the library
  141. query_dict = dict([
  142. (k.encode('utf8'),
  143. v.encode('utf8')) for k, v in request.REQUEST.items()
  144. ])
  145. url = get_url_host(request) + request.path
  146. openid_response = consumer.complete(query_dict, url)
  147. if openid_response.status == SUCCESS:
  148. return on_success(request,
  149. openid_response.identity_url,
  150. openid_response)
  151. elif openid_response.status == CANCEL:
  152. return on_failure(request,
  153. _('The request was cancelled'), failure_template)
  154. elif openid_response.status == FAILURE:
  155. return on_failure(request, openid_response.message, failure_template)
  156. elif openid_response.status == SETUP_NEEDED:
  157. return on_failure(request, _('Setup needed'), failure_template)
  158. else:
  159. assert False, "Bad openid status: %s" % openid_response.status
  160. def default_on_success(request, identity_url, openid_response):
  161. if 'openids' not in request.session.keys():
  162. request.session['openids'] = []
  163. # Eliminate any duplicates
  164. request.session['openids'] = [
  165. o for o in request.session['openids'] if o.openid != identity_url
  166. ]
  167. request.session['openids'].append(from_openid_response(openid_response))
  168. # Set up request.openids and request.openid, reusing middleware logic
  169. OpenIDMiddleware().process_request(request)
  170. next = request.GET.get('next', '').strip()
  171. if not next or not is_valid_next_url(next):
  172. next = getattr(settings, 'OPENID_REDIRECT_NEXT', '/')
  173. return HttpResponseRedirect(next)
  174. def default_on_failure(request, message,
  175. template_name='openid_consumer/failure.html'):
  176. return render(template_name, {
  177. 'message': message
  178. }, RequestContext(request))
  179. def signout(request):
  180. request.session['openids'] = []
  181. next = request.GET.get('next', '/')
  182. if not is_valid_next_url(next):
  183. next = '/'
  184. return HttpResponseRedirect(next)