summaryrefslogtreecommitdiff
path: root/coip/apps/saml2/views.py
blob: 06272c1e690d27aba73a5191d929cbe441a4213a (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
'''
Created on Apr 2, 2012

@author: leifj
'''

from saml2 import server, BINDING_SOAP
from saml2 import soap
from saml2 import config
import logging
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseBadRequest
from saml2.metadata import entity_descriptor
from saml2.saml import NAME_FORMAT_URI
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from saml2.request import AttributeQuery

def get_full_path(request,path=None):
    if path == None:
        path = request.path
    full_path = ('http', ('', 's')[request.is_secure()], '://', request.META['HTTP_HOST'], path)
    return ''.join(full_path)

def _config(request):
    host = request.get_host().replace(":","-")
    c = {
            "entityid" : get_full_path(request,"/saml2/entity"),
            "description": "COIP",
            "service": {
                "aa": {
                    "name" : "COIP",
                    "endpoints" : {
                        "attribute_service" : [(get_full_path(request,"/saml2/aq"), BINDING_SOAP)],
                    },
                    "policy": {
                        "default": {
                            "lifetime": {"minutes":15},
                            "attribute_restrictions": None, # means all I have
                            "name_form": NAME_FORMAT_URI
                        },
                    },
                    "subject_data": ("dict", {}),
                }
            },
            "debug" : 1,
            "key_file" : "%s/%s.key" % (settings.SSL_KEY_DIR,host),
            "cert_file" : "%s/%s.crt" % (settings.SSL_CRT_DIR,host),
            "attribute_map_dir" : "%s/saml2/attributemaps" % settings.BASE_DIR,
            "metadata" : {
                "local": ["%s/saml2/metadata/sp.xml" % settings.BASE_DIR],
            },
            "organization": {
                "display_name": "COIP on %s" % host,
                "name": "COIP on %s" % host,
                "url": get_full_path(request,"/"),
            },
         }
    return c

def _aa_reply(aa, aq, user, sp_entityid):
    consumer_url = aa.metadata.consumer_url(aq.issuer.text)
    in_response_to = aq.id
    name_id = aq.subject.name_id

    logging.info("name_id: %s" % name_id)
    return  aa.do_aa_response(in_response_to, 
                              consumer_url,
                              sp_entityid,
                              identity=user,
                              name_id=name_id,
                              issuer=aa.conf.entityid)

def metadata(request):
    cnf = config.Config().load(_config(request), metadata_construction=True)
    ed = entity_descriptor(cnf, 0)
    return HttpResponse(content=ed,content_type="text/xml")

def parse_attribute_query(aa, xml_string, decode=True):
        """ Parse an attribute query
        
        :param xml_string: The Attribute Query as an XML string
        :param decode: Whether the xmlstring is base64encoded and zipped
        :return: 3-Tuple containing:
            subject - identifier of the subject
            attribute - which attributes that the requestor wants back
            query - the whole query
        """
        receiver_addresses = aa.conf.endpoint("attribute_service")
        attribute_query = AttributeQuery( aa.sec, receiver_addresses)
        logging.debug(xml_string)
        attribute_query = attribute_query.loads(xml_string, decode=decode)
        attribute_query = attribute_query.verify()
        logging.info(repr(attribute_query))
        #logging.info("KEYS: %s" % attribute_query.message.keys())
        # Subject is described in the a saml.Subject instance
        subject = attribute_query.subject_id()
        attribute = attribute_query.attribute()

        return subject, attribute, attribute_query.message

@csrf_exempt
def aq(request):
    if request.method == 'POST':
        cnf = config.Config().load(_config(request))
        cnf.context = 'aa'
        aa = server.Server(config=cnf, log=logging, debug=1, stype="aa")
        request_xml = soap.parse_soap_enveloped_saml_attribute_query(request.raw_post_data)
        logging.debug(request_xml)
        (subject, attribute, aq) = parse_attribute_query(aa,request_xml,True)
        sp_entityid = aq.issuer.text
        
        claims = {}
        try:
            logging.debug("Subject: %s" % subject.text)
            user = User.objects.get(username=subject.text)
            p = user.get_profile()
            claims = {'uid': user.username,'displayName': p.display_name}
        except Exception,exc:
            logging.debug(exc)
            pass
        
        aa_response = _aa_reply(aa, aq, claims, sp_entityid)
        xml = soap.make_soap_enveloped_saml_thingy(aa_response)
        logging.debug(xml)
        return HttpResponse(content=xml, content_type="application/soap+xml")
    else:
        return HttpResponseBadRequest("<html><head><title>No</title></head><body><h1>Bad Request</h1><p>Go sell crazy someplace else, we're all stocked up here!</p></body></html>")