def add_state(self, request_args=None, **kwargs): if 'state' not in request_args: request_args['state'] = rndstr(32) # As a side effect bind logout state to session state self.store_logout_state2state(request_args['state'], kwargs['state']) return request_args, {}
def construct_request_uri(local_dir, base_path, **kwargs): """ Constructs a special redirect_uri to be used when communicating with one OP. Each OP should get their own redirect_uris. :param local_dir: Local directory in which to place the file :param base_path: Base URL to start with :param kwargs: :return: 2-tuple with (filename, url) """ _filedir = local_dir if not os.path.isdir(_filedir): os.makedirs(_filedir) _webpath = base_path _name = rndstr(10) + ".jwt" filename = os.path.join(_filedir, _name) while os.path.exists(filename): _name = rndstr(10) filename = os.path.join(_filedir, _name) _webname = "%s%s" % (_webpath, _name) return filename, _webname
def init_authorization(self, client=None, state='', req_args=None): """ Constructs the URL that will redirect the user to the authorization endpoint of the OP/AS. :param client: A Client instance :param req_args: Non-default Request arguments :return: A dictionary with 2 keys: **url** The authorization redirect URL and **state** the key to the session information in the state data store. """ if not client: if state: client = self.get_client_from_session_key(state) else: raise ValueError('Missing state/session key') service_context = client.service_context _nonce = rndstr(24) request_args = { 'redirect_uri': service_context.get('redirect_uris')[0], 'scope': service_context.get('behaviour')['scope'], 'response_type': service_context.get('behaviour')['response_types'][0], 'nonce': _nonce } _req_args = service_context.config.get("request_args") if _req_args: if 'claims' in _req_args: _req_args["claims"] = Claims(**_req_args["claims"]) request_args.update(_req_args) if req_args is not None: request_args.update(req_args) # Need a new state for a new authorization request _state = client.session_interface.create_state( service_context.get('issuer')) request_args['state'] = _state client.session_interface.store_nonce2state(_nonce, _state) logger.debug('Authorization request args: {}'.format(request_args)) _srv = client.service['authorization'] _info = _srv.get_request_parameters(request_args=request_args) logger.debug('Authorization info: {}'.format(_info)) return {'url': _info['url'], 'state': _state}
def create_state(self, iss, key=''): """ Create a State and assign some value to it. :param iss: The issuer :param key: A key to use to access the state """ if not key: key = rndstr(32) else: if key.startswith('__') and key.endswith('__'): raise ValueError( 'Invalid format. Leading and trailing "__" not allowed') _state = State(iss=iss) self.state_db.set(key, _state.to_json()) return key
def __init__(self, symkey='', seed_file='seed.txt', cookie=None): self.symkey = as_bytes(symkey) for attr, default in {'path':'', 'domain':'', 'max_age':0}.items(): if attr not in cookie: cookie[attr] = default self.cookie = cookie # Need to be able to restart the OP and still use the same seed if os.path.isfile(seed_file): _seed = open(seed_file).read() else: _seed = rndstr(48) with open('seed.txt', "w") as f: f.write(_seed) self.seed= as_bytes(_seed)
def init_srv(self, srv): """ Make sure the server has the necessary attributes :param srv: A server instance """ if not srv: return self.srv = srv # verify that the server instance has a cymkey attribute symkey = getattr(self.srv, 'symkey', None) if symkey is not None and symkey == "": msg = "CookieDealer.srv.symkey can not be an empty value" raise ImproperlyConfigured(msg) # if there is no 'sed' attribute defined create one if not getattr(srv, 'seed', None): setattr(srv, 'seed', rndstr().encode("utf-8"))
def oidc_pre_construct(self, request_args=None, post_args=None, **kwargs): if request_args is None: request_args = {} try: _rt = request_args["response_type"] except KeyError: _rt = self.service_context.get('behaviour')['response_types'][0] request_args["response_type"] = _rt # For OIDC 'openid' is required in scope if 'scope' not in request_args: request_args['scope'] = self.service_context.get('behaviour').get( "scope", ["openid"]) elif 'openid' not in request_args['scope']: request_args['scope'].append('openid') # 'code' and/or 'id_token' in response_type means an ID Roken # will eventually be returnedm, hence the need for a nonce if "code" in _rt or "id_token" in _rt: if "nonce" not in request_args: request_args["nonce"] = rndstr(32) if post_args is None: post_args = {} for attr in ["request_object_signing_alg", "algorithm", 'sig_kid']: try: post_args[attr] = kwargs[attr] except KeyError: pass else: del kwargs[attr] if "request_method" in kwargs: if kwargs["request_method"] == "reference": post_args['request_param'] = "request_uri" else: post_args['request_param'] = "request" del kwargs["request_method"] return request_args, post_args
def assertion_jwt(client_id, keys, audience, algorithm, lifetime=600): """ Create a signed Json Web Token containing some information. :param client_id: The Client ID :param keys: Signing keys :param audience: Who is the receivers for this assertion :param algorithm: Signing algorithm :param lifetime: The lifetime of the signed Json Web Token :return: A Signed Json Web Token """ _now = utc_time_sans_frac() _token = AuthnToken(iss=client_id, sub=client_id, aud=audience, jti=rndstr(32), exp=_now + lifetime, iat=_now) LOGGER.debug('AuthnToken: %s', _token.to_dict()) return _token.to_jwt(key=keys, algorithm=algorithm)
from oidcservice.service import build_services from oidcservice.service_context import ServiceContext from fedoidcservice.service import factory KEYDEFS = [{ "type": "RSA", "key": '', "use": ["sig"] }, { "type": "EC", "crv": "P-256", "use": ["sig"] }] SYMKEY = rndstr(16) TOOL_ISS = 'https://localhost' ALL = [ 'https://swamid.sunet.se', 'https://www.feide.no', 'https://sunet.se', 'https://uninett.no', 'https://sunet.se/op', 'https://foodle.uninett.no' ] _path = os.path.realpath(__file__) root_dir, _fname = os.path.split(_path) FEDENT = create_federation_entities(ALL, KEYDEFS, root_dir=root_dir) fo_keybundle = JWKSBundle('') for iss in ['https://swamid.sunet.se', 'https://www.feide.no']:
def __init__(self, base_url, client_configs=None, services=None, keyjar=None, hash_seed="", verify_ssl=True, client_authn_factory=None, client_cls=None, state_db=None, http_lib=None, httpc_params=None, **kwargs): self.base_url = base_url if hash_seed: self.hash_seed = as_bytes(hash_seed) else: self.hash_seed = as_bytes(rndstr(32)) _jwks_path = kwargs.get('jwks_path') if keyjar is None: self.keyjar = init_key_jar(**DEFAULT_RP_KEY_DEFS, issuer_id='') self.keyjar.import_jwks_as_json( self.keyjar.export_jwks_as_json(True, ''), base_url) if _jwks_path is None: _jwks_path = DEFAULT_RP_KEY_DEFS['public_path'] else: self.keyjar = keyjar if _jwks_path: self.jwks_uri = add_path(base_url, _jwks_path) else: self.jwks_uri = "" if len(self.keyjar): self.jwks = self.keyjar.export_jwks() else: self.jwks = {} if state_db: self.state_db = state_db else: self.state_db = InMemoryStateDataBase() # self.session_interface = StateInterface(self.state_db) self.extra = kwargs self.client_cls = client_cls or oidc.RP if services is None: self.services = DEFAULT_SEVICES else: self.services = services self.client_authn_factory = client_authn_factory if client_configs is None: self.client_configs = DEFAULT_CLIENT_CONFIGS else: self.client_configs = client_configs # keep track on which RP instance that serves with OP self.issuer2rp = {} self.hash2issuer = {} self.httplib = http_lib if not httpc_params: self.httpc_params = {'verify': verify_ssl} else: self.httpc_params = httpc_params if not self.keyjar.httpc_params: self.keyjar.httpc_params = self.httpc_params