Beispiel #1
0
def test_update_to_token():
    sdb = SessionDB()
    sid = sdb.create_authz_session("user_id", AREQ)
    grant = sdb[sid]["code"]
    _dict = sdb.update_to_token(grant)

    print _dict.keys()
    assert _eq(_dict.keys(), ['code', 'authzreq', 'token_type', 'local_sub',
                              'client_id', 'oauth_state', 'refresh_token',
                              'revoked', 'sub', 'access_token',
                              'token_expires_at', 'expires_in', 'state',
                              'redirect_uri', 'code_used', 'scope',
                              'access_token_scope'])

    raises(Exception, 'sdb.update_to_token(grant)')

    raises(Exception, 'sdb.update_to_token(_dict["access_token"]')

    sdb = SessionDB()
    sid = sdb.create_authz_session("another_user_id", AREQ)
    grant = sdb[sid]["code"]

    _dict = sdb.update_to_token(grant, id_token="id_token", oidreq=OIDR)
    print _dict.keys()
    assert _eq(_dict.keys(), ['code', 'authzreq', 'id_token', 'token_type',
                              'local_sub', 'client_id', 'oauth_state',
                              'refresh_token', 'revoked', 'sub', 'oidreq',
                              'access_token', 'token_expires_at', 'expires_in',
                              'state', 'redirect_uri', 'code_used', 'scope',
                              'access_token_scope'])

    assert _dict["id_token"] == "id_token"
    assert _dict["oidreq"].type() == "OpenIDRequest"
    _ = _dict["access_token"]
    raises(Exception, 'sdb.update_to_token(token)')
Beispiel #2
0
def test_revoke_token():
    sdb = SessionDB()
    sid = sdb.create_authz_session("user_id", AREQ)

    grant = sdb[sid]["code"]
    _dict = sdb.update_to_token(grant)

    token = _dict["access_token"]
    rtoken = _dict["refresh_token"]
    
    assert sdb.is_valid(token)

    sdb.revoke_token(token)
    assert sdb.is_valid(token) is False

    dict2 = sdb.refresh_token(rtoken)
    token = dict2["access_token"]
    assert sdb.is_valid(token)

    sdb.revoke_token(rtoken)
    assert sdb.is_valid(rtoken) is False

    raises(ExpiredToken, 'sdb.refresh_token(rtoken)')

    assert sdb.is_valid(token)

    # --- new token ----

    sdb = SessionDB()
    sid = sdb.create_authz_session("user_id", AREQ)

    grant = sdb[sid]["code"]
    sdb.revoke_token(grant)
    assert sdb.is_valid(grant) is False
Beispiel #3
0
def test_refresh_token():
    sdb = SessionDB()
    sid = sdb.create_authz_session("user_id", AREQ)
    grant = sdb[sid]["code"]
    _dict = sdb.update_to_token(grant)
    dict1 = _dict.copy()

    rtoken = _dict["refresh_token"]
    time.sleep(1)
    dict2 = sdb.refresh_token(rtoken)
    print dict2
    
    assert dict1["issued"] != dict2["issued"]
    assert dict1["access_token"] != dict2["access_token"]

    raises(Exception, 'sdb.refresh_token(dict2["access_token"])')
Beispiel #4
0
def test_is_valid():
    sdb = SessionDB()
    sid = sdb.create_authz_session("user_id", AREQ)
    grant = sdb[sid]["code"]

    assert sdb.is_valid(grant)

    _dict = sdb.update_to_token(grant)
    assert sdb.is_valid(grant) is False
    token1 = _dict["access_token"]
    assert sdb.is_valid(token1)

    rtoken = _dict["refresh_token"]
    assert sdb.is_valid(rtoken)

    dict2 = sdb.refresh_token(rtoken)
    token2 = dict2["access_token"]
    assert sdb.is_valid(token2)

    # replace refresh_token

    dict2["refresh_token"] = token2
    assert sdb.is_valid(rtoken) is False
    
    # mess with the time-line

    dict2["expires_at"] = utc_time_sans_frac() - 86400  # like yesterday
    assert sdb.is_valid(token2) is False

    # replace access_token

    dict2["access_token"] = token1
    assert sdb.is_valid(token2) is False

    sid = sdb.create_authz_session("another:user", AREQ)
    grant = sdb[sid]["code"]

    gdict = sdb[grant]
    gdict["expires_at"] = utc_time_sans_frac() - 86400  # like yesterday
    assert sdb.is_valid(grant) is False
Beispiel #5
0
class MyFakeOICServer(Server):
    def __init__(self, name=""):
        Server.__init__(self)
        self.sdb = SessionDB()
        self.name = name
        self.client = {}
        self.registration_expires_in = 3600
        self.host = ""
        self.webfinger = WebFinger()

    #noinspection PyUnusedLocal
    def http_request(self, path, method="GET", **kwargs):
        part = urlparse(path)
        path = part[2]
        query = part[4]
        self.host = "%s://%s" % (part.scheme, part.netloc)

        response = Response
        response.status_code = 500
        response.text = ""

        if path == ENDPOINT["authorization_endpoint"]:
            assert method == "GET"
            response = self.authorization_endpoint(query)
        elif path == ENDPOINT["token_endpoint"]:
            assert method == "POST"
            response = self.token_endpoint(kwargs["data"])
        elif path == ENDPOINT["user_info_endpoint"]:
            assert method == "POST"
            response = self.userinfo_endpoint(kwargs["data"])
        elif path == ENDPOINT["refresh_session_endpoint"]:
            assert method == "GET"
            response = self.refresh_session_endpoint(query)
        elif path == ENDPOINT["check_session_endpoint"]:
            assert method == "GET"
            response = self.check_session_endpoint(query)
        elif path == ENDPOINT["end_session_endpoint"]:
            assert method == "GET"
            response = self.end_session_endpoint(query)
        elif path == ENDPOINT["registration_endpoint"]:
            if method == "POST":
                response = self.registration_endpoint(kwargs["data"])
        elif path == "/.well-known/webfinger":
            assert method == "GET"
            qdict = parse_qs(query)
            response.status_code = 200
            response.text = self.webfinger.response(qdict["resource"][0],
                                                    "%s/" % self.name)
        elif path == "/.well-known/openid-configuration":
            assert method == "GET"
            response = self.openid_conf()

        return response

    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        sid = self.sdb.create_authz_session(sub="user", areq=req)
        _info = self.sdb[sid]
        _info["sub"] = _info["local_sub"]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.update_to_token(grant)
                _dict["oauth_state"] = "authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
                #resp.code = grant
            else:
                resp = AuthorizationResponse(state=req["state"],
                                             code=_info["code"])

        else:  # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            _dict = dict([(k, v) for k, v in
                          self.sdb.update_to_token(grant).items() if k in
                                                                     params])
            try:
                del _dict["refresh_token"]
            except KeyError:
                pass

            if "id_token" in req["response_type"]:
                _idt = self.make_id_token(_info, issuer=self.name,
                                          access_token=_dict["access_token"])
                alg = "RS256"
                ckey = self.keyjar.get_signing_key(alg2keytype(alg),
                                                   _info["client_id"])
                _dict["id_token"] = _idt.to_jwt(key=ckey, algorithm=alg)

            resp = AccessTokenResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response = Response()
        response.headers = {"location": location}
        response.status_code = 302
        response.text = ""
        return response

    def token_endpoint(self, data):
        if "grant_type=refresh_token" in data:
            req = self.parse_refresh_token_request(body=data)
            _info = self.sdb.refresh_token(req["refresh_token"])
        elif "grant_type=authorization_code":
            req = self.parse_token_request(body=data)
            _info = self.sdb.update_to_token(req["code"])
        else:
            response = TokenErrorResponse(error="unsupported_grant_type")
            return response, ""

        resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))
        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()

        return response

    def userinfo_endpoint(self, data):

        _ = self.parse_user_info_request(data)
        _info = {
            "sub": "melgar",
            "name": "Melody Gardot",
            "nickname": "Mel",
            "email": "*****@*****.**",
            "verified": True,
        }

        resp = OpenIDSchema(**_info)
        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()

        return response

    def registration_endpoint(self, data):
        req = self.parse_registration_request(data)

        client_secret = rndstr()
        expires = utc_time_sans_frac() + self.registration_expires_in
        kwargs = {}
        if "client_id" not in req:
            client_id = rndstr(10)
            registration_access_token = rndstr(20)
            _client_info = req.to_dict()
            kwargs.update(_client_info)
            _client_info.update({
                "client_secret": client_secret,
                "info": req.to_dict(),
                "expires": expires,
                "registration_access_token": registration_access_token,
                "registration_client_uri": "register_endpoint"
            })
            self.client[client_id] = _client_info
            kwargs["registration_access_token"] = registration_access_token
            kwargs["registration_client_uri"] = "register_endpoint"
            try:
                del kwargs["operation"]
            except KeyError:
                pass
        else:
            client_id = req.client_id
            _cinfo = self.client[req.client_id]
            _cinfo["info"].update(req.to_dict())
            _cinfo["client_secret"] = client_secret
            _cinfo["expires"] = expires

        resp = RegistrationResponse(client_id=client_id,
                                    client_secret=client_secret,
                                    client_secret_expires_at=expires,
                                    **kwargs)

        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()

        return response

    def check_session_endpoint(self, query):
        try:
            idtoken = self.parse_check_session_request(query=query)
        except Exception:
            raise

        response = Response()
        response.text = idtoken.to_json()
        response.headers = {"content-type": "application/json"}
        return response

    #noinspection PyUnusedLocal
    def refresh_session_endpoint(self, query):
        try:
            req = self.parse_refresh_session_request(query=query)
        except Exception:
            raise

        resp = RegistrationResponse(client_id="anonymous",
                                    client_secret="hemligt")

        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()
        return response

    def end_session_endpoint(self, query):
        try:
            req = self.parse_end_session_request(query=query)
        except Exception:
            raise

        # redirect back
        resp = EndSessionResponse(state=req["state"])

        url = resp.request(req["redirect_url"])

        response = Response()
        response.headers = {"location": url}
        response.status_code = 302  # redirect
        response.text = ""
        return response

    #noinspection PyUnusedLocal
    def add_credentials(self, user, passwd):
        return

    def openid_conf(self):
        endpoint = {}
        for point, path in ENDPOINT.items():
            endpoint[point] = "%s%s" % (self.host, path)

        signing_algs = jws.SIGNER_ALGS.keys()
        resp = ProviderConfigurationResponse(
            issuer=self.name,
            scopes_supported=["openid", "profile", "email", "address"],
            identifiers_supported=["public", "PPID"],
            flows_supported=["code", "token", "code token", "id_token",
                             "code id_token", "token id_token"],
            subject_types_supported=["pairwise", "public"],
            response_types_supported=["code", "token", "id_token",
                                      "code token", "code id_token",
                                      "token id_token", "code token id_token"],
            jwks_uri="http://example.com/oidc/jwks",
            id_token_signing_alg_values_supported=signing_algs,
            grant_types_supported=["authorization_code", "implicit"],
            **endpoint)

        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()
        return response
Beispiel #6
0
class MyFakeOICServer(Server):
    def __init__(self, jwt_keys=None, name=""):
        Server.__init__(self, jwt_keys=jwt_keys)
        self.sdb = SessionDB()
        self.name = name
        self.client = {}
        self.registration_expires_in = 3600
        self.host = ""

    #noinspection PyUnusedLocal
    def http_request(self, path, method="GET", **kwargs):
        part = urlparse.urlparse(path)
        path = part[2]
        query = part[4]
        self.host = "%s://%s" % (part.scheme, part.netloc)

        response = Response
        response.status_code = 500
        response.text = ""

        if path == ENDPOINT["authorization_endpoint"]:
            assert method == "GET"
            response = self.authorization_endpoint(query)
        elif path == ENDPOINT["token_endpoint"]:
            assert method == "POST"
            response = self.token_endpoint(kwargs["data"])
        elif path == ENDPOINT["user_info_endpoint"]:
            assert method == "POST"
            response = self.userinfo_endpoint(kwargs["data"])
        elif path == ENDPOINT["refresh_session_endpoint"]:
            assert method == "GET"
            response = self.refresh_session_endpoint(query)
        elif path == ENDPOINT["check_session_endpoint"]:
            assert method == "GET"
            response = self.check_session_endpoint(query)
        elif path == ENDPOINT["end_session_endpoint"]:
            assert method == "GET"
            response = self.end_session_endpoint(query)
        elif path == ENDPOINT["registration_endpoint"]:
            if method == "POST":
                response = self.registration_endpoint(kwargs["data"])
        elif path == "/.well-known/simple-web-discovery":
            assert method == "GET"
            response = self.issuer(query)
        elif path == "/swd_server":
            assert method == "GET"
            response = self.swd_server(query)
        elif path == "/.well-known/openid-configuration"\
        or path == "/providerconf/.well-known/openid-configuration":
            assert method == "GET"
            response = self.openid_conf()

        return response

    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        sid = self.sdb.create_authz_session(user_id="user", areq=req)
        _info = self.sdb[sid]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.update_to_token(grant)
                _dict["oauth_state"]="authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
                #resp.code = grant
            else:
                resp = AuthorizationResponse(state=req["state"],
                                             code=_info["code"])

        else: # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            _dict = dict([(k,v) for k,
                        v in self.sdb.update_to_token(grant).items() if k in
                                                                    params])
            try:
                del _dict["refresh_token"]
            except KeyError:
                pass

            if "id_token" in req["response_type"]:
                _dict["id_token"] = self.make_id_token(_info, issuer=self.name,
                                            access_token=_dict["access_token"])

            resp = AccessTokenResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response= Response()
        response.headers = {"location":location}
        response.status_code = 302
        response.text = ""
        return response

    def token_endpoint(self, data):
        if "grant_type=refresh_token" in data:
            req = self.parse_refresh_token_request(body=data)
            _info = self.sdb.refresh_token(req["refresh_token"])
        elif "grant_type=authorization_code":
            req = self.parse_token_request(body=data)
            _info = self.sdb.update_to_token(req["code"])
        else:
            response = TokenErrorResponse(error="unsupported_grant_type")
            return response, ""

        resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))
        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()

        return response

    def userinfo_endpoint(self, data):

        _ = self.parse_user_info_request(data)
        _info = {
            "name": "Melody Gardot",
            "nickname": "Mel",
            "email": "*****@*****.**",
            "verified": True,
            }

        resp = OpenIDSchema(**_info)
        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()

        return response

    def registration_endpoint(self, data):
        req = self.parse_registration_request(data)

        client_secret = rndstr()
        expires = utc_time_sans_frac() + self.registration_expires_in
        if req["type"] == "client_associate":
            client_id = rndstr(10)

            self.client[client_id] = {
                "client_secret": client_secret,
                "info": req.to_dict(),
                "expires": expires
            }
        else:
            client_id = req.client_id
            _cinfo = self.client[req.client_id]
            _cinfo["info"].update(req.to_dict())
            _cinfo["client_secret"] = client_secret
            _cinfo["expires"] = expires

        resp = RegistrationResponseCARS(client_id=client_id,
                                    client_secret=client_secret,
                                    expires_at=expires)

        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()

        return response

    def check_session_endpoint(self, query):
        try:
            idtoken = self.parse_check_session_request(query=query)
        except Exception:
            raise

        response = Response()
        response.text = idtoken.to_json()
        response.headers = {"content-type":"application/json"}
        return response

    #noinspection PyUnusedLocal
    def refresh_session_endpoint(self, query):
        try:
            req = self.parse_refresh_session_request(query=query)
        except Exception:
            raise

        resp = RegistrationResponseCARS(client_id="anonymous",
                                    client_secret="hemligt")

        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()
        return response

    def end_session_endpoint(self, query):
        try:
            req = self.parse_end_session_request(query=query)
        except Exception:
            raise

        # redirect back
        resp = EndSessionResponse(state=req["state"])

        url = resp.request(req["redirect_url"])

        response = Response()
        response.headers= {"location":url}
        response.status_code = 302  # redirect
        response.text = ""
        return response

    #noinspection PyUnusedLocal
    def add_credentials(self, user, passwd):
        return

    def issuer(self, query):
        request = self.parse_issuer_request(query)
        if request["principal"] == "*****@*****.**":
            resp = IssuerResponse(locations="http://example.com/")
        elif request["principal"] == "*****@*****.**":
            swd = SWDServiceRedirect(location="https://example.net/swd_server")
            resp = IssuerResponse(SWD_service_redirect=swd,
                                  expires=time_sans_frac() + 600)
        else:
            resp = None

        if resp is None:
            response = Response()
            response.status = 401
            return response, ""
        else:
            response = Response()
            response.headers = {"content-type":"application/json"}
            response.text = resp.to_json()
            return response

    def swd_server(self, query):
        request = self.parse_issuer_request(query)
        if request["principal"] == "*****@*****.**":
            resp = IssuerResponse(locations="http://example.net/providerconf")
        else:
            resp = None

        if resp is None:
            response = Response()
            response.status_code = 401
            response.text = ""
            return response
        else:
            response = Response()
            response.headers = {"content-type":"application/json"}
            response.text = resp.to_json()
            return response

    def openid_conf(self):
        endpoint = {}
        for point, path in ENDPOINT.items():
            endpoint[point] = "%s%s" % (self.host, path)

        resp = ProviderConfigurationResponse(
                                   issuer=self.name,
                                   scopes_supported=["openid", "profile",
                                                     "email", "address"],
                                   identifiers_supported=["public", "PPID"],
                                   flows_supported=["code", "token",
                                                    "code token", "id_token",
                                                    "code id_token",
                                                    "token id_token"],
                                   **endpoint)

        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()
        return response
Beispiel #7
0
class MyFakeOAuth2Server(Server):
    def __init__(self, jwt_keys=None, name=""):
        Server.__init__(self, jwt_keys=jwt_keys)
        self.sdb = SessionDB()
        self.name = name
        self.client = {}
        self.registration_expires_in = 3600
        self.host = ""

    #noinspection PyUnusedLocal
    def http_request(self, url, method="GET", **kwargs):
        part = urlparse.urlparse(url)
        path = part[2]
        query = part[4]
        self.host = "%s://%s" % (part.scheme, part.netloc)

        response = Response
        response.status_code = 500
        response.text = ""

        if path == ENDPOINT["authorization_endpoint"]:
            assert method == "GET"
            response = self.authorization_endpoint(query)
        elif path == ENDPOINT["token_endpoint"]:
            assert method == "POST"
            response = self.token_endpoint(kwargs["data"])

        return response

    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        sid = self.sdb.create_authz_session(user_id="user", areq=req)
        _info = self.sdb[sid]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.update_to_token(grant)
                _dict["oauth_state"]="authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
                #resp.code = grant
            else:
                resp = AuthorizationResponse(state=req["state"],
                                             code=_info["code"])

        else: # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            _dict = dict([(k,v) for k,
                                    v in self.sdb.update_to_token(grant).items() if k in
                                                                                    params])
            try:
                del _dict["refresh_token"]
            except KeyError:
                pass

            resp = AccessTokenResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response= Response()
        response.headers = {"location":location}
        response.status_code = 302
        response.text = ""
        return response

    def token_endpoint(self, data):
        if "grant_type=refresh_token" in data:
            req = self.parse_refresh_token_request(body=data)
            _info = self.sdb.refresh_token(req["refresh_token"])
        elif "grant_type=authorization_code":
            req = self.parse_token_request(body=data)
            _info = self.sdb.update_to_token(req["code"])
        else:
            response = TokenErrorResponse(error="unsupported_grant_type")
            return response, ""

        resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))
        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()

        return response
Beispiel #8
0
class MyFakeOAuth2Server(Server):
    def __init__(self, jwt_keys=None, name=""):
        Server.__init__(self, jwt_keys=jwt_keys)
        self.sdb = SessionDB()
        self.name = name
        self.client = {}
        self.registration_expires_in = 3600
        self.host = ""

    #noinspection PyUnusedLocal
    def http_request(self, url, method="GET", **kwargs):
        part = urlparse.urlparse(url)
        path = part[2]
        query = part[4]
        self.host = "%s://%s" % (part.scheme, part.netloc)

        response = Response
        response.status_code = 500
        response.text = ""

        if path == ENDPOINT["authorization_endpoint"]:
            assert method == "GET"
            response = self.authorization_endpoint(query)
        elif path == ENDPOINT["token_endpoint"]:
            assert method == "POST"
            response = self.token_endpoint(kwargs["data"])

        return response

    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        sid = self.sdb.create_authz_session(user_id="user", areq=req)
        _info = self.sdb[sid]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.upgrade_to_token(grant)
                _dict["oauth_state"]="authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
                #resp.code = grant
            else:
                resp = AuthorizationResponse(state=req["state"],
                                             code=_info["code"])

        else: # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            _dict = dict([(k,v) for k,
                                    v in self.sdb.upgrade_to_token(grant).items() if k in
                                                                                    params])
            try:
                del _dict["refresh_token"]
            except KeyError:
                pass

            resp = AccessTokenResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response= Response()
        response.headers = {"location":location}
        response.status_code = 302
        response.text = ""
        return response

    def token_endpoint(self, data):
        if "grant_type=refresh_token" in data:
            req = self.parse_refresh_token_request(body=data)
            _info = self.sdb.refresh_token(req["refresh_token"])
        elif "grant_type=authorization_code":
            req = self.parse_token_request(body=data)
            _info = self.sdb.update_to_token(req["code"])
        else:
            response = TokenErrorResponse(error="unsupported_grant_type")
            return response, ""

        resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))
        response = Response()
        response.headers = {"content-type":"application/json"}
        response.text = resp.to_json()

        return response