Пример #1
0
class TestToken2(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[''] = [kb]

        self.access_token = JWTToken(
            'T', keyjar=kj, iss='https://example.com/as', sign_alg='RS256')

    def test_create(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(sid, sinfo=session_info, kid='sign1',
                                 lifetime=1200)

        assert _jwt
        assert len(_jwt.split('.')) == 3  # very simple JWS check

    def test_create_with_aud(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(
            sid, sinfo=session_info, kid='sign1',
            aud=['https://example.com/rs'], lifetime=1200)

        assert _jwt

        info = self.access_token.get_info(_jwt)
        assert info['exp'] - info['iat'] == 1200
Пример #2
0
class TestEncToken(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[''] = [kb]

        self.access_token = JWTToken('T',
                                     keyjar=kj,
                                     lt_pattern={
                                         'code': 3600,
                                         'token': 900
                                     },
                                     iss='https://example.com/as',
                                     encrypt=True)

    def test_enc_create(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwe = self.access_token(sid, sinfo=session_info, kid='sign1')

        assert _jwe
        assert len(_jwe.split('.')) == 5  # very simple JWE check

    def test_parse_enc(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwe = self.access_token(sid, sinfo=session_info, kid='sign1')
        _info = self.access_token.get_info(_jwe)
        assert _info
Пример #3
0
class TestEncToken(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[''] = [kb]

        self.access_token = JWTToken('T', keyjar=kj,
                              lt_pattern={'code': 3600, 'token': 900},
                              iss='https://example.com/as', encrypt=True)

    def test_enc_create(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwe = self.access_token(sid, sinfo=session_info, kid='sign1')

        assert _jwe
        assert len(_jwe.split('.')) == 5  # very simple JWE check

    def test_parse_enc(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwe = self.access_token(sid, sinfo=session_info, kid='sign1')
        _info = self.access_token.get_info(_jwe)
        assert _info
Пример #4
0
class TestEncToken(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[""] = [kb]

        self.token = JWTToken(
            "T", keyjar=kj, lifetime={"code": 3600, "token": 900}, iss="https://example.com/as", encrypt=True
        )

    def test_enc_create(self):
        sid = rndstr(32)
        session_info = {"sub": "subject_id", "client_id": "https://example.com/rp", "response_type": ["code"]}

        _jwe = self.token(sid, sinfo=session_info, kid="sign1")

        assert _jwe
        assert len(_jwe.split(".")) == 5  # very simple JWE check

    def test_parse_enc(self):
        sid = rndstr(32)
        session_info = {"sub": "subject_id", "client_id": "https://example.com/rp", "response_type": ["code"]}

        _jwe = self.token(sid, sinfo=session_info, kid="sign1")
        _info = self.token.get_info(_jwe)
        assert _info
Пример #5
0
def test_pkce_token():
    kb = KeyBundle(JWKS["keys"])
    kj = KeyJar()
    kj.issuer_keys[''] = [kb]
    constructor = JWTToken('A',
                           keyjar=kj,
                           lt_pattern={'': 900},
                           iss='https://example.com/as',
                           sign_alg='RS256',
                           encrypt=True)

    sid = rndstr(32)
    session_info = {
        'sub': 'subject_id',
        'client_id': 'https://example.com/rp',
        'response_type': ['code'],
        'authzreq': '{}'
    }

    _cli = Client(config={'code_challenge': {'method': 'S512', 'length': 96}})
    args, cv = _cli.add_code_challenge()

    access_grant = constructor(
        sid,
        sinfo=session_info,
        kid='sign1',
        code_challenge=args['code_challenge'],
        code_challenge_method=args['code_challenge_method'])

    _info = constructor.get_info(access_grant)
    assert _info['code_challenge_method'] == args['code_challenge_method']
    assert _info['code_challenge'] == args['code_challenge']
Пример #6
0
def test_pkce_token():
    kb = KeyBundle(JWKS["keys"])
    kj = KeyJar()
    kj.issuer_keys[''] = [kb]
    constructor = JWTToken('A', keyjar=kj, lt_pattern={'': 900},
                           iss='https://example.com/as', sign_alg='RS256',
                           encrypt=True)

    sid = rndstr(32)
    session_info = {
        'sub': 'subject_id',
        'client_id': 'https://example.com/rp',
        'response_type': ['code'],
        'authzreq': '{}'
    }

    _cli = Client(config={'code_challenge': {'method': 'S512', 'length': 96}})
    args, cv = _cli.add_code_challenge()

    access_grant = constructor(
        sid, sinfo=session_info, kid='sign1',
        code_challenge=args['code_challenge'],
        code_challenge_method=args['code_challenge_method'])

    _info = constructor.get_info(access_grant)
    assert _info['code_challenge_method'] == args['code_challenge_method']
    assert _info['code_challenge'] == args['code_challenge']
Пример #7
0
def test_pkce_token():
    kb = KeyBundle(JWKS["keys"])
    kj = KeyJar()
    kj.issuer_keys[""] = [kb]
    constructor = JWTToken(
        "A",
        keyjar=kj,
        lt_pattern={"": 900},
        iss="https://example.com/as",
        sign_alg="RS256",
        encrypt=True,
    )

    sid = rndstr(32)
    session_info = {
        "sub": "subject_id",
        "client_id": "https://example.com/rp",
        "response_type": ["code"],
        "authzreq": "{}",
    }

    _cli = Client(config={"code_challenge": {"method": "S512", "length": 96}})
    args, cv = _cli.add_code_challenge()

    access_grant = constructor(
        sid,
        sinfo=session_info,
        kid="sign1",
        code_challenge=args["code_challenge"],
        code_challenge_method=args["code_challenge_method"],
    )

    _info = constructor.get_info(access_grant)
    assert _info["code_challenge_method"] == args["code_challenge_method"]
    assert _info["code_challenge"] == args["code_challenge"]
Пример #8
0
class TestToken2(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[""] = [kb]

        self.access_token = JWTToken("T",
                                     keyjar=kj,
                                     iss="https://example.com/as",
                                     sign_alg="RS256")

    def test_create(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(sid,
                                 sinfo=session_info,
                                 kid="sign1",
                                 lifetime=1200)

        assert _jwt
        assert len(_jwt.split(".")) == 3  # very simple JWS check

    def test_create_with_aud(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(
            sid,
            sinfo=session_info,
            kid="sign1",
            aud=["https://example.com/rs"],
            lifetime=1200,
        )

        assert _jwt

        info = self.access_token.get_info(_jwt)
        assert info["exp"] - info["iat"] == 1200
Пример #9
0
class TestToken2(object):
    @pytest.fixture(autouse=True)
    def create_token(self):
        kb = KeyBundle(JWKS["keys"])
        kj = KeyJar()
        kj.issuer_keys[''] = [kb]

        self.access_token = JWTToken('T',
                                     keyjar=kj,
                                     iss='https://example.com/as',
                                     sign_alg='RS256')

    def test_create(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(sid,
                                 sinfo=session_info,
                                 kid='sign1',
                                 lifetime=1200)

        assert _jwt
        assert len(_jwt.split('.')) == 3  # very simple JWS check

    def test_create_with_aud(self):
        sid = rndstr(32)
        session_info = SESSION_INFO

        _jwt = self.access_token(sid,
                                 sinfo=session_info,
                                 kid='sign1',
                                 aud=['https://example.com/rs'],
                                 lifetime=1200)

        assert _jwt

        info = self.access_token.get_info(_jwt)
        assert info['exp'] - info['iat'] == 1200
Пример #10
0
class TokenHandler(object):
    """
    Class for handling tokens.

    Note! the token and refresh token factories both keep their own token databases.
    """

    def __init__(
        self,
        issuer,
        token_policy,
        token_factory=None,
        refresh_token_factory=None,
        keyjar=None,
        sign_alg="RS256",
    ):
        """
        Initialize the class.

        :param token_factory: A callable function that returns a token
        :param refresh_token_factory: A callable function that returns a
            refresh token
        :param token_policy: A dictionary of the form
            {'access_token': {<target_id>: {<grant_type>: <lifetime>}},
             'refresh_token': {<target_id>: {<grant_type>: <lifetime>}}}
        :param keyjar: A oic.utils.keyio.KeyJar instance
        :param sign_alg: Which signature algorithm to use.
        :return: a TokenHandler instance
        """
        self.token_policy = token_policy
        if token_factory is None:
            self.token_factory = JWTToken(
                "T", keyjar=keyjar, iss=issuer, sign_alg=sign_alg
            )
        else:
            self.token_factory = token_factory

        if refresh_token_factory is None:
            self.refresh_token_factory = JWTToken(
                "R",
                keyjar=keyjar,
                iss="https://example.com/as",
                sign_alg=sign_alg,
                token_storage={},
            )
        else:
            self.refresh_token_factory = refresh_token_factory

    def get_access_token(self, target_id, scope, grant_type):
        """
        Return access token for given inputs.

        :param target_id:
        :param scope:
        :param grant_type:
        :return:
        """
        # No default, either there is an explicit policy or there is not
        try:
            lifetime = self.token_policy["access_token"][target_id][grant_type]
        except KeyError:
            raise NotAllowed(
                "Access token for grant_type {} for target_id {} not allowed"
            )

        sid = rndstr(32)
        return self.token_factory(
            sid,
            target_id=target_id,
            scope=scope,
            grant_type=grant_type,
            lifetime=lifetime,
        )

    def refresh_access_token(self, target_id, token, grant_type, **kwargs):
        """
        Return refresh_access_token for given input.

        :param target_id: Who gave me this token
        :param token: The refresh_token
        :param grant_type: Which grant type the token is connected to
        :param kwargs: Extra key word arguments
        :return: New access_token
        """
        # Check that the token is an refresh token
        info = self.refresh_token_factory.get_info(token)

        # Make sure the token should is usable by the client to get a
        # refresh token
        try:
            if target_id != info["azr"]:
                raise NotAllowed("{} can't use this token".format(target_id))
        except KeyError:
            if target_id not in info["aud"]:
                raise NotAllowed("{} can't use this token".format(target_id))

        if self.token_factory.is_valid(info):
            try:
                lifetime = self.token_policy["access_token"][target_id][grant_type]
            except KeyError:
                raise NotAllowed(
                    "Issue access token for grant_type {} for target_id {} not allowed"
                )
            else:
                sid = self.token_factory.db[info["jti"]]
                try:
                    _aud = kwargs["aud"]
                except KeyError:
                    _aud = info["aud"]

                return self.token_factory(
                    sid, target_id=target_id, lifetime=lifetime, aud=_aud
                )

    def get_refresh_token(self, target_id, grant_type, sid):
        try:
            lifetime = self.token_policy["refresh_token"][target_id][grant_type]
        except KeyError:
            raise NotAllowed(
                "Issue access token for grant_type {} for target_id {} not allowed"
            )
        else:
            return self.refresh_token_factory(
                sid, target_id=target_id, lifetime=lifetime
            )

    def invalidate(self, token):
        if self.token_factory.valid(token):
            self.token_factory.invalidate(token)
Пример #11
0
class TokenHandler(object):
    def __init__(self, issuer, token_policy, token_factory=None,
                 refresh_token_factory=None, keyjar=None, sign_alg='RS256'):
        """
        Note! the token and refresh token factories both keep their own
        token databases.

        :param token_factory: A callable function that returns a token
        :param refresh_token_factory: A callable function that returns a
            refresh token
        :param token_policy: A dictionary of the form
            {'access_token': {<target_id>: {<grant_type>: <lifetime>}},
             'refresh_token': {<target_id>: {<grant_type>: <lifetime>}}}
        :param keyjar: A oic.utils.keyio.KeyJar instance
        :param sign_alg: Which signature algorithm to use.
        :return: a TokenHandler instance
        """

        self.token_policy = token_policy
        if token_factory is None:
            self.token_factory = JWTToken('T', keyjar=keyjar, iss=issuer,
                                          sign_alg=sign_alg)
        else:
            self.token_factory = token_factory

        if refresh_token_factory is None:
            self.refresh_token_factory = JWTToken('R', keyjar=keyjar,
                                                  iss='https://example.com/as',
                                                  sign_alg=sign_alg)
        else:
            self.refresh_token_factory = refresh_token_factory

    def get_access_token(self, target_id, scope, grant_type):
        """

        :param target_id:
        :param scope:
        :param grant_type:
        :return:
        """
        # No default, either there is an explicit policy or there is not
        try:
            lifetime = self.token_policy['access_token'][target_id][grant_type]
        except KeyError:
            raise NotAllowed(
                'Access token for grant_type {} for target_id {} not allowed')

        sid = rndstr(32)
        return self.token_factory(sid, target_id=target_id, scope=scope,
                                  grant_type=grant_type, lifetime=lifetime)

    def refresh_access_token(self, target_id, token, grant_type, **kwargs):
        """

        :param target_id: Who gave me this token
        :param token: The refresh_token
        :param grant_type: Which grant type the token is connected to
        :param kwargs: Extra key word arguments
        :return: New access_token
        """
        # Check that the token is an refresh token
        info = self.refresh_token_factory.get_info(token)

        # Make sure the token should is usable by the client to get a
        # refresh token
        try:
            if target_id != info["azr"]:
                raise NotAllowed("{} can't use this token".format(target_id))
        except KeyError:
            if target_id not in info['aud']:
                raise NotAllowed("{} can't use this token".format(target_id))

        if self.token_factory.is_valid(info):
            try:
                lifetime = self.token_policy['access_token'][target_id][
                    grant_type]
            except KeyError:
                raise NotAllowed(
                    'Issue access token for grant_type {} for target_id {} not allowed')
            else:
                sid = self.token_factory.db[info['jti']]
                try:
                    _aud = kwargs['aud']
                except KeyError:
                    _aud = info['aud']

                return self.token_factory(
                    sid, target_id=target_id, lifetime=lifetime, aud=_aud)

    def get_refresh_token(self, target_id, grant_type, sid):
        try:
            lifetime = self.token_policy['refresh_token'][target_id][grant_type]
        except KeyError:
            raise NotAllowed(
                'Issue access token for grant_type {} for target_id {} not allowed')
        else:
            return self.refresh_token_factory(
                sid, target_id=target_id, lifetime=lifetime)

    def invalidate(self, token):
        if self.token_factory.valid(token):
            self.token_factory.invalidate(token)