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, {}
Example #2
0
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
Example #3
0
    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}
Example #4
0
    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
Example #5
0
    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)
Example #6
0
    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)
Example #9
0
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']:
Example #10
0
    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