Example #1
0
def test_create_fo_keys_bundle():
    jb = JWKSBundle(ORGOP.iss, ORGOP.keyjar)
    jb[FOP.iss] = FOP.keyjar
    jb[FO1P.iss] = FO1P.keyjar
    sb = jb.create_signed_bundle()
    _jw = jws.factory(sb)
    assert _jw
Example #2
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}
Example #3
0
def test_sign_encrypt_id_token():
    client_info = RegistrationResponse(id_token_signed_response_alg='RS512',
                                       client_id='client_1')
    session_info = {
        'authn_req': AREQN,
        'sub': 'sub',
        'authn_event': {
            "authn_info": 'loa2',
            "authn_time": time.time()
        }
    }

    ENDPOINT_CONTEXT.jwx_def["signing_alg"] = {'id_token': 'RS384'}
    ENDPOINT_CONTEXT.cdb['client_1'] = client_info.to_dict()

    _token = sign_encrypt_id_token(ENDPOINT_CONTEXT,
                                   session_info,
                                   'client_1',
                                   sign=True)
    assert _token

    _jws = jws.factory(_token)

    assert _jws.jwt.headers['alg'] == 'RS512'

    client_keyjar = KeyJar()
    _jwks = KEYJAR.export_jwks()
    client_keyjar.import_jwks(_jwks, ENDPOINT_CONTEXT.issuer)

    _jwt = JWT(keyjar=client_keyjar, iss='client_1')
    res = _jwt.unpack(_token)
    assert isinstance(res, JsonWebToken)
    assert res['aud'] == ['client_1']
Example #4
0
    def _parse_remote_response(self, response):
        """
        Parse simple JWKS or signed JWKS from the HTTP response.

        :param response: HTTP response from the 'jwks_uri' or 'signed_jwks_uri'
            endpoint
        :return: response parsed as JSON
        """
        # Check if the content type is the right one.
        try:
            if response.headers["Content-Type"] == 'application/json':
                logger.debug(
                    "Loaded JWKS: %s from %s" % (response.text, self.source))
                try:
                    return json.loads(response.text)
                except ValueError:
                    return None
            elif response.headers["Content-Type"] == 'application/jose':
                logger.debug(
                    "Signed JWKS: %s from %s" % (response.text, self.source))
                _jws = factory(response.text)
                _resp = _jws.verify_compact(
                    response.text, keys=self.verify_keys.get_signing_key())
                return _resp
            else:
                logger.error('Wrong content type: {}'.format(
                    response.headers['Content-Type']))
                return None
        except KeyError:
            pass
def test_dj_usage():
    pkey = import_private_rsa_key_from_file(full_path("./size2048.key"))
    payload = "Please take a moment to register today"
    keys = [RSAKey(key=pkey)]
    _jws = JWS(payload, alg='RS256')
    sjwt = _jws.sign_compact(keys)
    _jwt = factory(sjwt)
    assert _jwt.jwt.headers['alg'] == 'RS256'
Example #6
0
def unfurl(jwt):
    """
    Return the body of a signed JWT, without verifying the signature.
    
    :param jwt: A signed JWT 
    :return: The body of the JWT as a 'UTF-8' string
    """

    _rp_jwt = factory(jwt)
    return json.loads(_rp_jwt.jwt.part[1].decode('utf8'))
Example #7
0
def test_internal_signing_service():
    iss = InternalSigningService('https://swamid.sunet.se',
                                 KJ['https://swamid.sunet.se'])
    res = iss.sign(
        RegistrationRequest(redirect_uris=['https://example.com/rp/cb']),
        receiver='https://example.com/rp')

    _jws = factory(res)
    assert _jws.jwt.headers['alg'] == 'RS256'
    msg = _jws.jwt.payload()
    assert msg['iss'] == 'https://swamid.sunet.se'
    assert msg['aud'] == ['https://example.com/rp']
def test_signer_ps512():
    payload = "Please take a moment to register today"
    # Key has to be big enough  > 512+512+2
    _pkey = import_private_rsa_key_from_file(full_path("./size2048.key"))
    keys = [RSAKey(key=_pkey)]
    # keys[0]._keytype = "private"
    _jws = JWS(payload, alg="PS512")
    _jwt = _jws.sign_compact(keys)

    vkeys = [RSAKey(key=_pkey.public_key())]
    _rj = factory(_jwt)
    info = _rj.verify_compact(_jwt, vkeys)
    assert info == payload
Example #9
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
    _kj = public_keys_keyjar(_keyjar, '', None, op.iss)
    r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss))
    assert r
Example #10
0
    def parse_response(self, response):
        if 200 <= response.status_code < 300:
            _jw = factory(response.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(response.text,
                                   self.keyjar.get_verify_key(owner=self.iss))
            except AssertionError:
                raise JWSException('JWS signature verification error')

            location = response.headers['Location']

            return {'sms': response.text, 'loc': location}
        else:
            raise SigningServiceError("{}: {}".format(response.status_code,
                                                      response.text))
Example #11
0
def test_pack_metadata_statement():
    jb = FSJWKSBundle('', None, 'fo_jwks',
                      key_conv={'to': quote_plus, 'from': unquote_plus})
    _keyjar = build_keyjar(KEYDEFS)[1]
    self_signer = InternalSigningService('https://example.com/op',
                                         keyjar=_keyjar)
    op = Operator(self_signer=self_signer, jwks_bundle=jb,
                  iss='https://example.com/op')
    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
    _kj = public_keys_keyjar(_keyjar, '', None, op.iss)
    r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss))
    assert r
Example #12
0
def verify_request_signed_by_signing_keys(smsreq):
    """
    Verify that a JWT is signed with a key that is inside the JWT.
    
    :param smsreq: Signed Metadata Statement signing request
    :return: Dictionary containing 'ms' (the signed request) and 'iss' (the
        issuer of the JWT).
    """

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

    _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(smsreq, _keys)
    # remove the JWT specific claims
    for k in JsonWebToken.c_param.keys():
        try:
            del _ver[k]
        except KeyError:
            pass
    try:
        del _ver['kid']
    except KeyError:
        pass

    return {'ms': MetadataStatement(**_ver), 'iss': iss}
Example #13
0
def test_make_signed_metadata_statements():
    mds = MetaDataStore('mds')
    mds.clear()
    liss = list(FO.values())
    liss.extend(list(OA.values()))

    key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS,
                                     './')

    operator = {}

    for entity, _keyjar in key_bundle.items():
        operator[entity] = Operator(iss=entity, keyjar=_keyjar)

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']]
    ms = make_signed_metadata_statement(_spec,
                                        operator,
                                        mds=mds,
                                        base_uri='https:/example.org/ms')
    assert ms

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['edugain']]
    res = make_signed_metadata_statement(_spec,
                                         operator,
                                         mds=mds,
                                         base_uri='https:/example.org/ms')
    assert list(res['ms_uri'].keys()) == [FO['edugain']]

    _spec = SMS_DEF[OA['sunet']]["discovery"][FO['example']]
    res = make_signed_metadata_statement(_spec,
                                         operator,
                                         mds=mds,
                                         base_uri='https:/example.org/ms')
    assert list(res['ms'].keys()) == [FO['example']]
    _jws = factory(res['ms'][FO['example']])
    assert _jws
    def unpack(self, token):
        """
        Unpack a received signed or signed and encrypted Json Web Token

        :param token: The Json Web Token
        :return: If decryption and signature verification work the payload
            will be returned as a Message instance if possible.
        """
        if not token:
            raise KeyError

        _content_type = 'jwt'
        _jwe_header = _jws_header = None

        # Check if it's an encrypted JWT
        _rj = jwe.factory(token)
        if _rj:
            # Yes, try to decode
            _info = self._decrypt(_rj, token)
            _jwe_header = _rj.jwt.headers
            # Try to find out if the information encrypted was a signed JWT
            try:
                _content_type = _rj.jwt.headers['cty']
            except KeyError:
                pass
        else:
            _info = token

        # If I have reason to believe the information I have is a signed JWT
        if _content_type.lower() == 'jwt':
            # Check that is a signed JWT
            _rj = jws.factory(_info)
            if _rj:
                _info = self._verify(_rj, _info)
            else:
                raise Exception()
            _jws_header = _rj.jwt.headers
        else:
            # So, not a signed JWT
            try:
                # A JSON document ?
                _info = json.loads(_info)
            except JSONDecodeError:  # Oh, no ! Not JSON
                return _info

        # If I know what message class the info should be mapped into
        if self.msg_cls:
            _msg_cls = self.msg_cls
        else:
            try:
                # try to find a issuer specific message class
                _msg_cls = self.iss2msg_cls[_info['iss']]
            except KeyError:
                _msg_cls = None

        if _msg_cls:
            vp_args = {'skew': self.skew}
            if self.iss:
                vp_args['aud'] = self.iss
            _info = self.verify_profile(_msg_cls, _info, **vp_args)
            _info.jwe_header = _jwe_header
            _info.jws_header = _jws_header
            return _info
        else:
            return _info