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 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']
def create_sdb(self): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[""] = [kb] self.sdb = SessionDB( "https://example.com/", db=DictSessionBackend(), code_factory=DefaultToken("supersecret", "verybadpassword", typ="A", lifetime=600), token_factory=JWTToken( "T", keyjar=kj, lt_pattern={ "code": 3600, "token": 900 }, iss="https://example.com/as", sign_alg="RS256", ), refresh_token_factory=JWTToken( "R", keyjar=kj, lt_pattern={"": 24 * 3600}, iss="https://example.com/as", token_storage={}, ), )
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"]
def create_provider(self): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[''] = [kb] _sdb = SessionDB("https://example.com/", db={}, code_factory=DefaultToken('supersecret', 'verybadpassword', typ='A', lifetime=600), token_factory=JWTToken('T', keyjar=kj, lt_pattern={ 'code': 3600, 'token': 900 }, iss='https://example.com/as', sign_alg='RS256'), refresh_token_factory=JWTToken( 'R', keyjar=kj, lt_pattern={'': 24 * 3600}, iss='https://example.com/as')) # name, sdb, cdb, authn_broker, authz, client_authn, self.provider = Provider("as", _sdb, CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as')
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 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 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 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, )
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
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')
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
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
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
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 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 create_sdb(self): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[''] = [kb] self.sdb = SessionDB( "https://example.com/", token_factory=JWTToken('T', keyjar=kj, lt_pattern={ 'code': 3600, 'token': 900 }, iss='https://example.com/as', sign_alg='RS256'), refresh_token_factory=JWTToken('R', keyjar=kj, lt_pattern={'': 24 * 3600}, iss='https://example.com/as'))
def create_provider(self): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[""] = [kb] _sdb = SessionDB( "https://example.com/", db=DictSessionBackend(), code_factory=DefaultToken("supersecret", "verybadpassword", typ="A", lifetime=600), token_factory=JWTToken( "T", keyjar=kj, lt_pattern={ "code": 3600, "token": 900 }, iss="https://example.com/as", sign_alg="RS256", ), refresh_token_factory=JWTToken( "R", keyjar=kj, lt_pattern={"": 24 * 3600}, iss="https://example.com/as", token_storage={}, ), ) # name, sdb, cdb, authn_broker, authz, client_authn, self.provider = Provider( "as", _sdb, CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl="https://example.com/as", )
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 create_sdb(self): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[''] = [kb] self.sdb = SessionDB( "https://example.com/", db={}, code_factory=DefaultToken('supersecret', 'verybadpassword', typ='A', lifetime=600), token_factory=JWTToken('T', keyjar=kj, lt_pattern={ 'code': 3600, 'token': 900 }, iss='https://example.com/as', sign_alg='RS256'), refresh_token_factory=JWTToken('R', keyjar=kj, lt_pattern={'': 24 * 3600}, iss='https://example.com/as'))
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
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
jwks_file_name = JWKS_FILE_NAME f = open(jwks_file_name, "w") for key in jwks["keys"]: for k in key.keys(): key[k] = as_unicode(key[k]) f.write(json.dumps(jwks)) f.close() oas.jwks_uri = "{}/{}".format(oas.baseurl, jwks_file_name) # Initiate the SessionDB _token = JWTToken('T', oas.keyjar, { 'code': 3600, 'token': 900 }, iss=config.issuer, sign_alg='RS256') _refresh_token = JWTToken('R', oas.keyjar, {'': 86400}, iss=config.issuer, sign_alg='RS256') oas.sdb = SessionDB(config.SERVICE_URL, token_factory=_token, refresh_token_factory=_refresh_token) # set some parameters try: oas.cookie_ttl = config.COOKIETTL except AttributeError:
def as_arg_setup(args, lookup, config): if args.port: _port = args.port else: if args.tls: _port = 443 else: _port = 80 if args.path2port: # means there is a reverse proxy in front translating # path -> port p2p_map = read_path2port_map(args.path2port) _path = p2p_map[_port] if args.xport: _issuer = "{base}:{port}/{path}".format(base=config.baseurl, port=args.xport, path=_path) _port = args.xport else: _issuer = "{base}/{path}".format(base=config.baseurl, path=_path) else: # the old port based _path = '' _issuer = "{base}:{port}".format(base=config.baseurl, port=_port) if args.tls and _issuer.startswith('http://'): _issuer = _issuer.replace('http://', 'https://') cdb = {} ac = AuthnBroker() for authkey, value in list(config.AUTHENTICATION.items()): authn = None # if "UserPassword" == authkey: # from oic.utils.authn.user import UsernamePasswordMako # authn = UsernamePasswordMako(None, "login.mako", LOOKUP, PASSWD, # "authorization") if "NoAuthn" == authkey: from oic.utils.authn.user import NoAuthn authn = NoAuthn(None, user=config.AUTHENTICATION[authkey]["user"]) if authn is not None: ac.add(config.AUTHENTICATION[authkey]["ACR"], authn, config.AUTHENTICATION[authkey]["WEIGHT"]) # dealing with authorization authz = AuthzHandling() if config.USERINFO == "SIMPLE": # User info is a simple dictionary in this case statically defined in # the configuration file userinfo = UserInfo(config.USERDB) else: userinfo = None as_args = { "name": _issuer, 'instance_path': _path, 'instance_port': _port, "cdb": cdb, "authn_broker": ac, "userinfo": userinfo, "authz": authz, "client_authn": verify_client, "symkey": config.SYM_KEY, "template_lookup": lookup, "template": { "form_post": "form_response.mako" }, "jwks_name": "./static/jwks_{}.json", 'event_db': Events(), } try: as_args['behavior'] = config.BEHAVIOR except AttributeError: pass com_args = { "baseurl": config.baseurl, } for arg in [ 'name', 'cdb', 'authn_broker', 'userinfo', 'authz', 'template', 'jwks_name', 'client_authn', 'symkey', 'template_lookup' ]: com_args[arg] = as_args[arg] # Add own keys for signing/encrypting JWTs try: # a throw-away OP used to do the initial key setup _op = Provider(sdb=SessionDB(com_args["baseurl"]), **com_args) jwks = keyjar_init(_op, config.keys) except KeyError: key_arg = {} else: key_arg = {"jwks": jwks, "keys": config.keys} as_args['jwks_name'] = 'static/jwks.json' f = open('static/jwks.json', 'w') f.write(json.dumps(jwks)) f.close() if args.insecure: _op.keyjar.verify_ssl = False else: _op.keyjar.verify_ssl = True as_args['keyjar'] = _op.keyjar as_args['sdb'] = SessionDB( com_args["baseurl"], token_factory=JWTToken('T', keyjar=_op.keyjar, lt_pattern={ 'code': 3600, 'token': 900 }, iss=com_args['baseurl'], sign_alg='RS256'), refresh_token_factory=JWTToken('R', keyjar=_op.keyjar, lt_pattern={'': 24 * 3600}, iss=com_args['baseurl'])) return as_args, key_arg
def main_setup(args, lookup): sys.path.insert(0, ".") config = importlib.import_module(args.config) config.issuer = config.issuer % args.port config.SERVICE_URL = config.SERVICE_URL % args.port # Client data base # cdb = shelve.open(config.CLIENT_DB, writeback=True) cdb = {} ac = AuthnBroker() for authkey, value in list(config.AUTHENTICATION.items()): authn = None # if "UserPassword" == authkey: # from oic.utils.authn.user import UsernamePasswordMako # authn = UsernamePasswordMako(None, "login.mako", LOOKUP, PASSWD, # "authorization") if "NoAuthn" == authkey: from oic.utils.authn.user import NoAuthn authn = NoAuthn(None, user=config.AUTHENTICATION[authkey]["user"]) if authn is not None: ac.add(config.AUTHENTICATION[authkey]["ACR"], authn, config.AUTHENTICATION[authkey]["WEIGHT"]) # dealing with authorization authz = AuthzHandling() kwargs = { "template_lookup": lookup, "template": { "form_post": "form_response.mako" }, } if config.USERINFO == "SIMPLE": # User info is a simple dictionary in this case statically defined in # the configuration file userinfo = UserInfo(config.USERDB) else: userinfo = None # Should I care about verifying the certificates used by other entities if args.insecure: kwargs["verify_ssl"] = False else: kwargs["verify_ssl"] = True uri_schemes = read_uri_schemes('uri-schemes-1.csv') as_args = { "name": config.issuer, "cdb": cdb, "authn_broker": ac, "userinfo": userinfo, "authz": authz, "client_authn": verify_client, "symkey": config.SYM_KEY, "template_lookup": lookup, "template": { "form_post": "form_response.mako" }, "jwks_name": "./static/jwks_{}.json", 'event_db': Events(), } com_args = { "name": config.issuer, # "sdb": SessionDB(config.baseurl), "baseurl": config.baseurl, "cdb": cdb, "authn_broker": ac, "userinfo": userinfo, "authz": authz, "client_authn": verify_client, "symkey": config.SYM_KEY, "template_lookup": lookup, "template": { "form_post": "form_response.mako" }, "jwks_name": "./static/jwks_{}.json", 'uri_schemes': uri_schemes } op_arg = {} try: op_arg["cookie_ttl"] = config.COOKIETTL except AttributeError: pass try: op_arg["cookie_name"] = config.COOKIENAME except AttributeError: pass try: as_args['behavior'] = config.BEHAVIOR except AttributeError: pass # print URLS if args.debug: op_arg["debug"] = True if args.port == 80: _baseurl = config.baseurl else: if config.baseurl.endswith("/"): config.baseurl = config.baseurl[:-1] _baseurl = "%s:%d" % (config.baseurl, args.port) if not _baseurl.endswith("/"): _baseurl += "/" op_arg["baseurl"] = _baseurl # Add own keys for signing/encrypting JWTs try: # a throw-away OP used to do the initial key setup _op = Provider(sdb=SessionDB(com_args["baseurl"]), **com_args) jwks = keyjar_init(_op, config.keys) except KeyError: pass else: op_arg["jwks"] = jwks op_arg["keys"] = config.keys as_args['jwks_uri'] = '{}{}/jwks.json'.format(_baseurl, 'static') as_args['jwks_name'] = 'static/jwks.json' f = open('static/jwks.json', 'w') f.write(json.dumps(jwks)) f.close() as_args['keyjar'] = _op.keyjar as_args['sdb'] = SessionDB(com_args["baseurl"], token_factory=JWTToken('T', keyjar=_op.keyjar, lt_pattern={ 'code': 3600, 'token': 900 }, iss=_baseurl, sign_alg='RS256'), refresh_token_factory=JWTToken( 'R', keyjar=_op.keyjar, lt_pattern={'': 24 * 3600}, iss=_baseurl)) try: op_arg["marg"] = multi_keys(as_args, config.multi_keys) except AttributeError as err: pass return as_args, op_arg, config
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)
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)