Exemple #1
0
    def __init__(self, kty="", alg="", use="", kid="", key=None, x5c=None,
                 x5t="", x5u="", **kwargs):
        self.key = key
        self.extra_args = kwargs

        # want kty, alg, use and kid to be strings
        if isinstance(kty, six.string_types):
            self.kty = kty
        else:
            self.kty = as_unicode(kty)

        if isinstance(alg, six.string_types):
            self.alg = alg
        else:
            self.alg = as_unicode(alg)

        if isinstance(use, six.string_types):
            self.use = use
        else:
            self.use = as_unicode(use)

        if isinstance(kid, six.string_types):
            self.kid = kid
        else:
            self.kid = as_unicode(kid)

        self.x5c = x5c or []
        self.x5t = x5t
        self.x5u = x5u
        self.inactive_since = 0
        self._hash = None
Exemple #2
0
def left_hash(msg, func="HS256"):
    """ 128 bits == 16 bytes """
    if func == 'HS256':
        return as_unicode(b64e(sha256_digest(msg)[:16]))
    elif func == 'HS384':
        return as_unicode(b64e(sha384_digest(msg)[:24]))
    elif func == 'HS512':
        return as_unicode(b64e(sha512_digest(msg)[:32]))
Exemple #3
0
def left_hash(msg, func="HS256"):
    """ 128 bits == 16 bytes """
    if func == 'HS256':
        return as_unicode(b64e(sha256_digest(msg)[:16]))
    elif func == 'HS384':
        return as_unicode(b64e(sha384_digest(msg)[:24]))
    elif func == 'HS512':
        return as_unicode(b64e(sha512_digest(msg)[:32]))
 def request(self, location, fragment_enc=False):
     _l = as_unicode(location)
     _qp = as_unicode(self.to_urlencoded())
     if fragment_enc:
         return "%s#%s" % (_l, _qp)
     else:
         if "?" in location:
             return "%s&%s" % (_l, _qp)
         else:
             return "%s?%s" % (_l, _qp)
Exemple #5
0
 def request(self, location, fragment_enc=False):
     _l = as_unicode(location)
     _qp = as_unicode(self.to_urlencoded())
     if fragment_enc:
         return "%s#%s" % (_l, _qp)
     else:
         if "?" in location:
             return "%s&%s" % (_l, _qp)
         else:
             return "%s?%s" % (_l, _qp)
Exemple #6
0
def elements_to_unicode(b):
    """
    Tries to convert all elements in a list/dict from a byte string to an unicode string
    :param b: list / dict
    :return: list / dict
    """

    if isinstance(b, list):
        return [as_unicode(v) for v in b]

    if isinstance(b, dict):
        conv_dict = dict()
        for key in b.keys():
            conv_dict[key] = as_unicode(b[key])
        return conv_dict
Exemple #7
0
def elements_to_unicode(b):
    """
    Tries to convert all elements in a list/dict from a byte string to an unicode string
    :param b: list / dict
    :return: list / dict
    """

    if isinstance(b, list):
        return [as_unicode(v) for v in b]

    if isinstance(b, dict):
        conv_dict = dict()
        for key in b.keys():
            conv_dict[key] = as_unicode(b[key])
        return conv_dict
Exemple #8
0
def extract_from_request(environ, kwargs=None):
    if kwargs is None:
        kwargs = {}

    request = None
    try:
        request = environ["QUERY_STRING"]
    except KeyError:
        pass
    if not request:
        try:
            request = as_unicode(get_post(environ))
        except KeyError:
            pass
    kwargs["request"] = request
    # authentication information
    try:
        kwargs["authn"] = environ["HTTP_AUTHORIZATION"]
    except KeyError:
        pass
    try:
        kwargs["cookie"] = environ["HTTP_COOKIE"]
    except KeyError:
        pass

    # intended audience
    kwargs["requrl"] = geturl(environ)
    kwargs["url"] = geturl(environ, query=False)
    kwargs["baseurl"] = geturl(environ, query=False, path=False)
    kwargs["path"] = getpath(environ)
    return kwargs
Exemple #9
0
    def encryption_key(self, alg, **kwargs):
        """
        Return an encryption key as per
        http://openid.net/specs/openid-connect-core-1_0.html#Encryption

        :param alg: encryption algorithm
        :param kwargs:
        :return: encryption key as byte string
        """
        if not self.key:
            self.deserialize()

        tsize = ALG2KEYLEN[alg]
        #_keylen = len(self.key)

        if tsize <= 32:
            # SHA256
            _enc_key = sha256_digest(self.key)[:tsize]
        elif tsize <= 48:
            # SHA384
            _enc_key = sha384_digest(self.key)[:tsize]
        elif tsize <= 64:
            # SHA512
            _enc_key = sha512_digest(self.key)[:tsize]
        else:
            raise JWKException("No support for symmetric keys > 512 bits")

        logger.debug('Symmetric encryption key: {}'.format(
            as_unicode(b64e(_enc_key))))

        return _enc_key
Exemple #10
0
def verify_self_signed_jwks(sjwt):
    """
    Verify the signature of a signed JWT containing a JWKS.
    The JWT is signed by one of the keys in the JWKS. 
    In the JWT the JWKS is stored using this format ::
    
        'jwks': {
            'keys': [ ]
        }

    :param sjwt: Signed Jason Web Token
    :return: Dictionary containing 'jwks' (the JWKS) and 'iss' (the issuer of 
        the JWT)
    """

    _jws = factory(sjwt)
    _json = _jws.jwt.part[1]
    _body = json.loads(as_unicode(_json))
    iss = _body['iss']
    _jwks = _body['jwks']

    _kj = jwks_to_keyjar(_jwks, iss)

    try:
        _kid = _jws.jwt.headers['kid']
    except KeyError:
        _keys = _kj.get_signing_key(owner=iss)
    else:
        _keys = _kj.get_signing_key(owner=iss, kid=_kid)

    _ver = _jws.verify_compact(sjwt, _keys)
    return {'jwks': _ver['jwks'], 'iss': iss}
def extract_from_request(environ, kwargs=None):
    if kwargs is None:
        kwargs = {}

    request = None
    try:
        request = environ["QUERY_STRING"]
    except KeyError:
        pass
    if not request:
        try:
            request = as_unicode(get_post(environ))
        except KeyError:
            pass
    kwargs["request"] = request
    # authentication information
    try:
        kwargs["authn"] = environ["HTTP_AUTHORIZATION"]
    except KeyError:
        pass
    try:
        kwargs["cookie"] = environ["HTTP_COOKIE"]
    except KeyError:
        pass

    # intended audience
    kwargs["requrl"] = geturl(environ)
    kwargs["url"] = geturl(environ, query=False)
    kwargs["baseurl"] = geturl(environ, query=False, path=False)
    kwargs["path"] = getpath(environ)
    return kwargs
Exemple #12
0
    def backchannel_logout(self, **kwargs):
        logger.debug('Back channel logout: {}'.format(kwargs))
        self.sh['conv'].events.store(EV_HTTP_REQUEST, kwargs)
        if cherrypy.request.process_request_body is True:
            _request = as_unicode(cherrypy.request.body.read())
            if _request:
                logger.info('back_channel logout request: {}'.format(_request))
                if kwargs['entity_id'] != self.tester.conv.entity.entity_id:
                    self.sh['conv'].events.store(EV_FAULT, "Not for me!")
                    logger.debug('Not for me')
                    self.opresult()
                else:
                    return self._endpoint(ref='backchannel_logout',
                                          request=_request)
            else:
                _request_args = cherrypy.request.params
                if not _request_args:
                    raise cherrypy.HTTPError(
                        400, 'Missing Back channel Logout request body')

                logger.info('back_channel logout request_args: {}'.format(
                    _request_args))
                if kwargs['entity_id'] != self.tester.conv.entity.entity_id:
                    self.sh['conv'].events.store(EV_FAULT, "Not for me!")
                    logger.debug('Not for me')
                    self.opresult()
                else:
                    return self._endpoint(ref='backchannel_logout',
                                          request_args=_request_args)
        else:
            raise cherrypy.HTTPError(
                400, 'Missing Back channel Logout request body')
Exemple #13
0
def static(environ, start_response, path):
    logger.info("[static]sending: %s" % (path,))

    headers = []

    try:
        bytes = open(path, 'rb').read()
        if path.endswith(".ico"):
            headers.append(('Content-Type', "image/x-icon"))
        elif path.endswith(".html"):
            headers.append(('Content-Type', 'text/html'))
        elif path.endswith(".json"):
            headers.append(('Content-Type', 'application/json'))
        elif path.endswith(".txt"):
            headers.append(('Content-Type', 'text/plain'))
        elif path.endswith(".css"):
            headers.append(('Content-Type', 'text/css'))
        elif path.endswith(".tar"):
            headers.append(('Content-Type', 'application/x-tar'))
        else:
            headers.append(('Content-Type', 'text/plain'))
            start_response('200 OK', headers)
        try:
            text = as_unicode(bytes)
            text = as_bytes(text.encode('utf8'))
        except (ValueError, UnicodeDecodeError):
            text = bytes
        except AttributeError:
            text = bytes
        resp = do_response(Response, text)
    except IOError:
        resp = do_response(NotFound, path)

    return resp(environ, start_response)
Exemple #14
0
    def encryption_key(self, alg, **kwargs):
        """
        Return an encryption key as per
        http://openid.net/specs/openid-connect-core-1_0.html#Encryption

        :param alg: encryption algorithm
        :param kwargs:
        :return: encryption key as byte string
        """
        if not self.key:
            self.deserialize()

        tsize = ALG2KEYLEN[alg]
        # _keylen = len(self.key)

        if tsize <= 32:
            # SHA256
            _enc_key = sha256_digest(self.key)[:tsize]
        elif tsize <= 48:
            # SHA384
            _enc_key = sha384_digest(self.key)[:tsize]
        elif tsize <= 64:
            # SHA512
            _enc_key = sha512_digest(self.key)[:tsize]
        else:
            raise JWKException("No support for symmetric keys > 512 bits")

        logger.debug('Symmetric encryption key: {}'.format(
            as_unicode(b64e(_enc_key))))

        return _enc_key
Exemple #15
0
    def registration(self, **kwargs):
        logger.debug('Request headers: {}'.format(cherrypy.request.headers))
        if cherrypy.request.method == "OPTIONS":
            cherrypy_cors.preflight(
                allowed_methods=["POST", "GET"],
                origins='*',
                allowed_headers=['Authorization', 'content-type'])
        elif cherrypy.request.method == "GET":
            _cinfo = self.op.cdb[kwargs['client_id']]
            for attr in ['redirect_uris', 'post_logout_redirect_uris']:
                try:
                    _cinfo[attr] = unpack_redirect_uri(_cinfo[attr])
                except KeyError:
                    pass
            rr = RegistrationResponse(**_cinfo)
            cherrypy.response.headers['Content-Type'] = 'application/json'
            return as_bytes(json.dumps(rr.to_dict()))
        else:
            logger.debug('ClientRegistration kwargs: {}'.format(kwargs))
            _request = None

            if cherrypy.request.process_request_body is True:
                _request = as_unicode(cherrypy.request.body.read())
                logger.debug('request_body: {}'.format(_request))

            try:
                if _request:
                    resp = self.op.registration_endpoint(_request)
                else:
                    resp = self.op.registration_endpoint(kwargs)
            except Exception as err:
                logger.error(err)
                raise cherrypy.HTTPError(message=str(err))

            return conv_response(resp)
Exemple #16
0
def check_key_availability(inst, jwt):
    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemple #17
0
def modified_idtoken_hint(oper, arg):
    """
    Context:
        EndSession
    Action:
        Sets the 'id_token_hint' argument in a end_session request.
        The value of the argument is a incorrect signed JWT.
    Example:
        "create_idtoken_hint_other_issuer": null
    """
    res = get_signed_id_tokens(oper.conv)
    if res:
        _jws = jws_factory(res[-1])

        header = as_unicode(b64e(as_bytes(json.dumps({'alg': 'none'}))))
        oper.req_args["id_token_hint"] = '.'.join(
            [header, as_unicode(_jws.jwt.b64part[1]), ''])
Exemple #18
0
 def jwks(self):
     self._uptodate()
     keys = list()
     for k in self._keys:
         key = k.to_dict()
         for k, v in key.items():
             key[k] = as_unicode(v)
         keys.append(key)
     return json.dumps({"keys": keys})
Exemple #19
0
 def jwks(self):
     self._uptodate()
     keys = list()
     for k in self._keys:
         key = k.to_dict()
         for k, v in key.items():
             key[k] = as_unicode(v)
         keys.append(key)
     return json.dumps({"keys": keys})
Exemple #20
0
 def request(self, location, fragment_enc=False):
     """
     Given a URL this method will add a fragment, a query part or extend
     a query part if it already exists with the information in this instance.
     
     :param location: A URL 
     :param fragment_enc: Whether the information should be placed in a
         fragment (True) or in a query part (False)
     :return: The extended URL 
     """
     _l = as_unicode(location)
     _qp = as_unicode(self.to_urlencoded())
     if fragment_enc:
         return "%s#%s" % (_l, _qp)
     else:
         if "?" in location:
             return "%s&%s" % (_l, _qp)
         else:
             return "%s?%s" % (_l, _qp)
Exemple #21
0
    def val_hash(self, alg):
        halg = "HS%s" % alg[-3:]

        for attr, hash_attr in self.hashable.items():
            try:
                self[hash_attr] = jws.left_hash(as_unicode(self[attr]), halg)
            except KeyError:
                pass
            else:
                del self[attr]
Exemple #22
0
def is_lesser(a, b):
    """
    Verify that a in lesser then b
    :param a:
    :param b:
    :return: True or False
    """


    if type(a) != type(b):
        if PY2:  # one might be unicode and the other str
            return as_unicode(a) == as_unicode(b)

        return False

    if isinstance(a, string_types) and isinstance(b, string_types):
        return a == b
    elif isinstance(a, bool) and isinstance(b, bool):
        return a == b
    elif isinstance(a, list) and isinstance(b, list):
        for element in a:
            flag = 0
            for e in b:
                if is_lesser(element, e):
                    flag = 1
                    break
            if not flag:
                return False
        return True
    elif isinstance(a, dict) and isinstance(b, dict):
        if is_lesser(list(a.keys()), list(b.keys())):
            for key, val in a.items():
                if not is_lesser(val, b[key]):
                    return False
            return True
        return False
    elif isinstance(a, int) and isinstance(b, int):
        return a <= b
    elif isinstance(a, float) and isinstance(b, float):
        return a <= b

    return False
Exemple #23
0
def is_lesser(a, b):
    """
    Verify that a is <= then b
    
    :param a: An item
    :param b: Another item
    :return: True or False
    """

    if type(a) != type(b):
        if PY2:  # one might be unicode and the other str
            return as_unicode(a) == as_unicode(b)

        return False

    if isinstance(a, string_types) and isinstance(b, string_types):
        return a == b
    elif isinstance(a, bool) and isinstance(b, bool):
        return a == b
    elif isinstance(a, list) and isinstance(b, list):
        for element in a:
            flag = 0
            for e in b:
                if is_lesser(element, e):
                    flag = 1
                    break
            if not flag:
                return False
        return True
    elif isinstance(a, dict) and isinstance(b, dict):
        if is_lesser(list(a.keys()), list(b.keys())):
            for key, val in a.items():
                if not is_lesser(val, b[key]):
                    return False
            return True
        return False
    elif isinstance(a, int) and isinstance(b, int):
        return a <= b
    elif isinstance(a, float) and isinstance(b, float):
        return a <= b

    return False
Exemple #24
0
def test_pack_metadata_statement_other_alg():
    _keyjar = build_keyjar(KEYDEFS)[1]
    op = Operator(keyjar=_keyjar, iss='https://example.com/')
    req = MetadataStatement(issuer='https://example.org/op')
    sms = op.pack_metadata_statement(req, alg='ES256')
    assert sms  # Should be a signed JWT
    _jwt = factory(sms)
    _body = json.loads(as_unicode(_jwt.jwt.part[1]))
    assert _body['iss'] == 'https://example.com/'
    # verify signature
    r = _jwt.verify_compact(sms, _keyjar.get_signing_key())
    assert r
Exemple #25
0
    def test_create_fed_provider_info(self):
        fedpi = self.op.create_fed_providerinfo()

        assert 'signing_keys' not in fedpi

        assert len(fedpi['metadata_statements']) == 1
        _js = jws.factory(fedpi['metadata_statements'][FO['swamid']])
        assert _js
        assert _js.jwt.headers['alg'] == 'RS256'
        _body = json.loads(as_unicode(_js.jwt.part[1]))
        assert _body[
            'iss'] == self.op.federation_entity.signer.signing_service.iss
Exemple #26
0
 def jwks(self, private=False):
     self._uptodate()
     keys = list()
     for k in self._keys:
         if private:
             key = k.serialize(private)
         else:
             key = k.to_dict()
             for k, v in key.items():
                 key[k] = as_unicode(v)
         keys.append(key)
     return json.dumps({"keys": keys})
Exemple #27
0
 def jwks(self, private=False):
     self._uptodate()
     keys = list()
     for k in self._keys:
         if private:
             key = k.serialize(private)
         else:
             key = k.to_dict()
             for k, v in key.items():
                 key[k] = as_unicode(v)
         keys.append(key)
     return json.dumps({"keys": keys})
Exemple #28
0
def test_encryption_key():
    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWBw'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A192KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A256KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86vweU_Pi62X8'

    ek = sha256_digest(
        'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY')[
         :16]
    assert as_unicode(b64e(ek)) == 'yf_UUkAFZ8Pn_prxPPgu9w'

    sk = SYMKey(
        key='YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY')
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == as_unicode(b64e(ek))
Exemple #29
0
def test_encryption_key():
    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWBw'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A192KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A256KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86vweU_Pi62X8'

    ek = sha256_digest(
        'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY'
    )[:16]
    assert as_unicode(b64e(ek)) == 'yf_UUkAFZ8Pn_prxPPgu9w'

    sk = SYMKey(
        key=
        'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY'
    )
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == as_unicode(b64e(ek))
Exemple #30
0
def get_client_id(cdb, req, authn):
    """
    Verify the client and return the client id

    :param req: The request
    :param authn: Authentication information from the HTTP header
    :return:
    """

    logger.debug("REQ: %s" % req.to_dict())
    if authn:
        if authn.startswith("Basic "):
            logger.debug("Basic auth")
            (_id, _secret) = base64.b64decode(
                authn[6:].encode("utf-8")).decode("utf-8").split(":")

            _id = as_unicode(_id)
            if _id not in cdb:
                logger.debug("Unknown client_id")
                raise FailedAuthentication("Unknown client_id")
            else:
                if not valid_client_info(cdb[_id]):
                    logger.debug("Invalid Client info")
                    raise FailedAuthentication("Invalid Client")

                if _secret != cdb[_id]["client_secret"]:
                    logger.debug("Incorrect secret")
                    raise FailedAuthentication("Incorrect secret")
        else:
            if authn[:6].lower() == "bearer":
                logger.debug("Bearer auth")
                _token = authn[7:]
            else:
                raise FailedAuthentication("AuthZ type I don't know")

            try:
                _id = cdb[_token]
            except KeyError:
                logger.debug("Unknown access token")
                raise FailedAuthentication("Unknown access token")
    else:
        try:
            _id = str(req["client_id"])
            if _id not in cdb:
                logger.debug("Unknown client_id")
                raise FailedAuthentication("Unknown client_id")
            if not valid_client_info(cdb[_id]):
                raise FailedAuthentication("Invalid client_id")
        except KeyError:
            raise FailedAuthentication("Missing client_id")

    return _id
Exemple #31
0
def get_client_id(cdb, req, authn):
    """
    Verify the client and return the client id

    :param req: The request
    :param authn: Authentication information from the HTTP header
    :return:
    """

    logger.debug("REQ: %s" % req.to_dict())
    if authn:
        if authn.startswith("Basic "):
            logger.debug("Basic auth")
            (_id, _secret) = base64.b64decode(
                authn[6:].encode("utf-8")).decode("utf-8").split(":")

            _id = as_unicode(_id)
            if _id not in cdb:
                logger.debug("Unknown client_id")
                raise FailedAuthentication("Unknown client_id")
            else:
                if not valid_client_info(cdb[_id]):
                    logger.debug("Invalid Client info")
                    raise FailedAuthentication("Invalid Client")

                if _secret != cdb[_id]["client_secret"]:
                    logger.debug("Incorrect secret")
                    raise FailedAuthentication("Incorrect secret")
        else:
            if authn[:6].lower() == "bearer":
                logger.debug("Bearer auth")
                _token = authn[7:]
            else:
                raise FailedAuthentication("AuthZ type I don't know")

            try:
                _id = cdb[_token]
            except KeyError:
                logger.debug("Unknown access token")
                raise FailedAuthentication("Unknown access token")
    else:
        try:
            _id = str(req["client_id"])
            if _id not in cdb:
                logger.debug("Unknown client_id")
                raise FailedAuthentication("Unknown client_id")
            if not valid_client_info(cdb[_id]):
                raise FailedAuthentication("Invalid client_id")
        except KeyError:
            raise FailedAuthentication("Missing client_id")

    return _id
Exemple #32
0
    def payload(self):
        _msg = as_unicode(self.part[1])

        # If not JSON web token assume JSON
        if "cty" in self.headers and self.headers["cty"].lower() != "jwt":
            pass
        else:
            try:
                _msg = json.loads(_msg)
            except ValueError:
                pass

        return _msg
Exemple #33
0
    def payload(self):
        _msg = as_unicode(self.part[1])

        # If not JSON web token assume JSON
        if "cty" in self.headers and self.headers["cty"].lower() != "jwt":
            pass
        else:
            try:
                _msg = json.loads(_msg)
            except ValueError:
                pass

        return _msg
Exemple #34
0
    def test_provider_endpoint(self):
        pi_resp = self.op.providerinfo_endpoint()

        assert isinstance(pi_resp, Response)
        assert pi_resp.status == "200 OK"
        _info = json.loads(pi_resp.message)
        assert list(_info['metadata_statements'].keys()) == [FO['swamid']]
        _js = jws.factory(_info['metadata_statements'][FO['swamid']])
        assert _js
        assert _js.jwt.headers['alg'] == 'RS256'
        _body = json.loads(as_unicode(_js.jwt.part[1]))
        assert _body[
            'iss'] == self.op.federation_entity.signer.signing_service.iss
Exemple #35
0
 def index(self, op, **kwargs):
     if cherrypy.request.method == "OPTIONS":
         cherrypy_cors.preflight(
             allowed_methods=["POST"], origins='*',
             allowed_headers=['Authorization', 'content-type'])
     else:
         logger.debug('AccessTokenRequest')
         try:
             authn = cherrypy.request.headers['Authorization']
         except KeyError:
             authn = None
         logger.debug('Authorization: {}'.format(authn))
         resp = op.token_endpoint(as_unicode(kwargs), authn, 'dict')
         return conv_response(resp)
Exemple #36
0
 def index(self, op, **kwargs):
     if cherrypy.request.method == "OPTIONS":
         cherrypy_cors.preflight(
             allowed_methods=["POST"], origins='*',
             allowed_headers=['Authorization', 'content-type'])
     else:
         store_request(op, 'AccessTokenRequest')
         try:
             authn = cherrypy.request.headers['Authorization']
         except KeyError:
             authn = None
         logger.debug('Authorization: {}'.format(authn))
         resp = op.token_endpoint(as_unicode(kwargs), authn, 'dict')
         if resp.status_code < 300:
             set_content_type(resp, 'application/json')
         return conv_response(op, resp)
Exemple #37
0
 def index(self, op):
     if cherrypy.request.method == "OPTIONS":
         logger.debug('Request headers: {}'.format(cherrypy.request.headers))
         cherrypy_cors.preflight(
             allowed_methods=["POST"], origins='*',
             allowed_headers=['Authorization', 'content-type'])
     else:
         logger.debug('ClientRegistration request')
         if cherrypy.request.process_request_body is True:
             _request = cherrypy.request.body.read()
         else:
             raise cherrypy.HTTPError(400,
                                      'Missing Client registration body')
         logger.debug('request_body: {}'.format(_request))
         resp = op.registration_endpoint(as_unicode(_request))
         return conv_response(resp)
Exemple #38
0
def check_key_availability(inst, jwt):
    """
    If the server is restarted it will NOT load keys from jwks_uris for
    all the clients that has been registered. So this function is there
    to get a clients keys when needed.

    :param inst: OP instance
    :param jwt: A JWT that has to be verified or decrypted
    """

    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemple #39
0
def test_pack_metadata_statement():
    jb = FSJWKSBundle('', None, 'fo_jwks',
                      key_conv={'to': quote_plus, 'from': unquote_plus})
    _keyjar = build_keyjar(KEYDEFS)[1]
    op = Operator(keyjar=_keyjar, jwks_bundle=jb, iss='https://example.com/')
    req = MetadataStatement(issuer='https://example.org/op')
    sms = op.pack_metadata_statement(req)
    assert sms  # Should be a signed JWT
    _jwt = factory(sms)
    assert _jwt
    assert _jwt.jwt.headers['alg'] == 'RS256'
    _body = json.loads(as_unicode(_jwt.jwt.part[1]))
    assert _body['iss'] == op.iss
    assert _body['issuer'] == 'https://example.org/op'
    # verify signature
    r = _jwt.verify_compact(sms, _keyjar.get_signing_key())
    assert r
Exemple #40
0
def check_key_availability(inst, jwt):
    """
    If the server is restarted it will NOT load keys from jwks_uris for
    all the clients that has been registered. So this function is there
    to get a clients keys when needed.

    :param inst: OP instance
    :param jwt: A JWT that has to be verified or decrypted
    """

    _rj = jws.factory(jwt)
    payload = json.loads(as_unicode(_rj.jwt.part[1]))
    _cid = payload['iss']
    if _cid not in inst.keyjar:
        cinfo = inst.cdb[_cid]
        inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig'])
        inst.keyjar.add(_cid, cinfo['jwks_uri'])
Exemple #41
0
    def authenticated_as(self, cookie=None, authorization="", **kwargs):
        """

        :param cookie: A HTTP Cookie
        :param authorization: The HTTP Authorization header
        :param args: extra args
        :param kwargs: extra key word arguments
        :return:
        """
        if authorization.startswith("Basic"):
            authorization = authorization[6:]

        _decoded = as_unicode(base64.b64decode(authorization))
        (user, pwd) = _decoded.split(":")
        user = unquote_plus(user)
        pwd = unquote_plus(pwd)
        self.verify_password(user, pwd)
        return {"uid": user}, time.time()
Exemple #42
0
 def jwks(self, private=False):
     """
     Create a JWKS
     
     :param private: Whether private key information should be included.
     :return: A JWKS representation of the keys in this bundle 
     """
     self._uptodate()
     keys = list()
     for k in self._keys:
         if private:
             key = k.serialize(private)
         else:
             key = k.to_dict()
             for k, v in key.items():
                 key[k] = as_unicode(v)
         keys.append(key)
     return json.dumps({"keys": keys})
Exemple #43
0
 def index(self, op):
     if cherrypy.request.method == "OPTIONS":
         logger.debug('Request headers: {}'.format(cherrypy.request.headers))
         cherrypy_cors.preflight(
             allowed_methods=["POST"], origins='*',
             allowed_headers=['Authorization', 'content-type'])
     else:
         store_request(op, 'ClientRegistration')
         if cherrypy.request.process_request_body is True:
             _request = cherrypy.request.body.read()
         else:
             raise cherrypy.HTTPError(400,
                                      'Missing Client registration body')
         logger.debug('request_body: {}'.format(_request))
         resp = op.registration_endpoint(as_unicode(_request))
         if resp.status_code < 300:
             set_content_type(resp, 'application/json')
         return conv_response(op, resp)
Exemple #44
0
    def authenticated_as(self, cookie=None, authorization="", **kwargs):
        """

        :param cookie: A HTTP Cookie
        :param authorization: The HTTP Authorization header
        :param args: extra args
        :param kwargs: extra key word arguments
        :return:
        """
        if authorization.startswith("Basic"):
            authorization = authorization[6:]

        _decoded = as_unicode(base64.b64decode(authorization))
        (user, pwd) = _decoded.split(":")
        user = unquote_plus(user)
        pwd = unquote_plus(pwd)
        self.verify_password(user, pwd)
        return {"uid": user}, time.time()
Exemple #45
0
 def index(self, op, **kwargs):
     if cherrypy.request.method == "OPTIONS":
         cherrypy_cors.preflight(
             allowed_methods=["GET", "POST"], origins='*',
             allowed_headers=['Authorization', 'content-type'])
     else:
         store_request(op, 'CheckSessionIframe')
         logger.debug('CheckSessionIframe: {}'.format(kwargs))
         if cherrypy.request.method == "POST":
             _req = cherrypy.request.body.read()
             kwargs = json.loads(as_unicode(_req))
             # will contain client_id and origin
             if kwargs['client_id'] not in op.cdb:
                 return b'error'
             # Should have some intelligent check for origin
             return b'ok'
         else:
             doc = open('templates/check_session_iframe.html').read()
             return as_bytes(doc)
Exemple #46
0
    def __call__(self, req, **kwargs):
        r = requests.post(self.url, json=req, verify=False)
        if 200 <= r.status_code < 300:
            _jw = factory(r.text)

            # First Just checking the issuer ID *not* verifying the Signature
            body = json.loads(as_unicode(_jw.jwt.part[1]))
            assert body['iss'] == self.iss

            # Now verifying the signature
            try:
                _jw.verify_compact(r.text,
                                   self.keyjar.get_verify_key(owner=self.iss))
            except AssertionError:
                raise JWSException('JWS signature verification error')

            return r.text
        else:
            raise SigningServiceError("{}: {}".format(r.status_code, r.text))
    def do_left_hash(cls, input, alg, base64_func):
        hash_funcs = { 'HS256' : [16, jwk.sha256_digest],
                       'hs256' : [16, jwk.sha256_digest],
                       'RS256' : [16, jwk.sha256_digest],
                       'rs256' : [16, jwk.sha256_digest],
                       'HS384' : [24, jwk.sha384_digest],
                       'hs384' : [24, jwk.sha384_digest],
                       'RS384' : [24, jwk.sha384_digest],
                       'rs384' : [24, jwk.sha384_digest],
                       'HS512' : [32, jwk.sha512_digest],
                       'hs512' : [32, jwk.sha512_digest],
                       'RS512' : [32, jwk.sha512_digest],
                       'rs512' : [32, jwk.sha512_digest]
                       }

        hash_info = hash_funcs.get(alg)
        if hash_info == None:
            raise OAuth2ProtocolError("unknown hash algorithm: " + alg)

        hash_size, hash_func = hash_info
        return jwkest.as_unicode(base64_func(hash_func(input)[:hash_size]))
Exemple #48
0
 def serialize(self, private=True):
     res = self.common()
     res["k"] = as_unicode(b64e(bytes(self.key)))
     return res
    try:
        jwks = keyjar_init(OAS, config.keys, kid_template="op%d")

    except Exception as err:
        LOGGER.error("Key setup failed: {}".format(err))
        print("Key setup failed: {}".format(err))
        exit()
        #OAS.key_setup("static", sig={"format": "jwk", "alg": "rsa"})
    else:
        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:
Exemple #50
0
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = as_unicode(_jw.decrypt(txt, dkeys))
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = _jwt.payload()
                _header = _jwt.headers

                logger.debug("Raw JSON: {}".format(jso))
                logger.debug("header: {}".format(_header))
                if _header["alg"] == "none":
                    pass
                else:
                    if keyjar:
                        logger.debug("Issuer keys: {}".format(keyjar.keys()))
                        try:
                            _iss = jso["iss"]
                        except KeyError:
                            pass
                        else:
                            if "jku" in _header:
                                if not keyjar.find(_header["jku"], _iss):
                                    # This is really questionable
                                    try:
                                        if kwargs["trusting"]:
                                            keyjar.add(jso["iss"],
                                                       _header["jku"])
                                    except KeyError:
                                        pass

                            if "kid" in _header and _header["kid"]:
                                _jw["kid"] = _header["kid"]
                                try:
                                    _key = keyjar.get_key_by_kid(_header["kid"],
                                                                 _iss)
                                    if _key:
                                        key.append(_key)
                                except KeyError:
                                    pass

                        try:
                            self._add_key(keyjar, kwargs["opponent_id"], key)
                        except KeyError:
                            pass

                    if verify:
                        if keyjar:
                            for ent in ["iss", "aud", "client_id"]:
                                if ent not in jso:
                                    continue
                                if ent == "aud":
                                    # list or basestring
                                    if isinstance(jso["aud"], six.string_types):
                                        _aud = [jso["aud"]]
                                    else:
                                        _aud = jso["aud"]
                                    for _e in _aud:
                                        self._add_key(keyjar, _e, key)
                                else:
                                    self._add_key(keyjar, jso[ent], key)

                        if "alg" in _header and _header["alg"] != "none":
                            if not key:
                                raise MissingSigningKey(
                                        "alg=%s" % _header["alg"])

                        logger.debug("Verify keys: {}".format(key))
                        _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = as_unicode(_jw.decrypt(txt, dkeys))
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = _jwt.payload()
                _header = _jwt.headers

                logger.debug("Raw JSON: {}".format(jso))
                logger.debug("header: {}".format(_header))
                if _header["alg"] == "none":
                    pass
                elif verify:
                    if keyjar:
                        key = self.get_verify_keys(keyjar, key, jso, _header,
                                                   _jw, **kwargs)

                    if "alg" in _header and _header["alg"] != "none":
                        if not key:
                            raise MissingSigningKey(
                                "alg=%s" % _header["alg"])

                    logger.debug("Verify keys: {}".format(key))
                    try:
                        _jw.verify_compact(txt, key)
                    except NoSuitableSigningKeys:
                        if keyjar:
                            update_keyjar(keyjar)
                            key = self.get_verify_keys(keyjar, key, jso,
                                                       _header, _jw, **kwargs)
                            _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)