Example #1
0
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
Example #2
0
    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
Example #3
0
    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")
Example #4
0
    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)
Example #5
0
 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)
Example #6
0
    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)
Example #7
0
    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
Example #8
0
    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
Example #10
0
 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")
Example #11
0
 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))
Example #12
0
    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