Esempio n. 1
0
    def begin(self, environ, start_response):
        """ Begin the OAuth2 flow

        :param environ: The WSGI environment
        :param start_response: The function to start the response process
        :return: A URL to which the user should be redirected
        """

        LOG_DEBUG("- begin -")

        # Store the request and the redirect uri used
        _path = http_util.geturl(environ, False, False)
        self.redirect_uris = ["%s%s" % (_path, self.authz_page)]
        self._request = http_util.geturl(environ)

        # Put myself in the dictionary of sessions, keyed on session-id
        if not self.seed:
            self.seed = rndstr()

        sid = stateID(_path, self.seed)
        self.state = sid
        self.grant[sid] = Grant(seed=self.seed)
        self._backup(sid)
        self.sdb["seed:%s" % self.seed] = sid

        location = self.request_info(AuthorizationRequest,
                                     method="GET", scope=self.scope,
                                     request_args={"state": sid})[0]


        LOG_DEBUG("Redirecting to: %s" % (location,))

        return location
Esempio n. 2
0
def test_geturl():
    environ = {
        "wsgi.url_scheme": "http",
        "SERVER_NAME": "example.com",
        "SERVER_PORT": "80",
        "SCRIPT_NAME": "/foo",
        "PATH_INFO": "/bar",
        "QUERY_STRING": "baz=xyz"
    }

    assert geturl(environ) == "http://example.com/foo/bar?baz=xyz"
Esempio n. 3
0
def test_geturl():
    environ = {
        "wsgi.url_scheme": "http",
        "SERVER_NAME": "example.com",
        "SERVER_PORT": "80",
        "SCRIPT_NAME": "/foo",
        "PATH_INFO": "/bar",
        "QUERY_STRING": "baz=xyz"
    }

    assert geturl(environ) == "http://example.com/foo/bar?baz=xyz"
Esempio n. 4
0
    def verify_client(self, environ, areq):
        try:
            _token = self._bearer_auth(environ)
            if _token in self.cdb:
                return True
        except AuthnFailure:
            pass

        if areq["client_id"] not in self.cdb:
            return False

        if "client_secret" in areq: # client_secret_post
            identity = areq["client_id"]
            if self.cdb[identity]["client_secret"] == areq["client_secret"]:
                return True
        elif "client_assertion" in areq: # client_secret_jwt or public_key_jwt
            if areq["client_assertion_type"] != JWT_BEARER:
                return False

            key_col = {areq["client_id"]:
                       self.keystore.get_verify_key(owner=areq["client_id"])}
            key_col.update({".": self.keystore.get_verify_key()})

#           On a busy system this is lots of data
#            if log_info:
#                log_info("key_col: %s" % (key_col,))

            bjwt = AuthnToken().from_jwt(areq["client_assertion"], key_col)

            try:
                assert bjwt["iss"] == areq["client_id"] # Issuer = the client
                # Is this true bjwt.iss == areq.client_id
                assert str(bjwt["iss"]) in self.cdb # It's a client I know
                assert str(bjwt["aud"]) == geturl(environ, query=False)
                return True
            except AssertionError:
                pass

        return False
Esempio n. 5
0
    def handle_authorization_response(self, environ, start_response):
        """
        This is where we get redirect back to after authorization at the
        authorization server has happened.

        :param environ: The WSGI environment
        :param start_response: The function to start the response process
        :return: A AccessTokenResponse instance
        """

        LOG_DEBUG("- authorization - %s flow -" % self.flow_type)

        _query = environ.get("QUERY_STRING")
        LOG_DEBUG("QUERY: %s" % _query)
        _path = http_util.geturl(environ, False, False)

        if "code" in self.response_type:
            # Might be an error response
            try:
                aresp = self.parse_response(AuthorizationResponse,
                                            info=_query, sformat="urlencoded")
            except Exception, err:
                logger.error("%s" % err)
                raise

            if isinstance(aresp, Message):
                if aresp.type().endswith("ErrorResponse"):
                    raise AuthzError(aresp["error"])

            try:
                self.update(aresp["state"])
            except KeyError:
                raise UnknownState(aresp["state"])

            self._backup(aresp["state"])

            return aresp
Esempio n. 6
0
    def parse_authz(self, environ, start_response):
        """
        This is where we get redirect back to after authorization at the
        authorization server has happened.

        :param environ: The WSGI environment
        :param start_response: The function to start the response process
        :return: A AccessTokenResponse instance
        """

        _log_info = logger.info
        if self.debug:
            _log_info("- authorization -")
            _log_info("environ: %s" % environ)

        if environ.get("REQUEST_METHOD") == "GET":
            _query = environ.get("QUERY_STRING")
#        elif environ.get("REQUEST_METHOD") == "POST":
#            _query = http_util.get_post(environ)
        else:
            resp = http_util.BadRequest("Unsupported method")
            return resp(environ, start_response)

        _log_info("response: %s" % _query)
        
        _path = http_util.geturl(environ, False, False)
        vkeys = self.keystore.get_verify_key(owner=None)

        if "code" in self.config["response_type"]:
            # Might be an error response
            _log_info("Expect Authorization Response")
            aresp = self.parse_response(AuthorizationResponse,
                                        info=_query,
                                        format="urlencoded",
                                        key=vkeys)
            if aresp.type() == "ErrorResponse":
                _log_info("ErrorResponse: %s" % aresp)
                raise AuthzError(aresp.error)

            _log_info("Aresp: %s" % aresp)

            _state = aresp["state"]
            try:
                self.update(_state)
            except KeyError:
                raise UnknownState(_state)

            self.redirect_uris = [self.sdb[_state]["redirect_uris"]]

            # May have token and id_token information too
            if "access_token" in aresp:
                atr = clean_response(aresp)
                self.access_token = atr
                # update the grant object
                self.get_grant(state=_state).add_token(atr)
            else:
                atr = None

            self._backup(_state)

            try:
                idt = aresp["id_token"]
            except KeyError:
                idt = None

            return aresp, atr, idt
        else: # implicit flow
            _log_info("Expect Access Token Response")
            atr = self.parse_response(AccessTokenResponse, info=_query,
                                      format="urlencoded", key=vkeys)
            if atr.type() == "ErrorResponse":
                raise TokenError(atr["error"])

            idt = None
            return None, atr, idt
Esempio n. 7
0
    def begin(self, environ, start_response, scope="",
              response_type="", use_nonce=False):
        """ Begin the OAuth2 flow

        :param environ: The WSGI environment
        :param start_response: The function to start the response process
        :param scope: Defines which user info claims is wanted
        :param response_type: Controls the parameters returned in the
            response from the Authorization Endpoint
        :param use_nonce: If not implicit flow nonce is optional.
            This defines if it should be used anyway.
        :return: A URL to which the user should be redirected
        """
        _log_info = logger.info

        if self.debug:
            _log_info("- begin -")

        _path = http_util.geturl(environ, False, False)
        _page = self.config["authz_page"]
        if not _path.endswith("/"):
            if _page.startswith("/"):
                self.redirect_uris = [_path + _page]
            else:
                self.redirect_uris = ["%s/%s" % (_path, _page)]
        else:
            if _page.startswith("/"):
                self.redirect_uris = [_path + _page[1:]]
            else:
                self.redirect_uris = ["%s/%s" % (_path, _page)]

        # Put myself in the dictionary of sessions, keyed on session-id
        if not self.seed:
            self.seed = rndstr()

        if not scope:
            scope = self.config["scope"]
        if not response_type:
            response_type = self.config["response_type"]

        sid = stateID(_path, self.seed)
        self.state = sid
        self.grant[sid] = Grant(seed=self.seed)

        self._backup(sid)
        self.sdb["seed:%s" % self.seed] = sid

        # Store the request and the redirect uri used
        self._request = http_util.geturl(environ)

        args = {
            "client_id": self.client_id,
            "state":sid,
            "response_type":response_type,
            "scope": scope,
            }

    # nonce is REQUIRED in implicit flow,
        # OPTIONAL on code flow.
        if "token" in response_type or use_nonce:
            self.nonce = rndstr(12)
            args["nonce"] = self.nonce

        if "max_age" in self.config:
            args["idtoken_claims"] = {"max_age": self.config["max_age"]}

        if "user_info" in self.config:
            args["userinfo_claims"] = self.config["user_info"]

        if "request_method" in self.config:
            areq = self.construct_OpenIDRequest(request_args=args,
                                                 extra_args=None)

            if self.config["request_method"] == "file":
                id_request = areq["request"]
                del areq["request"]
                _filedir = self.config["temp_dir"]
                _webpath = self.config["temp_path"]
                _name = rndstr(10)
                filename = os.path.join(_filedir, _name)
                while os.path.exists(filename):
                    _name = rndstr(10)
                    filename = os.path.join(_filedir, _name)
                fid = open(filename, mode="w")
                fid.write(id_request)
                fid.close()
                _webname = "%s%s%s" % (_path,_webpath,_name)
                areq["request_uri"] = _webname
                self.request_uri = _webname
                self._backup(sid)
        else:
            if "userinfo_claims" in args: # can only be carried in an IDRequest
                raise Exception("Need a request method")

            areq = self.construct_AuthorizationRequest(AuthorizationRequest,
                                                       request_args=args)

        location = areq.request(self.authorization_endpoint)

        if self.debug:
            _log_info("Redirecting to: %s" % location)

        return location