Project

General

Profile

« Previous | Next » 

Revision b71e8531

Added by Serghei Mihai over 9 years ago

Client building refactored

View differences:

ckanext/ozwillo_pyoidc/conf.py
21 21
    "response_types": ["code"]
22 22
}
23 23

  
24
BEHAVIOUR = {
25
    "response_type": "code",
26
    "scope": ["openid", "profile", "email", "address", "phone"],
27
}
28

  
29 24
ACR_VALUES = ["SAML"]
30 25

  
31
# The keys in this dictionary are the OPs short userfriendly name
32
# not the issuer (iss) name.
33

  
34
CLIENTS = {
35
    # The ones that support webfinger, OP discovery and client registration
36
    # This is the default, any client that is not listed here is expected to
37
    # support dynamic discovery and registration.
38
    # Supports OP information lookup but not client registration
39
    "ozwillo": {
40
        "srv_discovery_url": "https://accounts.ozwillo-preprod.eu/",
41
        "client_registration": {
42
            "client_id": None,
43
            "client_secret": None,
44
            "redirect_uris": [],
45
        },
46
        "behaviour": {
47
            "response_type": "code",
48
            "scope": ["openid", "profile", "email"]
49
        },
50
        "allow": {
51
            "issuer_mismatch": True
52
        }
26
CLIENT = {
27
    "srv_discovery_url": "https://accounts.ozwillo-preprod.eu/",
28
    "client_registration": {
29
        "client_id": None,
30
        "client_secret": None,
31
        "redirect_uris": [],
32
    },
33
    "behaviour": {
34
        "response_type": "code",
35
        "scope": ["openid", "profile", "email"]
36
    },
37
    "allow": {
38
        "issuer_mismatch": True
53 39
    }
54 40
}
ckanext/ozwillo_pyoidc/oidc.py
1
from oic.utils.http_util import Redirect
2 1
from oic.exception import MissingAttribute
3 2
from oic import oic
4 3
from oic.oauth2 import rndstr, ErrorResponse
......
7 6
from oic.oic import AuthorizationRequest
8 7
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
9 8

  
10
__author__ = 'roland'
11

  
12 9
import logging
13 10

  
14 11
logger = logging.getLogger(__name__)
15 12

  
13
import conf
16 14

  
17 15
class OIDCError(Exception):
18 16
    pass
......
107 105

  
108 106
        return userinfo
109 107

  
110

  
111
class OIDCClients(object):
112
    def __init__(self, config):
113
        """
114

  
115
        :param config: Imported configuration module
116
        :return:
117
        """
118
        self.client = {}
119
        self.client_cls = Client
120
        self.config = config
121

  
122
        for key, val in config.CLIENTS.items():
123
            if key == "":
124
                continue
125
            else:
126
                self.client[key] = self.create_client(**val)
127

  
128
    def create_client(self, userid="", **kwargs):
129
        """
130
        Do an instantiation of a client instance
131

  
132
        :param userid: An identifier of the user
133
        :param: Keyword arguments
134
            Keys are ["srv_discovery_url", "client_info", "client_registration",
135
            "provider_info"]
136
        :return: client instance
137
        """
138

  
139
        _key_set = set(kwargs.keys())
140
        args = {}
141
        for param in ["verify_ssl"]:
142
            try:
143
                args[param] = kwargs[param]
144
            except KeyError:
145
                pass
146
            else:
147
                _key_set.discard(param)
148

  
149
        client = self.client_cls(client_authn_method=CLIENT_AUTHN_METHOD,
150
                                 behaviour=kwargs["behaviour"], verify_ssl=self.config.VERIFY_SSL, **args)
151

  
152
        # The behaviour parameter is not significant for the election process
153
        _key_set.discard("behaviour")
154
        for param in ["allow"]:
155
            try:
156
                setattr(client, param, kwargs[param])
157
            except KeyError:
158
                pass
159
            else:
160
                _key_set.discard(param)
161

  
162
        if _key_set == set(["client_info"]):  # Everything dynamic
163
            # There has to be a userid
164
            if not userid:
165
                raise MissingAttribute("Missing userid specification")
166

  
167
            # Find the service that provides information about the OP
168
            issuer = client.wf.discovery_query(userid)
169
            # Gather OP information
170
            _ = client.provider_config(issuer)
171
            # register the client
172
            _ = client.register(client.provider_info["registration_endpoint"],
173
                                **kwargs["client_info"])
174
        elif _key_set == set(["client_info", "srv_discovery_url"]):
175
            # Ship the webfinger part
176
            # Gather OP information
177
            _ = client.provider_config(kwargs["srv_discovery_url"])
178
            # register the client
179
            _ = client.register(client.provider_info["registration_endpoint"],
180
                                **kwargs["client_info"])
181
        elif _key_set == set(["provider_info", "client_info"]):
182
            client.handle_provider_config(
183
                ProviderConfigurationResponse(**kwargs["provider_info"]),
184
                kwargs["provider_info"]["issuer"])
185
            _ = client.register(client.provider_info["registration_endpoint"],
186
                                **kwargs["client_info"])
187
        elif _key_set == set(["provider_info", "client_registration"]):
188
            client.handle_provider_config(
189
                ProviderConfigurationResponse(**kwargs["provider_info"]),
190
                kwargs["provider_info"]["issuer"])
191
            client.store_registration_info(RegistrationResponse(
192
                **kwargs["client_registration"]))
193
        elif _key_set == set(["srv_discovery_url", "client_registration"]):
194
            _ = client.provider_config(kwargs["srv_discovery_url"])
195
            client.store_registration_info(RegistrationResponse(
196
                **kwargs["client_registration"]))
197
        else:
198
            raise Exception("Configuration error ?")
199

  
200
        return client
201

  
202
    def dynamic_client(self, userid):
203
        client = self.client_cls(client_authn_method=CLIENT_AUTHN_METHOD,
204
                                 verify_ssl=self.config.VERIFY_SSL)
205

  
206
        issuer = client.wf.discovery_query(userid)
207
        if issuer in self.client:
208
            return self.client[issuer]
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
209 119
        else:
210
            # Gather OP information
211
            _pcr = client.provider_config(issuer)
212
            # register the client
213
            _ = client.register(_pcr["registration_endpoint"],
214
                                **self.config.CLIENTS[""]["client_info"])
215
            try:
216
                client.behaviour.update(**self.config.CLIENTS[""]["behaviour"])
217
            except KeyError:
218
                pass
120
            _key_set.discard(param)
219 121

  
220
            self.client[issuer] = client
221
            return client
122
    client = Client(client_authn_method=CLIENT_AUTHN_METHOD,
123
                    behaviour=kwargs["behaviour"],
124
                    verify_ssl=conf.VERIFY_SSL, **args)
222 125

  
223
    def __getitem__(self, item):
224
        """
225
        Given a service or user identifier return a suitable client
226
        :param item:
227
        :return:
228
        """
126
    # The behaviour parameter is not significant for the election process
127
    _key_set.discard("behaviour")
128
    for param in ["allow"]:
229 129
        try:
230
            return self.client[item]
130
            setattr(client, param, kwargs[param])
231 131
        except KeyError:
232
            return self.dynamic_client(item)
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")
233 140

  
234
    def keys(self):
235
        return self.client.keys()
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
ckanext/ozwillo_pyoidc/plugin.py
9 9

  
10 10
from pylons import config, request
11 11

  
12
from oidc import OIDCClients
12
import conf
13
from oidc import create_client
13 14

  
14 15
plugin_config_prefix = 'ckanext.ozwillo_pyoidc.'
15 16

  
......
51 52
        global CLIENT
52 53
        if 'organization_id' in session:
53 54
            g = model.Group.get(session['organization_id'])
54
            conf.CLIENTS['ozwillo']['client_registration'].update({
55
            conf.CLIENT['client_registration'].update({
55 56
                'client_id': g._extras['client_id'].value,
56 57
                'client_secret': g._extras['client_secret'].value,
57 58
                'redirect_uris': [toolkit.url_for(host=request.host,
......
61 62
                                                  qualified=True)]
62 63
                })
63 64
            log.info('registration info for organization "%s" set' % g.name)
64
            CLIENT = OIDCClients(conf)['ozwillo']
65
            CLIENT = create_client(**conf.CLIENT)
65 66
            url, ht_args = CLIENT.create_authn_request(session, conf.ACR_VALUES)
66 67
            if ht_args:
67 68
                toolkit.request.headers.update(ht_args)

Also available in: Unified diff