예제 #1
0
파일: dynreg.py 프로젝트: atidev/pyoidc
    def registration_endpoint(self, request, environ, **kwargs):
        """

        :param request: The request
        :param authn: Client authentication information
        :param kwargs: extra keyword arguments
        :return: A Response instance
        """

        _request = RegistrationRequest().deserialize(request, "json")
        try:
            _request.verify()
        except InvalidRedirectUri as err:
            msg = ClientRegistrationError(error="invalid_redirect_uri",
                                          error_description="%s" % err)
            return BadRequest(msg.to_json(), content="application/json")
        except (MissingPage, VerificationError) as err:
            msg = ClientRegistrationError(error="invalid_client_metadata",
                                          error_description="%s" % err)
            return BadRequest(msg.to_json(), content="application/json")

        # authenticated client
        if self.authn_at_registration:
            try:
                _ = self.verify_client(environ, _request,
                                       self.authn_at_registration)
            except (AuthnFailure, UnknownAssertionType):
                return Unauthorized()

        client_id = self.create_new_client(_request)

        return self.client_info(client_id)
예제 #2
0
    def introspection_endpoint_(self, user, **kwargs):
        """
        The endpoint URI at which the resource server introspects an RPT
        presented to it by a client.
        """

        request = kwargs["request"]
        logger.debug("requestor: %s, request: %s" % (user, request))
        ir = IntrospectionRequest().from_json(request)
        adb = self.get_adb(kwargs["client_id"])
        try:
            try:
                # requestor = self.rpt[ir["token"]]["requestor"]
                perms = adb.permit.get_accepted_by_rpt(user, ir["token"])
            except KeyError:
                response = BadRequest()
            else:
                if perms:
                    irep = IntrospectionResponse(active=True,
                                                 exp=perms[0]["exp"],
                                                 permissions=perms)
                    logger.debug("response: %s" % irep.to_json())
                    response = Response(irep.to_json(),
                                        content="application/json")
                else:
                    logger.info("No permissions bound to this RPT")
                    response = BadRequest()
        except ToOld:
            logger.info("RPT expired")
            irep = IntrospectionResponse(valid=False)
            response = Response(irep.to_json(), content="application/json")
        except KeyError:
            response = BadRequest()

        return response
예제 #3
0
    def client_info_endpoint(self, method="GET", **kwargs):
        """
        Operations on this endpoint are switched through the use of different HTTP methods.

        :param method: HTTP method used for the request
        :param kwargs: keyword arguments
        :return: A Response instance
        """
        _query = compact(parse_qs(kwargs["query"]))
        try:
            _id = _query["client_id"]
        except KeyError:
            return BadRequest("Missing query component")

        if _id not in self.cdb:
            return Unauthorized()

        # authenticated client
        try:
            self.verify_client(
                kwargs["environ"], kwargs["request"], "bearer_header", client_id=_id
            )
        except (AuthnFailure, UnknownAssertionType):
            return Unauthorized()

        if method == "GET":
            return self.client_info(_id)
        elif method == "PUT":
            try:
                _request = self.server.message_factory.get_request_type(
                    "update_endpoint"
                )().from_json(kwargs["request"])
            except ValueError as err:
                return BadRequest(str(err))

            try:
                _request.verify()
            except InvalidRedirectUri as err:
                msg = ClientRegistrationError(
                    error="invalid_redirect_uri", error_description="%s" % err
                )
                return BadRequest(msg.to_json(), content="application/json")
            except (MissingPage, VerificationError) as err:
                msg = ClientRegistrationError(
                    error="invalid_client_metadata", error_description="%s" % err
                )
                return BadRequest(msg.to_json(), content="application/json")

            try:
                self.client_info_update(_id, _request)
                return self.client_info(_id)
            except ModificationForbidden:
                return Forbidden()
        elif method == "DELETE":
            try:
                del self.cdb[_id]
            except KeyError:
                return Unauthorized()
            else:
                return NoContent()
예제 #4
0
def webfinger(environ, events):
    query = parse_qs(environ["QUERY_STRING"])
    _op = environ["oic.op"]

    try:
        if query["rel"] != [OIC_ISSUER]:
            events.store(
                EV_CONDITION,
                State('webfinger_parameters',
                      ERROR,
                      message='parameter rel wrong value: {}'.format(
                          query['rel'])))
            return BadRequest('Parameter value error')
        else:
            resource = query["resource"][0]
    except KeyError as err:
        events.store(
            EV_CONDITION,
            State('webfinger_parameters',
                  ERROR,
                  message='parameter {} missing'.format(err)))
        resp = BadRequest("Missing parameter in request")
    else:
        wf = WebFinger()
        resp = Response(wf.response(subject=resource, base=_op.baseurl))
    return resp
예제 #5
0
파일: dynreg.py 프로젝트: programDEV/pyoidc
    def client_info_endpoint(self,
                             request,
                             environ,
                             method="GET",
                             query="",
                             **kwargs):
        """
        Operations on this endpoint are switched through the use of different
        HTTP methods

        :param request: The request
        :param authn: Client authentication information
        :param method: HTTP method used for the request
        :param query: The query part of the URL used, this is where the
            client_id is supposed to reside.
        :param kwargs: extra keyword arguments
        :return: A Response instance
        """

        _query = urlparse.parse_qs(query)
        try:
            _id = _query["client_id"][0]
        except KeyError:
            return BadRequest("Missing query component")

        try:
            assert _id in self.cdb
        except AssertionError:
            return Unauthorized()

        # authenticated client
        try:
            _ = self.verify_client(environ,
                                   request,
                                   "bearer_header",
                                   client_id=_id)
        except (AuthnFailure, UnknownAssertionType):
            return Unauthorized()

        if method == "GET":
            return self.client_info(_id)
        elif method == "PUT":
            try:
                _request = ClientUpdateRequest().from_json(request)
            except ValueError:
                return BadRequest()

            try:
                _request.verify()
            except InvalidRedirectUri, err:
                msg = ClientRegistrationError(error="invalid_redirect_uri",
                                              error_description="%s" % err)
                return BadRequest(msg.to_json(), content="application/json")
            except (MissingPage, VerificationError), err:
                msg = ClientRegistrationError(error="invalid_client_metadata",
                                              error_description="%s" % err)
                return BadRequest(msg.to_json(), content="application/json")
예제 #6
0
    def registration_endpoint(self, **kwargs):
        """
        Perform dynamic client registration.

        :param request: The request
        :param authn: Client authentication information
        :param kwargs: extra keyword arguments
        :return: A Response instance
        """
        _request = self.server.message_factory.get_request_type(
            "registration_endpoint"
        )().deserialize(kwargs["request"], "json")
        try:
            _request.verify(keyjar=self.keyjar)
        except InvalidRedirectUri as err:
            msg = ClientRegistrationError(
                error="invalid_redirect_uri", error_description="%s" % err
            )
            return BadRequest(msg.to_json(), content="application/json")
        except (MissingPage, VerificationError) as err:
            msg = ClientRegistrationError(
                error="invalid_client_metadata", error_description="%s" % err
            )
            return BadRequest(msg.to_json(), content="application/json")

        # If authentication is necessary at registration
        if self.authn_at_registration:
            try:
                self.verify_client(
                    kwargs["environ"], _request, self.authn_at_registration
                )
            except (AuthnFailure, UnknownAssertionType):
                return Unauthorized()

        client_restrictions = {}  # type: ignore
        if "parsed_software_statement" in _request:
            for ss in _request["parsed_software_statement"]:
                client_restrictions.update(self.consume_software_statement(ss))
            del _request["software_statement"]
            del _request["parsed_software_statement"]

        try:
            client_id = self.create_new_client(_request, client_restrictions)
        except CapabilitiesMisMatch as err:
            msg = ClientRegistrationError(
                error="invalid_client_metadata", error_description="%s" % err
            )
            return BadRequest(msg.to_json(), content="application/json")
        except RestrictionError as err:
            msg = ClientRegistrationError(
                error="invalid_client_metadata", error_description="%s" % err
            )
            return BadRequest(msg.to_json(), content="application/json")

        return self.client_info(client_id)
예제 #7
0
def exception_to_error_mesg(excep):
    if isinstance(excep, PyoidcError):
        if excep.content_type:
            if isinstance(excep.args, tuple):
                resp = BadRequest(excep.args[0], content=excep.content_type)
            else:
                resp = BadRequest(excep.args, content=excep.content_type)
        else:
            resp = BadRequest()
    else:
        err = ErrorResponse(error='service_error',
                            error_description='{}:{}'.format(
                                excep.__class__.__name__, excep.args))
        resp = BadRequest(err.to_json(), content='application/json')
    return resp
예제 #8
0
    def _complete_authz(self, user, areq, sid, **kwargs):
        _log_debug = logger.debug
        _log_debug("- in authenticated() -")

        # Do the authorization
        try:
            permission = self.authz(user, client_id=areq['client_id'])
            self.sdb.update(sid, "permission", permission)
        except Exception:
            raise

        _log_debug("response type: %s" % areq["response_type"])

        if self.sdb.is_revoked(sid):
            return self._error(error="access_denied",
                               descr="Token is revoked")

        info = self.create_authn_response(areq, sid)
        if isinstance(info, Response):
            return info
        else:
            aresp, fragment_enc = info

        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError) as err:
            return BadRequest("%s" % err)

        # Must not use HTTP unless implicit grant type and native application

        info = self.aresp_check(aresp, areq)
        if isinstance(info, Response):
            return info

        headers = []
        try:
            _kaka = kwargs["cookie"]
        except KeyError:
            pass
        else:
            if _kaka and self.cookie_name not in _kaka:  # Don't overwrite cookie
                headers.append(
                    self.cookie_func(user, typ="sso", ttl=self.sso_ttl))

        # Now about the response_mode. Should not be set if it's obvious
        # from the response_type. Knows about 'query', 'fragment' and
        # 'form_post'.

        if "response_mode" in areq:
            try:
                resp = self.response_mode(areq, fragment_enc, aresp=aresp,
                                          redirect_uri=redirect_uri,
                                          headers=headers)
            except InvalidRequest as err:
                return self._error("invalid_request", err)
            else:
                if resp is not None:
                    return resp

        return aresp, headers, redirect_uri, fragment_enc
예제 #9
0
    def _complete_authz(self, user, areq, sid, **kwargs):
        _log_debug = logger.debug
        _log_debug("- in authenticated() -")

        # Do the authorization
        try:
            permission = self.authz(user, client_id=areq['client_id'])
            self.sdb.update(sid, "permission", permission)
        except Exception:
            raise

        _log_debug("response type: %s" % areq["response_type"])

        if self.sdb.is_revoked(sid):
            return self._error(error="access_denied", descr="Token is revoked")

        info = self.create_authn_response(areq, sid)
        if isinstance(info, Response):
            return info
        else:
            aresp, fragment_enc = info

        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError), err:
            return BadRequest("%s" % err)
예제 #10
0
def safe(environ, start_response):
    _op = environ["oic.oas"]
    _srv = _op.server
    _log_info = _op.logger.info

    _log_info("- safe -")
    # _log_info("env: %s" % environ)
    # _log_info("handle: %s" % (handle,))

    try:
        _authz = environ["HTTP_AUTHORIZATION"]
        (_typ, code) = _authz.split(" ")
        assert _typ == "Bearer"
    except KeyError:
        resp = BadRequest("Missing authorization information")
        return resp(environ, start_response)

    try:
        _sinfo = _srv.sdb[code]
    except KeyError:
        resp = Unauthorized("Not authorized")
        return resp(environ, start_response)

    _info = "'%s' secrets" % _sinfo["sub"]
    resp = Response(_info)
    return resp(environ, start_response)
예제 #11
0
    def revocation_endpoint(self, authn='', request=None, **kwargs):
        """
        Implements RFC7009 allows a client to invalidate an access or refresh
        token.

        :param authn: Client Authentication information
        :param request: The revocation request
        :param kwargs:
        :return:
        """

        trr = TokenRevocationRequest().deserialize(request, "urlencoded")

        resp = self.get_token_info(authn, trr, 'revocation_endpoint')

        if isinstance(resp, Response):
            return resp
        else:
            client_id, token_type, _info = resp

        logger.info('{} token revocation: {}'.format(client_id, trr.to_dict()))

        try:
            self.sdb.token_factory[token_type].invalidate(trr['token'])
        except KeyError:
            return BadRequest()
        else:
            return Response('OK')
예제 #12
0
def webfinger(environ, start_response, session_info, trace, **kwargs):
    query = parse_qs(environ["QUERY_STRING"])

    # Find the identifier
    session_info["test_id"] = find_identifier(query["resource"][0])

    trace.info(HEADER % "WebFinger")
    trace.request(environ["QUERY_STRING"])
    trace.info("QUERY: %s" % (query, ))

    try:
        assert query["rel"] == [OIC_ISSUER]
        resource = query["resource"][0]
    except AssertionError:
        errmsg = "Wrong 'rel' value: %s" % query["rel"][0]
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    except KeyError:
        errmsg = "Missing 'rel' parameter in request"
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    else:
        wf = WebFinger()
        p = urlparse(resource)

        if p.scheme == "acct":
            l, _ = p.path.split("@")
            path = pathmap.IDMAP[l.lower()]
        else:  # scheme == http/-s
            try:
                path = pathmap.IDMAP[p.path[1:].lower()]
            except KeyError:
                path = None

        if path:
            _url = os.path.join(kwargs["op_arg"]["baseurl"],
                                session_info["test_id"], path[1:])
            resp = Response(wf.response(subject=resource, base=_url),
                            content="application/jrd+json")
        else:
            resp = BadRequest("Incorrect resource specification")

        trace.reply(resp.message)

    dump_log(session_info, trace)
    return resp(environ, start_response)
예제 #13
0
def _webfinger(provider, request, **kwargs):
    """Handle webfinger requests."""
    params = urlparse.parse_qs(request)
    if params["rel"][0] == OIC_ISSUER:
        wf = WebFinger()
        return Response(wf.response(params["resource"][0], provider.baseurl),
                        headers=[("Content-Type", "application/jrd+json")])
    else:
        return BadRequest("Incorrect webfinger.")
예제 #14
0
    def verify_endpoint(self, request="", cookie=None, **kwargs):
        _req = parse_qs(request)
        try:
            areq = parse_qs(_req["query"][0])
        except KeyError:
            return BadRequest('Could not verify endpoint')

        authn, acr = self.pick_auth(areq=areq)
        kwargs["cookie"] = cookie
        return authn.verify(_req, **kwargs)
def webfinger(environ, start_response, _):
    query = parse_qs(environ["QUERY_STRING"])
    try:
        assert query["rel"] == [OIC_ISSUER]
        resource = query["resource"][0]
    except KeyError:
        resp = BadRequest("Missing parameter in request")
    else:
        wf = WebFinger()
        resp = Response(wf.response(subject=resource, base=OAS.baseurl))
    return resp(environ, start_response)
예제 #16
0
def webfinger(environ, start_response, session_info, events, jlog, **kwargs):
    _query = session_info['parameters']
    events.store(EV_REQUEST, Operation("WebFinger", _query))

    try:
        assert _query["rel"] == [OIC_ISSUER]
        resource = _query["resource"][0]
    except AssertionError:
        errmsg = "Wrong 'rel' value: %s" % _query["rel"][0]
        events.store(EV_FAULT, errmsg)
        resp = BadRequest(errmsg)
    except KeyError:
        errmsg = "Missing 'rel' parameter in request"
        events.store(EV_FAULT, errmsg)
        resp = BadRequest(errmsg)
    else:
        wf = WebFinger()

        _url = os.path.join(kwargs["op_arg"]["baseurl"],
                            session_info['oper_id'], session_info["test_id"])

        _mesg = wf.response(subject=resource, base=_url)
        if session_info['test_id'] == 'rp-discovery-webfinger-http-href':
            _msg = json.loads(_mesg)
            _msg['links'][0]['href'] = _msg['links'][0]['href'].replace(
                'https', 'http')
            _mesg = json.dumps(_msg)
        elif session_info[
                'test_id'] == 'rp-discovery-webfinger-unknown-member':
            _msg = json.loads(_mesg)
            _msg['dummy'] = 'foobar'
            _mesg = json.dumps(_msg)

        resp = Response(_mesg, content="application/jrd+json")

        events.store(EV_RESPONSE, resp.message)

    jlog.info(resp2json(resp))

    dump_log(session_info, events)
    return resp(environ, start_response)
예제 #17
0
    def replace(self, qiss, qtag, info, path):
        # read entity configuration and replace if changed
        try:
            _js = json.loads(info)
        except Exception as err:
            return BadRequest(err)

        _js0 = self.read_conf(qiss, qtag)
        if _js == _js0:  # don't bother
            pass
        else:
            self.write(qiss, qtag, json.dumps(_js))

        return Response('OK')
예제 #18
0
def webfinger(environ, start_response, session, trace):
    query = parse_qs(environ["QUERY_STRING"])

    # Find the identifier
    session["test_id"] = find_identifier(query["resource"][0])

    trace.info(HEADER % "WebFinger")
    trace.request(environ["QUERY_STRING"])
    trace.info("QUERY: %s" % (query,))

    try:
        assert query["rel"] == [OIC_ISSUER]
        resource = query["resource"][0]
    except AssertionError:
        errmsg = "Wrong 'rel' value: %s" % query["rel"][0]
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    except KeyError:
        errmsg = "Missing 'rel' parameter in request"
        trace.error(errmsg)
        resp = BadRequest(errmsg)
    else:
        wf = WebFinger()
        p = urlparse(resource)
        if p.scheme == "acct":
            l, _ = p.path.split("@")
            path = pathmap.IDMAP[l]
        else:  # scheme == http/-s
            path = pathmap.IDMAP[p.path[1:]]

        _url = os.path.join(OP_ARG["baseurl"], session["test_id"], path[1:])
        resp = Response(wf.response(subject=resource, base=_url))

        trace.reply(resp.message)

    dump_log(session, trace)
    return resp(environ, start_response)
예제 #19
0
    def client_info(self, client_id):
        _cinfo = self.cdb[client_id].copy()
        if not valid_client_info(_cinfo):
            err = ErrorResponse(
                error="invalid_client", error_description="Invalid client secret"
            )
            return BadRequest(err.to_json(), content="application/json")

        try:
            _cinfo["redirect_uris"] = self._tuples_to_uris(_cinfo["redirect_uris"])
        except KeyError:
            pass

        msg = self.server.message_factory.get_response_type("update_endpoint")(**_cinfo)
        return Response(msg.to_json(), content="application/json")
예제 #20
0
    def client_info(self, client_id):
        _cinfo = self.cdb[client_id].copy()
        if not valid_client_info(_cinfo):
            err = ErrorResponse(error="invalid_client",
                                error_description="Invalid client secret")
            return BadRequest(err.to_json(), content="application/json")

        try:
            _cinfo["redirect_uris"] = self._tuples_to_uris(
                _cinfo["redirect_uris"])
        except KeyError:
            pass

        msg = ClientInfoResponse(**_cinfo)
        return Response(msg.to_json(), content="application/json")
예제 #21
0
    def get_token_info(self, authn, req, endpoint):
        """
        Parse token for information.

        :param authn:
        :param req:
        :return:
        """
        try:
            client_id = self.client_authn(self, req, authn)
        except FailedAuthentication as err:
            logger.error(err)
            error = TokenErrorResponse(error="unauthorized_client",
                                       error_description="%s" % err)
            return Response(error.to_json(),
                            content="application/json",
                            status="401 Unauthorized")

        logger.debug("{}: {} requesting {}".format(endpoint, client_id,
                                                   req.to_dict()))

        try:
            token_type = req["token_type_hint"]
        except KeyError:
            try:
                _info = self.sdb.token_factory["access_token"].get_info(
                    req["token"])
            except Exception:
                try:
                    _info = self.sdb.token_factory["refresh_token"].get_info(
                        req["token"])
                except Exception:
                    return self._return_inactive()
                else:
                    token_type = "refresh_token"
            else:
                token_type = "access_token"
        else:
            try:
                _info = self.sdb.token_factory[token_type].get_info(
                    req["token"])
            except Exception:
                return self._return_inactive()

        if not self.token_access(endpoint, client_id, _info):
            return BadRequest()

        return client_id, token_type, _info
예제 #22
0
파일: dynreg.py 프로젝트: programDEV/pyoidc
    def registration_endpoint(self, request, environ, **kwargs):
        """

        :param request: The request
        :param authn: Client authentication information
        :param kwargs: extra keyword arguments
        :return: A Response instance
        """

        _request = RegistrationRequest().deserialize(request, "json")
        try:
            _request.verify()
        except InvalidRedirectUri, err:
            msg = ClientRegistrationError(error="invalid_redirect_uri",
                                          error_description="%s" % err)
            return BadRequest(msg.to_json(), content="application/json")
예제 #23
0
    def get_token_info(self, authn, req, endpoint):
        """

        :param authn:
        :param req:
        :return:
        """
        try:
            client_id = self.client_authn(self, req, authn)
        except FailedAuthentication as err:
            logger.error(err)
            err = TokenErrorResponse(error="unauthorized_client",
                                     error_description="%s" % err)
            return Response(err.to_json(),
                            content="application/json",
                            status="401 Unauthorized")

        logger.debug('{}: {} requesting {}'.format(endpoint, client_id,
                                                   req.to_dict()))

        try:
            token_type = req['token_type_hint']
        except KeyError:
            try:
                _info = self.sdb.token_factory['access_token'].info(
                    req['token'])
            except KeyError:
                try:
                    _info = self.sdb.token_factory['refresh_token'].get_info(
                        req['token'])
                except KeyError:
                    raise
                else:
                    token_type = 'refresh_token'
            else:
                token_type = 'access_token'
        else:
            try:
                _info = self.sdb.token_factory[token_type].get_info(
                    req['token'])
            except KeyError:
                raise

        if not self.token_access(endpoint, client_id, _info):
            return BadRequest()

        return client_id, token_type, _info
예제 #24
0
파일: rp.py 프로젝트: simudream/oictest
def test(environ, session, path):
    _test = path[5:]
    session["flow_index"] = FLOW_SEQUENCE.index(_test)
    session["phase_index"] = 0
    session["start"] = 0
    session["trace"] = Trace()
    _op = resp = client = link = None
    try:
        query = parse_qs(environ["QUERY_STRING"])
    except KeyError:
        pass
    else:
        try:
            session["op"] = query["op"][0]
            try:
                assert session["op"] in SERVER_ENV["OP"]
                _op = session["op_conf"] = SERVER_ENV["OP"][session["op"]]
            except AssertionError:
                return BadRequest("OP chosen that is not configured")
        except KeyError:
            pass
    if _op:
        try:
            client = SERVER_ENV["OIC_CLIENT"][session["opkey"]]
        except KeyError:
            _key = rndstr()
            try:
                kwargs = {"deviate": _op["deviate"]}
            except KeyError:
                kwargs = {}
            client = create_client(_key, **kwargs)
            session["opkey"] = _key
            SERVER_ENV["OIC_CLIENT"][session["opkey"]] = client

        if _op["features"]["discovery"]:
            link = _op["provider"]["dynamic"]
            session["srv_discovery_url"] = link
        else:
            client.handle_provider_config(_op["provider"], session["op"])
    else:
        resp = Redirect("/")

    if resp:
        return resp
    else:
        return {"client": client, "link": link}
예제 #25
0
파일: rp.py 프로젝트: simudream/oictest
def uid(environ, session, path):
    query = parse_qs(environ["QUERY_STRING"])
    if "uid" in query:
        try:
            link = RP.find_srv_discovery_url(resource=query["uid"][0])
        except requests.ConnectionError:
            return ServiceError("Webfinger lookup failed, connection error")

        session["srv_discovery_url"] = link
        md5 = hashlib.md5()
        md5.update(link)
        opkey = base64.b16encode(md5.digest())
        client = create_client(opkey)
        SERVER_ENV["OIC_CLIENT"][opkey] = client
        session["opkey"] = opkey
        return {"client": client, "link": link}
    else:
        return BadRequest()
예제 #26
0
    def discovery_endpoint(self, request, handle=None, **kwargs):
        if isinstance(request, dict):
            request = DiscoveryRequest(**request)
        else:
            request = DiscoveryRequest().deserialize(request, "urlencoded")

        try:
            assert request["service"] == SWD_ISSUER
        except AssertionError:
            return BadRequest("Unsupported service")

        _response = DiscoveryResponse(locations=[self.baseurl])
        if self.signed_metadata_statements:
            _response.update(
                {'metadata_statements': self.signed_metadata_statements})

        headers = [("Cache-Control", "no-store")]

        return Response(_response.to_json(),
                        content="application/json",
                        headers=headers)
예제 #27
0
    def permission_registration_endpoint_(self, request, **kwargs):
        """
        The endpoint URI at which the resource server registers a
        client-requested permission with the authorization server.
        This is a proposed permission waiting for the user to accept it.

        :param request: The permission registration request
        :return: HTTP Response
        """

        adb = self.get_adb(kwargs['client_id'])
        prr = self.to_prr(request, kwargs['client_id'])
        if prr:
            _ticket = adb.ticket_factory.pack(aud=[kwargs['client_id']],
                                              type='ticket')
            logging.debug("Registering permission request: %s" % request)
            adb.permission_requests[_ticket] = prr
            resp = PermissionRegistrationResponse(ticket=_ticket)

            return Created(resp.to_json(), content="application/json")
        else:
            return BadRequest("Can't register permission for unknown resource")
예제 #28
0
파일: dynreg.py 프로젝트: programDEV/pyoidc
class Provider(provider.Provider):
    def __init__(self,
                 name,
                 sdb,
                 cdb,
                 authn_broker,
                 authz,
                 client_authn,
                 symkey="",
                 urlmap=None,
                 iv=0,
                 default_scope="",
                 ca_bundle=None,
                 seed="",
                 client_authn_methods=None,
                 authn_at_registration="",
                 client_info_url="",
                 secret_lifetime=86400):
        provider.Provider.__init__(self, name, sdb, cdb, authn_broker, authz,
                                   client_authn, symkey, urlmap, iv,
                                   default_scope, ca_bundle)

        self.endp.extend([RegistrationEndpoint, ClientInfoEndpoint])

        # dictionary of client authentication methods
        self.client_authn_methods = client_authn_methods
        if authn_at_registration:
            assert authn_at_registration in client_authn_methods
        self.authn_at_registration = authn_at_registration
        self.seed = seed
        self.client_info_url = client_info_url
        self.secret_lifetime = secret_lifetime

    # @staticmethod
    # def _uris_to_dict(uris):
    #     ruri = {}
    #     for uri in uris:
    #         base, query = urllib.splitquery(uri)
    #         if query:
    #             try:
    #                 ruri[base].append(urlparse.parse_qs(query))
    #             except KeyError:
    #                 ruri[base] = [urlparse.parse_qs(query)]
    #         else:
    #             ruri[base] = [""]
    #     return ruri
    #
    # @staticmethod
    # def _dict_to_uris(spec):
    #     _uri = []
    #     for url, qlist in spec.items():
    #         for query in qlist:
    #             if query:
    #                 _uri.append("%s?%s" % (url, query))
    #             else:
    #                 _uri.append(url)
    #     return _uri

    @staticmethod
    def _uris_to_tuples(uris):
        tup = []
        for uri in uris:
            base, query = urllib.splitquery(uri)
            if query:
                tup.append((base, query))
            else:
                tup.append((base, ""))
        return tup

    @staticmethod
    def _tuples_to_uris(items):
        _uri = []
        for url, query in items:
            if query:
                _uri.append("%s?%s" % (url, query))
            else:
                _uri.append(url)
        return _uri

    def create_new_client(self, request):
        """

        :param request: The Client registration request
        :return: The client_id
        """

        _cinfo = request.to_dict()

        # create new id and secret
        _id = rndstr(12)
        while _id in self.cdb:
            _id = rndstr(12)

        _cinfo["client_id"] = _id
        _cinfo["client_secret"] = secret(self.seed, _id)
        _cinfo["client_id_issued_at"] = utc_time_sans_frac()
        _cinfo["client_secret_expires_at"] = utc_time_sans_frac() + \
            self.secret_lifetime

        # If I support client info endpoint
        if ClientInfoEndpoint in self.endp:
            _cinfo["registration_access_token"] = rndstr(32)
            _cinfo["registration_client_uri"] = "%s%s?client_id=%s" % (
                self.client_info_url, ClientInfoEndpoint.etype, _id)

        if "redirect_uris" in request:
            _cinfo["redirect_uris"] = self._uris_to_tuples(
                request["redirect_uris"])

        self.cdb[_id] = _cinfo

        return _id

    def client_info(self, client_id):
        _cinfo = self.cdb[client_id].copy()
        try:
            _cinfo["redirect_uris"] = self._tuples_to_uris(
                _cinfo["redirect_uris"])
        except KeyError:
            pass

        msg = ClientInfoResponse(**_cinfo)
        return Response(msg.to_json(), content="application/json")

    def client_info_update(self, client_id, request):
        _cinfo = self.cdb[client_id].copy()
        try:
            _cinfo["redirect_uris"] = self._tuples_to_uris(
                _cinfo["redirect_uris"])
        except KeyError:
            pass

        for key, value in request.items():
            if key in ["client_secret", "client_id"]:
                # assure it's the same
                try:
                    assert value == _cinfo[key]
                except AssertionError:
                    raise ModificationForbidden("Not allowed to change")
            else:
                _cinfo[key] = value

        for key in _cinfo.keys():
            if key in [
                    "client_id_issued_at", "client_secret_expires_at",
                    "registration_access_token", "registration_client_uri"
            ]:
                continue
            if key not in request:
                del _cinfo[key]

        if "redirect_uris" in request:
            _cinfo["redirect_uris"] = self._uris_to_tuples(
                request["redirect_uris"])

        self.cdb[client_id] = _cinfo

    def verify_client(self, environ, areq, authn_method, client_id=""):
        """

        :param environ: WSGI environ
        :param areq: The request
        :param authn_method: client authentication method
        :return:
        """

        if not client_id:
            client_id = self.get_client_id(areq, environ["HTTP_AUTHORIZATION"])

        try:
            method = self.client_authn_methods[authn_method]
        except KeyError:
            raise UnSupported()
        return method(self).verify(environ, client_id=client_id)

    def registration_endpoint(self, request, environ, **kwargs):
        """

        :param request: The request
        :param authn: Client authentication information
        :param kwargs: extra keyword arguments
        :return: A Response instance
        """

        _request = RegistrationRequest().deserialize(request, "json")
        try:
            _request.verify()
        except InvalidRedirectUri, err:
            msg = ClientRegistrationError(error="invalid_redirect_uri",
                                          error_description="%s" % err)
            return BadRequest(msg.to_json(), content="application/json")
        except (MissingPage, VerificationError), err:
            msg = ClientRegistrationError(error="invalid_client_metadata",
                                          error_description="%s" % err)
            return BadRequest(msg.to_json(), content="application/json")
예제 #29
0
    def _complete_authz(self, user, areq, sid, **kwargs):
        _log_debug = logger.debug
        _log_debug("- in authenticated() -")

        # Do the authorization
        try:
            permission = self.authz(user, client_id=areq['client_id'])
            self.sdb.update(sid, "permission", permission)
        except Exception:
            raise

        _log_debug("response type: %s" % areq["response_type"])

        if self.sdb.is_revoked(sid):
            return error_response("access_denied", descr="Token is revoked")

        try:
            info = self.create_authn_response(areq, sid)
        except UnSupported as err:
            return error_response(*err.args)

        if isinstance(info, Response):
            return info
        else:
            aresp, fragment_enc = info

        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError) as err:
            return BadRequest("%s" % err)

        # Must not use HTTP unless implicit grant type and native application

        info = self.aresp_check(aresp, areq)
        if isinstance(info, Response):
            return info

        headers = []
        try:
            _kaka = kwargs["cookie"]
        except KeyError:
            pass
        else:
            if _kaka:
                if isinstance(_kaka, dict):
                    for name, val in _kaka.items():
                        _c = SimpleCookie()
                        _c[name] = val
                        _x = _c.output()
                        if PY2:
                            _x = str(_x)
                        headers.append(tuple(_x.split(": ", 1)))
                else:
                    _c = SimpleCookie()
                    _c.load(_kaka)
                    for x in _c.output().split('\r\n'):
                        if PY2:
                            x = str(x)
                        headers.append(tuple(x.split(": ", 1)))

                if self.cookie_name not in _kaka:  # Don't overwrite
                    header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl)
                    if header:
                        headers.append(header)
            else:
                header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl)
                if header:
                    headers.append(header)

        # Now about the response_mode. Should not be set if it's obvious
        # from the response_type. Knows about 'query', 'fragment' and
        # 'form_post'.

        if "response_mode" in areq:
            try:
                resp = self.response_mode(areq, fragment_enc, aresp=aresp,
                                          redirect_uri=redirect_uri,
                                          headers=headers)
            except InvalidRequest as err:
                return error_response("invalid_request", str(err))
            else:
                if resp is not None:
                    return resp

        return aresp, headers, redirect_uri, fragment_enc
예제 #30
0
    def auth_init(self, request, request_class=AuthorizationRequest):
        """

        :param request: The AuthorizationRequest
        :return:
        """
        logger.debug("Request: '%s'" % sanitize(request))
        # Same serialization used for GET and POST

        try:
            areq = self.server.parse_authorization_request(
                request=request_class, query=request)
        except (MissingRequiredValue, MissingRequiredAttribute,
                AuthzError) as err:
            logger.debug("%s" % err)
            areq = request_class()
            areq.lax = True
            if isinstance(request, dict):
                areq.from_dict(request)
            else:
                areq.deserialize(request, "urlencoded")
            try:
                redirect_uri = self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError, UnknownClient) as err:
                return error_response("invalid_request", "%s" % err)
            try:
                _rtype = areq["response_type"]
            except KeyError:
                _rtype = ["code"]
            try:
                _state = areq["state"]
            except KeyError:
                _state = ''

            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err, _state, _rtype)
        except KeyError:
            areq = request_class().deserialize(request, "urlencoded")
            # verify the redirect_uri
            try:
                self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError) as err:
                return error_response("invalid_request", "%s" % err)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.error(message)
            logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__))
            err = ErrorResponse(error='invalid_request',
                                error_description=str(err))
            return BadRequest(err.to_json(), content='application/json')

        if not areq:
            logger.debug("No AuthzRequest")
            return error_response("invalid_request", "Can not parse AuthzRequest")

        areq = self.filter_request(areq)

        if self.events:
            self.events.store('Protocol request', areq)

        try:
            _cinfo = self.cdb[areq['client_id']]
        except KeyError:
            logger.error(
                'Client ID ({}) not in client database'.format(
                    areq['client_id']))
            return error_response('unauthorized_client', 'unknown client')
        else:
            try:
                _registered = [set(rt.split(' ')) for rt in
                               _cinfo['response_types']]
            except KeyError:
                # If no response_type is registered by the client then we'll
                # code which it the default according to the OIDC spec.
                _registered = [{'code'}]

            _wanted = set(areq["response_type"])
            if _wanted not in _registered:
                return error_response("invalid_request", "Trying to use unregistered response_typ")

        logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),))
        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError, UnknownClient) as err:
            return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err))

        try:
            keyjar = self.keyjar
        except AttributeError:
            keyjar = ""

        try:
            # verify that the request message is correct
            areq.verify(keyjar=keyjar, opponent_id=areq["client_id"])
        except (MissingRequiredAttribute, ValueError,
                MissingRequiredValue) as err:
            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err)

        return {"areq": areq, "redirect_uri": redirect_uri}