summaryrefslogtreecommitdiff
path: root/baserock_openid_provider/openid_provider/utils.py
blob: dc0c714fab6cc9589b43bf692aaec4922f8fd4e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding: utf-8 -*- vim: set et ts=4 sw=4 :
# some code from http://www.djangosnippets.org/snippets/310/ by simon
# and from examples/djopenid from python-openid-2.2.4
from hashlib import sha1
from openid_provider import conf
from openid.extensions import ax, sreg
from openid.server.server import Server, BROWSER_REQUEST_MODES
from openid.server.trustroot import verifyReturnTo
from openid.yadis.discover import DiscoveryFailure
from openid.fetchers import HTTPFetchingError

from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
from django.http import HttpResponse
from django.shortcuts import render_to_response

from importlib import import_module

import logging

logger = logging.getLogger(__name__)

def import_module_attr(path):
    package, module = path.rsplit('.', 1)
    return getattr(import_module(package), module)

def get_username(u):
    if hasattr(u, 'get_username'):
        return u.get_username()
    return u.username

def get_default_sreg_data(request, orequest):
    return {
        'email': request.user.email,
        'nickname': get_username(request.user),
        'fullname': request.user.get_full_name(),
    }

def get_default_ax_data(request, orequest):
    return {
        'http://axschema.org/contact/email': request.user.email,
        'http://axschema.org/namePerson': request.user.get_full_name(),
        'http://axschema.org/namePerson/friendly': get_username(request.user),
        'http://axschema.org/namePerson/first': request.user.first_name,
        'http://axschema.org/namePerson/last': request.user.last_name,
    }

def add_sreg_data(request, orequest, oresponse):
    callback = get_sreg_callback()
    if callback is None or not callable(callback):
        return
    sreg_data = callback(request, orequest)
    sreg_req = sreg.SRegRequest.fromOpenIDRequest(orequest)
    sreg_resp = sreg.SRegResponse.extractResponse(sreg_req, sreg_data)
    oresponse.addExtension(sreg_resp)

def add_ax_data(request, orequest, oresponse):
    callback = get_ax_callback()
    if callback is None or not callable(callback):
        return
    ax_data = callback(request, orequest)
    ax_req = ax.FetchRequest.fromOpenIDRequest(orequest)
    ax_resp = ax.FetchResponse(ax_req)
    if ax_req is not None:
        for attr in ax_req.getRequiredAttrs():
            value = ax_data.get(attr, None)
            if value is not None:
                ax_resp.addValue(attr, value)
    oresponse.addExtension(ax_resp)

def get_sreg_callback():
    try:
        return import_module_attr(conf.SREG_DATA_CALLBACK)
    except (ImportError, AttributeError):
        return None

def get_ax_callback():
    try:
        return import_module_attr(conf.AX_DATA_CALLBACK)
    except (ImportError, AttributeError):
        return None

def get_store(request):
    try:
        store_class = import_module_attr(conf.STORE)
    except ImportError:
        raise ImproperlyConfigured(
            "OpenID store %r could not be imported" % conf.STORE)
    # The FileOpenIDStore requires a path to save the user files.
    if conf.STORE == 'openid.store.filestore.FileOpenIDStore':
        return store_class(conf.FILESTORE_PATH)
    return store_class()

def trust_root_validation(orequest):
    """
    OpenID specs 9.2.1: using realm for return url verification
    """
    try:
        return verifyReturnTo(
            orequest.trust_root, orequest.return_to) and "Valid" or "Invalid"
    except HTTPFetchingError:
        return "Unreachable"
    except DiscoveryFailure:
        return "DISCOVERY_FAILED"

def get_trust_session_key(orequest):
    return 'OPENID_' + sha1(
        orequest.trust_root + orequest.return_to).hexdigest()

def prep_response(request, orequest, oresponse, server=None):
    # Convert a webresponse from the OpenID library in to a Django HttpResponse

    if not server:
        server = Server(get_store(request),
            op_endpoint=request.build_absolute_uri(
                reverse('openid-provider-root')))
    webresponse = server.encodeResponse(oresponse)
    if webresponse.code == 200 and orequest.mode in BROWSER_REQUEST_MODES:
        response = render_to_response('openid_provider/response.html', {
            'body': webresponse.body,
        }, context_instance=RequestContext(request))
        logger.debug('rendering browser response')
    else:
        response = HttpResponse(webresponse.body)
        response.status_code = webresponse.code
        for key, value in webresponse.headers.items():
            response[key] = value
        logger.debug('rendering raw response')
    return response