def random_client_id(length: int = 16, reserved: list = [], **kwargs): # create new id och secret client_id = rndstr(16) # cdb client_id MUST be unique! while client_id in reserved: client_id = rndstr(16) return client_id
def __init__( self, handler: TokenHandler, conf: Optional[dict] = None, sub_func: Optional[dict] = None, ): self.conf = conf or {} # these won't change runtime session_params = self.conf.get("session_params") or {} self._key = session_params.get("password") or rndstr(24) self._salt = session_params.get("salt") or rndstr(32) self.key = self.load_key() self.salt = self.load_key() self._init_db() self.token_handler = handler # this allows the subject identifier minters to be defined by someone # else then me. if sub_func is None: self.sub_func = { "public": public_id, "pairwise": pairwise_id, "ephemeral": ephemeral_id, } else: self.sub_func = sub_func if "public" not in sub_func: self.sub_func["public"] = public_id if "pairwise" not in sub_func: self.sub_func["pairwise"] = pairwise_id if "ephemeral" not in sub_func: self.sub_func["ephemeral"] = ephemeral_id
def __call__(self, session_id: Optional[str] = "", token_class: Optional[str] = "", **payload) -> str: """ Return a token. :param payload: Token information :return: """ if not token_class and self.token_class: token_class = self.token_class else: token_class = "authorization_code" if self.lifetime >= 0: exp = str(time_sans_frac() + self.lifetime) else: exp = "-1" # Live for ever tmp = "" rnd = "" while rnd == tmp: # Don't use the same random value again rnd = rndstr(32) # Ultimate length multiple of 16 return base64.b64encode( self.crypt.encrypt( lv_pack(rnd, token_class, session_id, exp).encode())).decode("utf-8")
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Those that use seed wants bytes but I can only store str. # seed _seed = kwargs.get("seed") or rndstr(32) self.seed = as_bytes(_seed)
def __init__(self, salt: Optional[str] = "", filename: Optional[str] = ""): if salt: self.salt = salt elif filename: if os.path.isfile(filename): self.salt = open(filename).read() elif not os.path.isfile(filename) and os.path.exists( filename ): # Not a file, Something else raise ConfigurationError("Salt filename points to something that is not a file") else: self.salt = rndstr(24) # May raise an exception fp = open(filename, "w") fp.write(self.salt) fp.close() else: self.salt = rndstr(24)
def __init__(self, key: Optional[str] = "", **kwargs): ImpExp.__init__(self) self.db = DLDict() for k, v in kwargs.items(): setattr(self, k, v) self.key = key or rndstr(24) self.crypt = Crypt(key)
def add_registration_api(self, cinfo, client_id, context): _rat = rndstr(32) cinfo["registration_access_token"] = _rat endpoint = self.server_get("endpoints") cinfo["registration_client_uri"] = "{}?client_id={}".format( endpoint["registration_read"].full_path, client_id) context.registration_access_token[_rat] = client_id
def authz_part2(self, request, session_id, **kwargs): """ After the authentication this is where you should end up :param request: The Authorization Request :param session_id: Session identifier :param kwargs: possible other parameters :return: A redirect to the redirect_uri of the client """ try: resp_info = self.post_authentication(request, session_id, **kwargs) except Exception as err: return self.error_response({}, "server_error", err) _context = self.server_get("endpoint_context") if "check_session_iframe" in _context.provider_info: salt = rndstr() try: authn_event = _context.session_manager.get_authentication_event( session_id) except KeyError: return self.error_response({}, "server_error", "No such session") else: if authn_event.is_valid() is False: return self.error_response({}, "server_error", "Authentication has timed out") _state = b64e( as_bytes(json.dumps({"authn_time": authn_event["authn_time"]}))) _session_cookie_content = _context.new_cookie( name=_context.cookie_handler.name["session_management"], state=as_unicode(_state), ) opbs_value = _session_cookie_content["value"] logger.debug( "compute_session_state: client_id=%s, origin=%s, opbs=%s, salt=%s", request["client_id"], resp_info["return_uri"], opbs_value, salt, ) _session_state = compute_session_state(opbs_value, salt, request["client_id"], resp_info["return_uri"]) if _session_cookie_content: if "cookie" in resp_info: resp_info["cookie"].append(_session_cookie_content) else: resp_info["cookie"] = [_session_cookie_content] resp_info["response_args"]["session_state"] = _session_state # Mix-Up mitigation resp_info["response_args"]["iss"] = _context.issuer resp_info["response_args"]["client_id"] = request["client_id"] return resp_info
def __init__( self, conf: Union[dict, OPConfiguration], keyjar: Optional[KeyJar] = None, cwd: Optional[str] = "", cookie_handler: Optional[Any] = None, httpc: Optional[Any] = None, ): OidcContext.__init__(self, conf, keyjar, entity_id=conf.get("issuer", "")) self.conf = conf # For my Dev environment self.cdb = {} self.jti_db = {} self.registration_access_token = {} # self.session_db = {} self.cwd = cwd # Default values, to be changed below depending on configuration # arguments for endpoints add-ons self.args = {} self.authn_broker = None self.authz = None self.cookie_handler = cookie_handler self.endpoint_to_authn_method = {} self.httpc = httpc or requests self.idtoken = None self.issuer = "" self.jwks_uri = None self.login_hint_lookup = None self.login_hint2acrs = None self.par_db = {} self.provider_info = {} self.scope2claims = SCOPE2CLAIMS self.session_manager = None self.sso_ttl = 14400 # 4h self.symkey = rndstr(24) self.template_handler = None self.token_args_methods = [] self.userinfo = None for param in [ "issuer", "sso_ttl", "symkey", "client_authn", # "id_token_schema", ]: try: setattr(self, param, conf[param]) except KeyError: pass self.th_args = get_token_handler_args(conf) # session db self._sub_func = {} self.do_sub_func() _handler = conf.get("template_handler") if _handler: self.template_handler = _handler else: _loader = conf.get("template_loader") if _loader is None: _template_dir = conf.get("template_dir") if _template_dir: _loader = Environment(loader=FileSystemLoader(_template_dir), autoescape=True) if _loader: self.template_handler = Jinja2TemplateHandler(_loader) # self.setup = {} _keys_conf = conf.get("keys") if _keys_conf: jwks_uri_path = _keys_conf["uri_path"] if self.issuer.endswith("/"): self.jwks_uri = "{}{}".format(self.issuer, jwks_uri_path) else: self.jwks_uri = "{}/{}".format(self.issuer, jwks_uri_path) for item in [ "cookie_handler", "authentication", "id_token", "scope2claims", ]: _func = getattr(self, "do_{}".format(item), None) if _func: _func() for item in ["login_hint2acrs"]: _func = getattr(self, "do_{}".format(item), None) if _func: _func() # which signing/encryption algorithms to use in what context self.jwx_def = {} # The HTTP clients request arguments _cnf = conf.get("httpc_params") if _cnf: self.httpc_params = get_http_params(_cnf) else: # Backward compatibility self.httpc_params = {"verify": conf.get("verify_ssl", True)} self.set_scopes_handler() self.dev_auth_db = None self.claims_interface = None
def encrypted_session_id(self, *args) -> str: rnd = rndstr(32) return base64.b64encode( self.crypt.encrypt(lv_pack( rnd, self.session_key(*args)).encode())).decode("utf-8")
def __init__(self, server_get, **kwargs): _csi = kwargs.get("check_session_iframe") if _csi and not _csi.startswith("http"): kwargs["check_session_iframe"] = add_path(server_get("endpoint_context").issuer, _csi) Endpoint.__init__(self, server_get, **kwargs) self.iv = as_bytes(rndstr(24))
def client_registration_setup(self, request, new_id=True, set_secret=True): try: request.verify() except (MessageException, ValueError) as err: logger.error("request.verify() on %s", request) return ResponseMessage(error="invalid_configuration_request", error_description="%s" % err) request.rm_blanks() try: self.match_client_request(request) except CapabilitiesMisMatch as err: return ResponseMessage( error="invalid_request", error_description="Don't support proposed %s" % err, ) _context = self.server_get("endpoint_context") if new_id: if self.kwargs.get("client_id_generator"): cid_generator = importer( self.kwargs["client_id_generator"]["class"]) cid_gen_kwargs = self.kwargs["client_id_generator"].get( "kwargs", {}) else: cid_generator = importer( "oidcop.oidc.registration.random_client_id") cid_gen_kwargs = {} client_id = cid_generator(reserved=_context.cdb.keys(), **cid_gen_kwargs) if "client_id" in request: del request["client_id"] else: client_id = request.get("client_id") if not client_id: raise ValueError("Missing client_id") _cinfo = {"client_id": client_id, "client_salt": rndstr(8)} if self.server_get("endpoint", "registration_read"): self.add_registration_api(_cinfo, client_id, _context) if new_id: _cinfo["client_id_issued_at"] = utc_time_sans_frac() client_secret = "" if set_secret: client_secret = self.add_client_secret(_cinfo, client_id, _context) logger.debug( "Stored client info in CDB under cid={}".format(client_id)) _context.cdb[client_id] = _cinfo _cinfo = self.do_client_registration( request, client_id, ignore=["redirect_uris", "policy_uri", "logo_uri", "tos_uri"], ) if isinstance(_cinfo, ResponseMessage): return _cinfo args = dict([(k, v) for k, v in _cinfo.items() if k in self.response_cls.c_param]) comb_uri(args) response = self.response_cls(**args) # Add the client_secret as a symmetric key to the key jar if client_secret: _context.keyjar.add_symmetric(client_id, str(client_secret)) logger.debug( "Stored updated client info in CDB under cid={}".format(client_id)) logger.debug("ClientInfo: {}".format(_cinfo)) _context.cdb[client_id] = _cinfo # Not all databases can be sync'ed if hasattr(_context.cdb, "sync") and callable(_context.cdb.sync): _context.cdb.sync() msg = "registration_response: {}" logger.info(msg.format(sanitize(response.to_dict()))) return response