~mhall119/django-openid-auth/provides-784239

« back to all changes in this revision

Viewing changes to django_openidconsumer/views.py

  • Committer: swillison
  • Date: 2007-04-24 00:19:51 UTC
  • Revision ID: svn-v3-trunk0:3bcd880a-622a-0410-974b-89bbab7935c3:trunk:10
Ready for launch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from django.http import HttpResponse, HttpResponseRedirect, Http404
 
1
from django.http import HttpResponse, HttpResponseRedirect, get_host
2
2
from django.shortcuts import render_to_response as render
3
3
from django.template import RequestContext
4
4
from django.conf import settings
5
5
 
6
 
import md5, time
 
6
import md5, re, time
7
7
from openid.consumer.consumer import Consumer, \
8
8
    SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
9
9
from openid.consumer.discover import DiscoveryFailure
 
10
from yadis import xri
 
11
 
10
12
from util import OpenID, DjangoOpenIDStore, from_openid_response
11
13
 
12
14
from django.utils.html import escape
16
18
        protocol = 'https'
17
19
    else:
18
20
        protocol = 'http'
19
 
    host = escape(request.META['HTTP_HOST'])
 
21
    host = escape(get_host(request))
20
22
    return '%s://%s' % (protocol, host)
21
23
 
22
24
def get_full_url(request):
27
29
    host = escape(request.META['HTTP_HOST'])
28
30
    return get_url_host(request) + request.get_full_path()
29
31
 
30
 
def is_valid_after_url(after):
 
32
next_url_re = re.compile('^/[-\w/]+$')
 
33
 
 
34
def is_valid_next_url(next):
31
35
    # When we allow this:
32
 
    #   /openid/?after=/welcome/
33
 
    # For security reasons we want to restrict the after= bit to being a local 
 
36
    #   /openid/?next=/welcome/
 
37
    # For security reasons we want to restrict the next= bit to being a local 
34
38
    # path, not a complete URL.
35
 
    if not after.startswith('/'):
36
 
        return False
37
 
    if '://' in after:
38
 
        return False
39
 
    for c in after:
40
 
        if c.isspace():
41
 
            return False
42
 
    return True
 
39
    return bool(next_url_re.match(next))
43
40
 
44
 
def begin(request, sreg=None, extension_args=None):
 
41
def begin(request, sreg=None, extension_args=None, redirect_to=None):
 
42
    if request.GET.get('logo'):
 
43
        # Makes for a better demo
 
44
        return HttpResponse(
 
45
            OPENID_LOGO_BASE_64.decode('base64'), mimetype='image/gif'
 
46
        )
 
47
    
45
48
    extension_args = extension_args or {}
46
49
    if sreg:
47
50
        extension_args['sreg.optional'] = sreg
48
51
    trust_root = getattr(
49
52
        settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'
50
53
    )
51
 
    redirect_to = getattr(
 
54
    redirect_to = redirect_to or getattr(
52
55
        settings, 'OPENID_REDIRECT_TO',
53
56
        # If not explicitly set, assume current URL with complete/ appended
54
57
        get_full_url(request).split('?')[0] + 'complete/'
55
58
    )
 
59
    # In case they were lazy...
 
60
    if not redirect_to.startswith('http://'):
 
61
        redirect_to =  get_url_host(request) + redirect_to
56
62
    
57
 
    if request.GET.get('after') and is_valid_after_url(request.GET['after']):
 
63
    if request.GET.get('next') and is_valid_next_url(request.GET['next']):
58
64
        if '?' in redirect_to:
59
65
            join = '&'
60
66
        else:
61
67
            join = '?'
62
 
        redirect_to += join + 'after=' + urllib.urlencode(request.GET['after'])
 
68
        redirect_to += join + 'next=' + urllib.urlencode(request.GET['next'])
63
69
    
64
 
    user_url = request.POST.get('openid_url', None)    
 
70
    user_url = request.POST.get('openid_url', None)
65
71
    if not user_url:
66
 
        return render('openid_signin.html')
 
72
        return render('openid_signin.html', {'action': request.path})
 
73
    
 
74
    if xri.identifierScheme(user_url) == 'XRI' and getattr(
 
75
        settings, 'OPENID_DISALLOW_INAMES', False
 
76
        ):
 
77
        return failure(request, 'i-names are not supported')
67
78
    
68
79
    consumer = Consumer(request.session, DjangoOpenIDStore())
69
80
    try:
70
81
        auth_request = consumer.begin(user_url)
71
82
    except DiscoveryFailure:
72
 
        raise Http404, "Discovery failure"
 
83
        return failure(request, "The OpenID was invalid")
73
84
    
74
85
    # Add extension args (for things like simple registration)
75
86
    for name, value in extension_args.items():
103
114
    ]
104
115
    request.session['openids'].append(from_openid_response(openid_response))
105
116
    
106
 
    after = request.GET.get('after', '').strip()
107
 
    if not after or not is_valid_after_url(after):
108
 
        after = getattr(settings, 'OPENID_REDIRECT_AFTER', '/')
 
117
    next = request.GET.get('next', '').strip()
 
118
    if not next or not is_valid_next_url(next):
 
119
        next = getattr(settings, 'OPENID_REDIRECT_NEXT', '/')
109
120
    
110
 
    return HttpResponseRedirect(after)
 
121
    return HttpResponseRedirect(next)
111
122
 
112
123
def failure(request, message):
113
124
    return render('openid_failure.html', {
114
125
        'message': message
115
 
    }) # , context_instance = RequestContext(request))
 
126
    })
116
127
 
117
128
def signout(request):
118
 
    request.session.openids = []
119
 
    request.session.openid = None
 
129
    request.session['openids'] = []
120
130
    next = request.GET.get('next', '/')
 
131
    if not is_valid_next_url(next):
 
132
        next = '/'
121
133
    return HttpResponseRedirect(next)
 
134
 
 
135
# Logo from http://openid.net/login-bg.gif
 
136
# Embedded here for convenience; you should serve this as a static file
 
137
OPENID_LOGO_BASE_64 = """
 
138
R0lGODlhEAAQAMQAAO3t7eHh4srKyvz8/P5pDP9rENLS0v/28P/17tXV1dHEvPDw8M3Nzfn5+d3d
 
139
3f5jA97Syvnv6MfLzcfHx/1mCPx4Kc/S1Pf189C+tP+xgv/k1N3OxfHy9NLV1/39/f///yH5BAAA
 
140
AAAALAAAAAAQABAAAAVq4CeOZGme6KhlSDoexdO6H0IUR+otwUYRkMDCUwIYJhLFTyGZJACAwQcg
 
141
EAQ4kVuEE2AIGAOPQQAQwXCfS8KQGAwMjIYIUSi03B7iJ+AcnmclHg4TAh0QDzIpCw4WGBUZeikD
 
142
Fzk0lpcjIQA7
 
143
"""