Project

General

Profile

Download (6.27 KB) Statistics
| Branch: | Tag: | Revision:

oidc / ckanext / ozwillo_pyoidc / oidc.py @ 880b5def

1
from oic.exception import MissingAttribute
2
from oic import oic
3
from oic.oauth2 import rndstr, ErrorResponse
4
from oic.oic import ProviderConfigurationResponse, AuthorizationResponse
5
from oic.oic import RegistrationResponse
6
from oic.oic import AuthorizationRequest
7
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
8

    
9
import logging
10

    
11
logger = logging.getLogger(__name__)
12

    
13
import conf
14

    
15
class OIDCError(Exception):
16
    pass
17

    
18

    
19
class Client(oic.Client):
20
    def __init__(self, client_id=None, ca_certs=None,
21
                 client_prefs=None, client_authn_method=None, keyjar=None,
22
                 verify_ssl=True, behaviour=None):
23
        oic.Client.__init__(self, client_id, ca_certs, client_prefs,
24
                            client_authn_method, keyjar, verify_ssl)
25
        if behaviour:
26
            self.behaviour = behaviour
27

    
28
    def create_authn_request(self, session, acr_value=None):
29
        session["state"] = rndstr()
30
        session["nonce"] = rndstr()
31
        request_args = {
32
            "response_type": self.behaviour["response_type"],
33
            "scope": self.behaviour["scope"],
34
            "state": session["state"],
35
            # "nonce": session["nonce"],
36
            "redirect_uri": self.registration_response["redirect_uris"][0]
37
        }
38

    
39
        if acr_value is not None:
40
            request_args["acr_values"] = acr_value
41

    
42
        cis = self.construct_AuthorizationRequest(request_args=request_args)
43
        logger.debug("request: %s" % cis)
44

    
45
        url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis,
46
                                                    method="GET",
47
                                                    request_args=request_args)
48

    
49
        logger.debug("body: %s" % body)
50
        logger.info("URL: %s" % url)
51
        logger.debug("ht_args: %s" % ht_args)
52

    
53
        return str(url), ht_args
54

    
55
    def callback(self, response):
56
        """
57
        This is the method that should be called when an AuthN response has been
58
        received from the OP.
59

    
60
        :param response: The URL returned by the OP
61
        :return:
62
        """
63
        authresp = self.parse_response(AuthorizationResponse, response,
64
                                       sformat="dict", keyjar=self.keyjar)
65

    
66
        if isinstance(authresp, ErrorResponse):
67
            return OIDCError("Access denied")
68

    
69
        try:
70
            self.id_token[authresp["state"]] = authresp["id_token"]
71
        except KeyError:
72
            pass
73

    
74
        if self.behaviour["response_type"] == "code":
75
            # get the access token
76
            try:
77
                args = {
78
                    "grant_type": "authorization_code",
79
                    "code": authresp["code"],
80
                    "redirect_uri": self.registration_response[
81
                        "redirect_uris"][0],
82
                    "client_id": self.client_id,
83
                    "client_secret": self.client_secret
84
                }
85

    
86
                atresp = self.do_access_token_request(
87
                    scope="openid", state=authresp["state"], request_args=args,
88
                    authn_method=self.registration_response["token_endpoint_auth_method"])
89
            except Exception as err:
90
                logger.error("%s" % err)
91
                raise
92

    
93
            if isinstance(atresp, ErrorResponse):
94
                raise OIDCError("Invalid response %s." % atresp["error"])
95

    
96
        inforesp = self.do_user_info_request(state=authresp["state"],
97
                                             behavior='use_authorization_header')
98

    
99
        if isinstance(inforesp, ErrorResponse):
100
            raise OIDCError("Invalid response %s." % inforesp["error"])
101

    
102
        userinfo = inforesp.to_dict()
103

    
104
        logger.debug("UserInfo: %s" % inforesp)
105

    
106
        return userinfo
107

    
108
def create_client(**kwargs):
109
    """
110
    kwargs = config.CLIENT.iteritems
111
    """
112
    _key_set = set(kwargs.keys())
113
    args = {}
114
    for param in ["verify_ssl"]:
115
        try:
116
            args[param] = kwargs[param]
117
        except KeyError:
118
            pass
119
        else:
120
            _key_set.discard(param)
121

    
122
    client = Client(client_authn_method=CLIENT_AUTHN_METHOD,
123
                    behaviour=kwargs["behaviour"],
124
                    verify_ssl=conf.VERIFY_SSL, **args)
125

    
126
    # The behaviour parameter is not significant for the election process
127
    _key_set.discard("behaviour")
128
    for param in ["allow"]:
129
        try:
130
            setattr(client, param, kwargs[param])
131
        except KeyError:
132
            pass
133
        else:
134
            _key_set.discard(param)
135

    
136
    if _key_set == set(["client_info"]):  # Everything dynamic
137
        # There has to be a userid
138
        if not userid:
139
            raise MissingAttribute("Missing userid specification")
140

    
141
        # Find the service that provides information about the OP
142
        issuer = client.wf.discovery_query(userid)
143
        # Gather OP information
144
        _ = client.provider_config(issuer)
145
        # register the client
146
        _ = client.register(client.provider_info["registration_endpoint"],
147
                            **kwargs["client_info"])
148
    elif _key_set == set(["client_info", "srv_discovery_url"]):
149
        # Ship the webfinger part
150
        # Gather OP information
151
        _ = client.provider_config(kwargs["srv_discovery_url"])
152
        # register the client
153
        _ = client.register(client.provider_info["registration_endpoint"],
154
                            **kwargs["client_info"])
155
    elif _key_set == set(["provider_info", "client_info"]):
156
        client.handle_provider_config(
157
            ProviderConfigurationResponse(**kwargs["provider_info"]),
158
            kwargs["provider_info"]["issuer"])
159
        _ = client.register(client.provider_info["registration_endpoint"],
160
                            **kwargs["client_info"])
161
    elif _key_set == set(["provider_info", "client_registration"]):
162
        client.handle_provider_config(
163
            ProviderConfigurationResponse(**kwargs["provider_info"]),
164
            kwargs["provider_info"]["issuer"])
165
        client.store_registration_info(RegistrationResponse(
166
            **kwargs["client_registration"]))
167
    elif _key_set == set(["srv_discovery_url", "client_registration"]):
168
        _ = client.provider_config(kwargs["srv_discovery_url"])
169
        client.store_registration_info(RegistrationResponse(
170
            **kwargs["client_registration"]))
171
    else:
172
        raise Exception("Configuration error ?")
173

    
174
    return client
(3-3/4)