def dynamic_client(self, issuer="", userid=""): client = self.client_cls( client_authn_method=CLIENT_AUTHN_METHOD, verify_ssl=self.verify_ssl, **self.jwks_info ) if userid: try: issuer = client.wf.discovery_query(userid) except AttributeError: wf = WebFinger(httpd=client) issuer = wf.discovery_query(userid) if not issuer: raise OAuth2Error("Missing issuer") logger.info("issuer: {}".format(issuer)) if issuer in self.client: return self.client[issuer] else: # Gather OP information _pcr = client.provider_config(issuer) logger.info("Provider info: {}".format(sanitize(_pcr.to_dict()))) issuer = _pcr["issuer"] # So no hickup later about trailing '/' # register the client _cinfo = self.config.CLIENTS[""]["client_info"] reg_args = copy.copy(_cinfo) h = hashlib.sha256(self.seed) h.update(issuer.encode("utf8")) # issuer has to be bytes base_urls = _cinfo["redirect_uris"] reg_args["redirect_uris"] = [ u.format(base=self.base_url, iss=h.hexdigest()) for u in base_urls ] try: reg_args["post_logout_redirect_uris"] = [ u.format(base=self.base_url, iss=h.hexdigest()) for u in reg_args["post_logout_redirect_uris"] ] except KeyError: pass self.get_path(reg_args["redirect_uris"], issuer) if client.jwks_uri: reg_args["jwks_uri"] = client.jwks_uri rr = client.register(_pcr["registration_endpoint"], **reg_args) msg = "Registration response: {}" logger.info(msg.format(sanitize(rr.to_dict()))) try: client.behaviour.update(**self.config.CLIENTS[""]["behaviour"]) except KeyError: pass self.client[issuer] = client return client
def dynamic_client(self, issuer='', userid=''): client = self.client_cls(client_authn_method=CLIENT_AUTHN_METHOD, verify_ssl=self.verify_ssl, **self.jwks_info) if userid: try: issuer = client.wf.discovery_query(userid) except AttributeError: wf = WebFinger(httpd=client) issuer = wf.discovery_query(userid) if not issuer: raise OAuth2Error('Missing issuer') logger.info('issuer: {}'.format(issuer)) if issuer in self.client: return self.client[issuer] else: # Gather OP information _pcr = client.provider_config(issuer) logger.info('Provider info: {}'.format(sanitize(_pcr.to_dict()))) issuer = _pcr['issuer'] # So no hickup later about trailing '/' # register the client _cinfo = self.config.CLIENTS[""]["client_info"] reg_args = copy.copy(_cinfo) h = hashlib.sha256(self.seed) h.update(issuer.encode('utf8')) # issuer has to be bytes base_urls = _cinfo["redirect_uris"] reg_args['redirect_uris'] = [ u.format(base=self.base_url, iss=h.hexdigest()) for u in base_urls] try: reg_args['post_logout_redirect_uris'] = [ u.format(base=self.base_url, iss=h.hexdigest()) for u in reg_args['post_logout_redirect_uris'] ] except KeyError: pass self.get_path(reg_args['redirect_uris'], issuer) if client.jwks_uri: reg_args['jwks_uri'] = client.jwks_uri rr = client.register(_pcr["registration_endpoint"], **reg_args) msg = 'Registration response: {}' logger.info(msg.format(sanitize(rr.to_dict()))) try: client.behaviour.update(**self.config.CLIENTS[""]["behaviour"]) except KeyError: pass self.client[issuer] = client return client
def register_first_time(self, name: str, provider: config.ProviderConfig) -> None: """ Registers a client or reads the configuration from the registration endpoint If registration_url is present in the configuration file, then it will try to read the configuration using the registration_token. If configuration_url is present in the configuration file, it will try to set the configuration using the registration endpoint dynamically received with the well-known location url (configuration_url) """ client = oic.oic.Client(client_authn_method=CLIENT_AUTHN_METHOD) registration_response: RegistrationResponse try: if provider.registration_url and provider.registration_token: provider_info = client.provider_config( provider['configuration_url']) # Only read configuration registration_response = client.registration_read( url=provider['registration_url'], registration_access_token=provider['registration_token']) args = dict() args['redirect_uris'] = registration_response['redirect_uris'] elif provider.configuration_url and provider.configuration_token: assert self.cfg.proxy is not None provider_info = client.provider_config( provider['configuration_url']) redirect_uris = provider.redirect_uris if provider.redirect_uris else self.cfg.proxy[ 'redirect_uris'] args = { "redirect_uris": redirect_uris, "contacts": self.cfg.proxy['contacts'] } registration_response = client.register( provider_info["registration_endpoint"], registration_token=provider['configuration_token'], **args) else: raise arpoc.exceptions.OIDCProxyException( "Error in the configuration file") except oic.exception.RegistrationError: LOGGING.warning("Provider %s returned an error on registration", name) LOGGING.debug("Seems to be permament, so not retrying") return except (requests.exceptions.MissingSchema, requests.exceptions.InvalidSchema, requests.exceptions.InvalidURL): raise arpoc.exceptions.OIDCProxyException( "Error in the configuration file") self.__oidc_provider[name] = client self.__oidc_provider[name].redirect_uris = args["redirect_uris"] self._secrets[name] = registration_response.to_dict()