Client building refactored

This commit is contained in:
Serghei Mihai 2015-02-10 11:07:32 +01:00
parent 1f01e54b90
commit b71e85314e
3 changed files with 82 additions and 156 deletions

View File

@ -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
}
}

View File

@ -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]
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
self.client[issuer] = client
return client
def __getitem__(self, item):
"""
Given a service or user identifier return a suitable client
:param item:
:return:
"""
def create_client(**kwargs):
"""
kwargs = config.CLIENT.iteritems
"""
_key_set = set(kwargs.keys())
args = {}
for param in ["verify_ssl"]:
try:
return self.client[item]
args[param] = kwargs[param]
except KeyError:
return self.dynamic_client(item)
pass
else:
_key_set.discard(param)
def keys(self):
return self.client.keys()
client = Client(client_authn_method=CLIENT_AUTHN_METHOD,
behaviour=kwargs["behaviour"],
verify_ssl=conf.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

View File

@ -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)