commit b71e85314e729c2dccbc25d1d986e8cb187af996
Author: Serghei MIHAI <smihai@entrouvert.com>
Date:   Tue Feb 10 11:07:32 2015 +0100

    Client building refactored

diff --git a/ckanext/ozwillo_pyoidc/conf.py b/ckanext/ozwillo_pyoidc/conf.py
index 37486bd..e30d8e3 100644
--- a/ckanext/ozwillo_pyoidc/conf.py
+++ b/ckanext/ozwillo_pyoidc/conf.py
@@ -21,34 +21,20 @@ ME = {
     "response_types": ["code"]
 }
 
-BEHAVIOUR = {
-    "response_type": "code",
-    "scope": ["openid", "profile", "email", "address", "phone"],
-}
-
 ACR_VALUES = ["SAML"]
 
-# The keys in this dictionary are the OPs short userfriendly name
-# not the issuer (iss) name.
-
-CLIENTS = {
-    # The ones that support webfinger, OP discovery and client registration
-    # This is the default, any client that is not listed here is expected to
-    # support dynamic discovery and registration.
-    # Supports OP information lookup but not client registration
-    "ozwillo": {
-        "srv_discovery_url": "https://accounts.ozwillo-preprod.eu/",
-        "client_registration": {
-            "client_id": None,
-            "client_secret": None,
-            "redirect_uris": [],
-        },
-        "behaviour": {
-            "response_type": "code",
-            "scope": ["openid", "profile", "email"]
-        },
-        "allow": {
-            "issuer_mismatch": True
-        }
+CLIENT = {
+    "srv_discovery_url": "https://accounts.ozwillo-preprod.eu/",
+    "client_registration": {
+        "client_id": None,
+        "client_secret": None,
+        "redirect_uris": [],
+    },
+    "behaviour": {
+        "response_type": "code",
+        "scope": ["openid", "profile", "email"]
+    },
+    "allow": {
+        "issuer_mismatch": True
     }
 }
diff --git a/ckanext/ozwillo_pyoidc/oidc.py b/ckanext/ozwillo_pyoidc/oidc.py
index aa8c961..3d908af 100755
--- a/ckanext/ozwillo_pyoidc/oidc.py
+++ b/ckanext/ozwillo_pyoidc/oidc.py
@@ -1,4 +1,3 @@
-from oic.utils.http_util import Redirect
 from oic.exception import MissingAttribute
 from oic import oic
 from oic.oauth2 import rndstr, ErrorResponse
@@ -7,12 +6,11 @@ from oic.oic import RegistrationResponse
 from oic.oic import AuthorizationRequest
 from oic.utils.authn.client import CLIENT_AUTHN_METHOD
 
-__author__ = 'roland'
-
 import logging
 
 logger = logging.getLogger(__name__)
 
+import conf
 
 class OIDCError(Exception):
     pass
@@ -107,129 +105,70 @@ class Client(oic.Client):
 
         return userinfo
 
-
-class OIDCClients(object):
-    def __init__(self, config):
-        """
-
-        :param config: Imported configuration module
-        :return:
-        """
-        self.client = {}
-        self.client_cls = Client
-        self.config = config
-
-        for key, val in config.CLIENTS.items():
-            if key == "":
-                continue
-            else:
-                self.client[key] = self.create_client(**val)
-
-    def create_client(self, userid="", **kwargs):
-        """
-        Do an instantiation of a client instance
-
-        :param userid: An identifier of the user
-        :param: Keyword arguments
-            Keys are ["srv_discovery_url", "client_info", "client_registration",
-            "provider_info"]
-        :return: client instance
-        """
-
-        _key_set = set(kwargs.keys())
-        args = {}
-        for param in ["verify_ssl"]:
-            try:
-                args[param] = kwargs[param]
-            except KeyError:
-                pass
-            else:
-                _key_set.discard(param)
-
-        client = self.client_cls(client_authn_method=CLIENT_AUTHN_METHOD,
-                                 behaviour=kwargs["behaviour"], verify_ssl=self.config.VERIFY_SSL, **args)
-
-        # The behaviour parameter is not significant for the election process
-        _key_set.discard("behaviour")
-        for param in ["allow"]:
-            try:
-                setattr(client, param, kwargs[param])
-            except KeyError:
-                pass
-            else:
-                _key_set.discard(param)
-
-        if _key_set == set(["client_info"]):  # Everything dynamic
-            # There has to be a userid
-            if not userid:
-                raise MissingAttribute("Missing userid specification")
-
-            # Find the service that provides information about the OP
-            issuer = client.wf.discovery_query(userid)
-            # Gather OP information
-            _ = client.provider_config(issuer)
-            # register the client
-            _ = client.register(client.provider_info["registration_endpoint"],
-                                **kwargs["client_info"])
-        elif _key_set == set(["client_info", "srv_discovery_url"]):
-            # Ship the webfinger part
-            # Gather OP information
-            _ = client.provider_config(kwargs["srv_discovery_url"])
-            # register the client
-            _ = client.register(client.provider_info["registration_endpoint"],
-                                **kwargs["client_info"])
-        elif _key_set == set(["provider_info", "client_info"]):
-            client.handle_provider_config(
-                ProviderConfigurationResponse(**kwargs["provider_info"]),
-                kwargs["provider_info"]["issuer"])
-            _ = client.register(client.provider_info["registration_endpoint"],
-                                **kwargs["client_info"])
-        elif _key_set == set(["provider_info", "client_registration"]):
-            client.handle_provider_config(
-                ProviderConfigurationResponse(**kwargs["provider_info"]),
-                kwargs["provider_info"]["issuer"])
-            client.store_registration_info(RegistrationResponse(
-                **kwargs["client_registration"]))
-        elif _key_set == set(["srv_discovery_url", "client_registration"]):
-            _ = client.provider_config(kwargs["srv_discovery_url"])
-            client.store_registration_info(RegistrationResponse(
-                **kwargs["client_registration"]))
-        else:
-            raise Exception("Configuration error ?")
-
-        return client
-
-    def dynamic_client(self, userid):
-        client = self.client_cls(client_authn_method=CLIENT_AUTHN_METHOD,
-                                 verify_ssl=self.config.VERIFY_SSL)
-
-        issuer = client.wf.discovery_query(userid)
-        if issuer in self.client:
-            return self.client[issuer]
+def create_client(**kwargs):
+    """
+    kwargs = config.CLIENT.iteritems
+    """
+    _key_set = set(kwargs.keys())
+    args = {}
+    for param in ["verify_ssl"]:
+        try:
+            args[param] = kwargs[param]
+        except KeyError:
+            pass
         else:
-            # Gather OP information
-            _pcr = client.provider_config(issuer)
-            # register the client
-            _ = client.register(_pcr["registration_endpoint"],
-                                **self.config.CLIENTS[""]["client_info"])
-            try:
-                client.behaviour.update(**self.config.CLIENTS[""]["behaviour"])
-            except KeyError:
-                pass
+            _key_set.discard(param)
 
-            self.client[issuer] = client
-            return client
+    client = Client(client_authn_method=CLIENT_AUTHN_METHOD,
+                    behaviour=kwargs["behaviour"],
+                    verify_ssl=conf.VERIFY_SSL, **args)
 
-    def __getitem__(self, item):
-        """
-        Given a service or user identifier return a suitable client
-        :param item:
-        :return:
-        """
+    # The behaviour parameter is not significant for the election process
+    _key_set.discard("behaviour")
+    for param in ["allow"]:
         try:
-            return self.client[item]
+            setattr(client, param, kwargs[param])
         except KeyError:
-            return self.dynamic_client(item)
+            pass
+        else:
+            _key_set.discard(param)
+
+    if _key_set == set(["client_info"]):  # Everything dynamic
+        # There has to be a userid
+        if not userid:
+            raise MissingAttribute("Missing userid specification")
 
-    def keys(self):
-        return self.client.keys()
+        # Find the service that provides information about the OP
+        issuer = client.wf.discovery_query(userid)
+        # Gather OP information
+        _ = client.provider_config(issuer)
+        # register the client
+        _ = client.register(client.provider_info["registration_endpoint"],
+                            **kwargs["client_info"])
+    elif _key_set == set(["client_info", "srv_discovery_url"]):
+        # Ship the webfinger part
+        # Gather OP information
+        _ = client.provider_config(kwargs["srv_discovery_url"])
+        # register the client
+        _ = client.register(client.provider_info["registration_endpoint"],
+                            **kwargs["client_info"])
+    elif _key_set == set(["provider_info", "client_info"]):
+        client.handle_provider_config(
+            ProviderConfigurationResponse(**kwargs["provider_info"]),
+            kwargs["provider_info"]["issuer"])
+        _ = client.register(client.provider_info["registration_endpoint"],
+                            **kwargs["client_info"])
+    elif _key_set == set(["provider_info", "client_registration"]):
+        client.handle_provider_config(
+            ProviderConfigurationResponse(**kwargs["provider_info"]),
+            kwargs["provider_info"]["issuer"])
+        client.store_registration_info(RegistrationResponse(
+            **kwargs["client_registration"]))
+    elif _key_set == set(["srv_discovery_url", "client_registration"]):
+        _ = client.provider_config(kwargs["srv_discovery_url"])
+        client.store_registration_info(RegistrationResponse(
+            **kwargs["client_registration"]))
+    else:
+        raise Exception("Configuration error ?")
+
+    return client
diff --git a/ckanext/ozwillo_pyoidc/plugin.py b/ckanext/ozwillo_pyoidc/plugin.py
index afab907..8b2a8d8 100755
--- a/ckanext/ozwillo_pyoidc/plugin.py
+++ b/ckanext/ozwillo_pyoidc/plugin.py
@@ -9,7 +9,8 @@ import ckan.lib.base as base
 
 from pylons import config, request
 
-from oidc import OIDCClients
+import conf
+from oidc import create_client
 
 plugin_config_prefix = 'ckanext.ozwillo_pyoidc.'
 
@@ -51,7 +52,7 @@ class OzwilloPyoidcPlugin(plugins.SingletonPlugin):
         global CLIENT
         if 'organization_id' in session:
             g = model.Group.get(session['organization_id'])
-            conf.CLIENTS['ozwillo']['client_registration'].update({
+            conf.CLIENT['client_registration'].update({
                 'client_id': g._extras['client_id'].value,
                 'client_secret': g._extras['client_secret'].value,
                 'redirect_uris': [toolkit.url_for(host=request.host,
@@ -61,7 +62,7 @@ class OzwilloPyoidcPlugin(plugins.SingletonPlugin):
                                                   qualified=True)]
                 })
             log.info('registration info for organization "%s" set' % g.name)
-            CLIENT = OIDCClients(conf)['ozwillo']
+            CLIENT = create_client(**conf.CLIENT)
             url, ht_args = CLIENT.create_authn_request(session, conf.ACR_VALUES)
             if ht_args:
                 toolkit.request.headers.update(ht_args)
