def test_private_key_jwt_reusage_other_endpoint():
    # Own dynamic keys
    client_keyjar = build_keyjar(KEYDEFS)
    # The servers keys
    client_keyjar[conf["issuer"]] = KEYJAR.issuer_keys[""]

    _jwks = client_keyjar.export_jwks()
    endpoint_context.keyjar.import_jwks(_jwks, client_id)

    _jwt = JWT(client_keyjar, iss=client_id, sign_alg="RS256")
    _jwt.with_jti = True
    _assertion = _jwt.pack(
        {"aud": [endpoint_context.endpoint["token"].full_path]})

    request = {
        "client_assertion": _assertion,
        "client_assertion_type": JWT_BEARER
    }

    # This should be OK
    PrivateKeyJWT(endpoint_context).verify(request, endpoint="token")

    # This should NOT be OK
    with pytest.raises(NotForMe):
        PrivateKeyJWT(endpoint_context).verify(request,
                                               endpoint="authorization")

    # This should NOT be OK
    with pytest.raises(MultipleUsage):
        PrivateKeyJWT(endpoint_context).verify(request, endpoint="token")
    def test_private_key_jwt_auth_endpoint(self):
        # Own dynamic keys
        client_keyjar = build_keyjar(KEYDEFS)
        # The servers keys
        client_keyjar.import_jwks(KEYJAR.export_jwks(private=True),
                                  CONF["issuer"])

        _jwks = client_keyjar.export_jwks()
        self.method.server_get("endpoint_context").keyjar.import_jwks(
            _jwks, client_id)

        _jwt = JWT(client_keyjar, iss=client_id, sign_alg="RS256")
        _jwt.with_jti = True
        _assertion = _jwt.pack({
            "aud":
            [self.method.server_get("endpoint", "authorization").full_path]
        })

        request = {
            "client_assertion": _assertion,
            "client_assertion_type": JWT_BEARER
        }

        assert self.method.is_usable(request=request)
        authn_info = self.method.verify(
            request=request,
            endpoint=self.method.server_get("endpoint", "authorization"),
        )

        assert authn_info["client_id"] == client_id
        assert "jwt" in authn_info
    def test_unpack_aggregated_response_missing_keys(self):
        claims = {
            "address": {
                "street_address": "1234 Hollywood Blvd.",
                "locality": "Los Angeles",
                "region": "CA",
                "postal_code": "90210",
                "country": "US"
            },
            "phone_number": "+1 (555) 123-4567"
        }

        _keyjar = build_keyjar(KEYSPEC)

        srv = JWT(_keyjar, iss=ISS, sign_alg='ES256')
        _jwt = srv.pack(payload=claims)

        resp = OpenIDSchema(sub='diana', given_name='Diana',
                            family_name='krall',
                            _claim_names={
                                'address': 'src1',
                                'phone_number': 'src1'
                            },
                            _claim_sources={'src1': {'JWT': _jwt}})

        _resp = self.service.parse_response(resp.to_json(), state='abcde')
        assert _resp
    def test_verify_client_jws_authn_method(self):
        client_keyjar = KeyJar()
        client_keyjar.import_jwks(KEYJAR.export_jwks(private=True),
                                  CONF["issuer"])
        # The only own key the client has a this point
        client_keyjar.add_symmetric("", client_secret, ["sig"])

        _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256")
        # Audience is OP issuer ID
        aud = "{}token".format(CONF["issuer"])  # aud == Token endpoint
        _assertion = _jwt.pack({"aud": [aud]})

        request = {
            "client_assertion": _assertion,
            "client_assertion_type": JWT_BEARER
        }
        http_info = {"headers": {}}
        res = verify_client(
            self.endpoint_context,
            request,
            http_info=http_info,
            endpoint=self.server.server_get("endpoint", "token"),
        )
        assert res["method"] == "client_secret_jwt"
        assert res["client_id"] == "client_id"
def make_openid_request(arq,
                        keys,
                        issuer,
                        request_object_signing_alg,
                        recv,
                        with_jti=False,
                        lifetime=0):
    """
    Construct the JWT to be passed by value (the request parameter) or by
    reference (request_uri).
    The request will be signed

    :param arq: The Authorization request
    :param keys: Keys to use for signing/encrypting. A KeyJar instance
    :param issuer: Who is signing this JSON Web Token
    :param request_object_signing_alg: Which signing algorithm to use
    :param recv: The intended receiver of the request
    :param with_jti: Whether a JTI should be included in the JWT.
    :param lifetime: How long the JWT is expect to be live.
    :return: JWT encoded OpenID request
    """

    _jwt = JWT(key_jar=keys, iss=issuer, sign_alg=request_object_signing_alg)
    if with_jti:
        _jwt.with_jti = True
    if lifetime:
        _jwt.lifetime = lifetime
    return _jwt.pack(arq.to_dict(), owner=issuer, recv=recv)
예제 #6
0
    def do_back_channel_logout(self, cinfo, sid):
        """

        :param cinfo: Client information
        :param sid: The session ID
        :return: Tuple with logout URI and signed logout token
        """

        _context = self.server_get("endpoint_context")

        try:
            back_channel_logout_uri = cinfo["backchannel_logout_uri"]
        except KeyError:
            return None

        # Create the logout token
        # always include sub and sid so I don't check for
        # backchannel_logout_session_required

        enc_msg = self._encrypt_sid(sid)

        payload = {"sid": enc_msg, "events": {BACK_CHANNEL_LOGOUT_EVENT: {}}}

        try:
            alg = cinfo["id_token_signed_response_alg"]
        except KeyError:
            alg = _context.provider_info["id_token_signing_alg_values_supported"][0]

        _jws = JWT(_context.keyjar, iss=_context.issuer, lifetime=86400, sign_alg=alg)
        _jws.with_jti = True
        _logout_token = _jws.pack(payload=payload, recv=cinfo["client_id"])

        return back_channel_logout_uri, _logout_token
예제 #7
0
class EncryptedJWTFactory(EncryptedTokenFactory):

    key_jar: KeyJar

    def __init__(self,
                 key_jar: KeyJar = None,
                 encrypt: bool = True,
                 sign: bool = True,
                 **kwargs):

        if encrypt is not True:
            raise RuntimeError('JWT encryption is mandatory.')

        self.key_jar = key_jar if key_jar is not None else KeyJar()
        self._jwt = JWT(key_jar=self.key_jar,
                        encrypt=encrypt,
                        sign=sign,
                        **kwargs)

    @property
    def issuer_id(self):
        return self._jwt.iss

    @classmethod
    def new_keys(cls, iss: str = 'Generic', **kwargs):
        """Creates a new key jar based on RSA keys.
        """
        uses = ['enc', 'sig'] if kwargs.get('sign', True) else ['enc']
        key_specs = [{"type": "RSA", "use": uses}]
        key_jar = build_keyjar(key_specs, issuer_id=iss)
        return cls(key_jar, iss=iss, **kwargs)

    def generate(self,
                 payload: dict,
                 subject: str = 'token',
                 recv: typing.Optional[str] = None) -> str:
        if recv is None:
            recv = self._jwt.iss
        token = self._jwt.pack(
            recv=recv,
            payload={
                "sub": subject,
                "data": payload
            },
            encrypt=True,
        )
        return token

    def decrypt(self, token: str) -> dict:
        info = self._jwt.unpack(token)
        if self._jwt.lifetime:
            now = utc_time_sans_frac()
            if 'iat' not in info or 'exp' not in info:
                raise MissingExpirationHeader()
            if now < info['iat']:
                raise NotYet()
            if now > info['exp']:
                raise Expired()
        return info.get('data')
예제 #8
0
class Challenger(object):
    def __init__(self, kb: KeyBundle, issuer: str, lifetime: int) -> None:
        self.logger = logging.getLogger(__name__).getChild(
            self.__class__.__name__)
        self.issuer = issuer
        self.kj = KeyJar()
        self.kj.add_kb(self.issuer, kb)
        sign_alg = None
        enc_alg = None
        enc_enc = None
        kid = None
        for key in self.kj.get(key_use="enc", issuer_id=issuer):
            kid = key.kid
            if key.kty == "oct":
                sign_alg = "HS256"
                enc_alg = None
                enc_enc = None
                break
            elif key.kty == "EC":
                sign_alg = "ES256"
                enc_alg = "ECDH-ES"
                enc_enc = "A128GCM"
                break
            elif key.kty == "RSA":
                sign_alg = "RS256"
                enc_alg = "RSA1_5"
                enc_enc = "A128GCM"
                break
        if kid is None:
            raise Exception("No challenge key found")
        sign = sign_alg is not None
        encrypt = enc_alg is not None
        self.logger.info("Using challenge key kid=%s sign=%s encrypt=%s", kid,
                         sign, encrypt)
        self.jwt = JWT(
            key_jar=self.kj,
            iss=self.issuer,
            lifetime=lifetime,
            sign=sign,
            sign_alg=sign_alg,
            encrypt=encrypt,
            enc_alg=enc_alg,
            enc_enc=enc_enc,
        )

    def issue_bytes(self, payload: dict) -> bytes:
        """Issue token challenge"""
        return str(self.jwt.pack(payload=payload, recv=self.issuer)).encode()

    def verify_bytes(self, challenge: bytes) -> dict:
        """Verify challenge and return payload"""
        token = challenge.decode()
        payload = self.jwt.unpack(token)
        now = time.time()
        if "nbf" in payload and now < int(payload.get("nbf")):
            raise BadSignature("Token not yet valid (t < nbf)")
        if "exp" in payload and now >= int(payload.get("exp")):
            raise BadSignature("Token expired (t >= exp)")
        return dict(payload)
예제 #9
0
def test_jwt_pack_encrypt():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE)
    payload = {"sub": "sub", "aud": BOB}
    _jwt = alice.pack(payload=payload, encrypt=True, recv=BOB)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB)
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {"iat", "iss", "sub", "aud"}
예제 #10
0
def test_jwt_pack_and_unpack_with_lifetime():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, lifetime=600)
    payload = {"sub": "sub"}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB)
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {"iat", "iss", "sub", "exp"}
def test_jwt_pack_encrypt():
    alice = JWT(own_keys=ALICE_KEYS, iss=ALICE, rec_keys={BOB: BOB_PUB_KEYS})
    payload = {'sub': 'sub', 'aud': BOB}
    _jwt = alice.pack(payload=payload, encrypt=True, recv=BOB)

    bob = JWT(own_keys=BOB_KEYS, iss=BOB, rec_keys={ALICE: ALICE_PUB_KEYS})
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub', 'kid', 'aud'}
def test_jwt_pack_and_unpack_with_lifetime():
    alice = JWT(own_keys=ALICE_KEYS, iss=ALICE, lifetime=600)
    payload = {'sub': 'sub'}
    _jwt = alice.pack(payload=payload)

    bob = JWT(own_keys=BOB_KEYS, iss=BOB, rec_keys={ALICE: ALICE_PUB_KEYS})
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub', 'kid', 'exp', 'aud'}
예제 #13
0
def test_jwt_pack_and_unpack():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg="RS256")
    payload = {"sub": "sub"}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB, allowed_sign_algs=["RS256"])
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {"iat", "iss", "sub"}
예제 #14
0
def test_jwt_pack_and_unpack_with_alg():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg="RS384")
    payload = {"sub": "sub"}
    _jwt = alice.pack(payload=payload)

    bob = JWT(BOB_KEY_JAR, sign_alg="RS384")
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {"iat", "iss", "sub"}
예제 #15
0
def test_jwt_pack_encrypt():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE)
    payload = {'sub': 'sub', 'aud': BOB}
    _jwt = alice.pack(payload=payload, encrypt=True, recv=BOB)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB)
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub', 'aud'}
예제 #16
0
def test_jwt_pack_and_unpack_with_lifetime():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, lifetime=600)
    payload = {'sub': 'sub'}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB)
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub', 'exp'}
예제 #17
0
def test_jwt_pack_and_unpack():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg='RS256')
    payload = {'sub': 'sub'}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=BOB_KEY_JAR, iss=BOB, allowed_sign_algs=["RS256"])
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub'}
예제 #18
0
def test_jwt_pack_and_unpack_with_alg():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg='RS384')
    payload = {'sub': 'sub'}
    _jwt = alice.pack(payload=payload)

    bob = JWT(BOB_KEY_JAR, sign_alg='RS384')
    info = bob.unpack(_jwt)

    assert set(info.keys()) == {'iat', 'iss', 'sub'}
예제 #19
0
def test_jwt_pack_and_unpack_unknown_issuer():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg="RS256")
    payload = {"sub": "sub"}
    _jwt = alice.pack(payload=payload)

    kj = KeyJar()
    bob = JWT(key_jar=kj, iss=BOB, allowed_sign_algs=["RS256"])
    with pytest.raises(IssuerNotFound):
        info = bob.unpack(_jwt)
def test_jwt_pack_unpack_sym():
    _sym_key = SYMKey(key='hemligt ord', use='sig')
    alice = JWT(own_keys=[_sym_key], iss=ALICE, sign_alg="HS256")
    payload = {'sub': 'sub2'}
    _jwt = alice.pack(payload=payload)

    bob = JWT(own_keys=None, iss=BOB, rec_keys={ALICE: [_sym_key]})
    info = bob.unpack(_jwt)
    assert info
예제 #21
0
    def do_response(self,
                    response_args=None,
                    request=None,
                    client_id="",
                    **kwargs):

        if "error" in kwargs and kwargs["error"]:
            return Endpoint.do_response(self, response_args, request, **kwargs)

        _context = self.endpoint_context
        if not client_id:
            raise MissingValue("client_id")

        # Should I return a JSON or a JWT ?
        _cinfo = _context.cdb[client_id]

        # default is not to sign or encrypt
        try:
            sign_alg = _cinfo["userinfo_signed_response_alg"]
            sign = True
        except KeyError:
            sign_alg = ""
            sign = False

        try:
            enc_enc = _cinfo["userinfo_encrypted_response_enc"]
            enc_alg = _cinfo["userinfo_encrypted_response_alg"]
            encrypt = True
        except KeyError:
            encrypt = False
            enc_alg = enc_enc = ""

        if encrypt or sign:
            _jwt = JWT(
                self.endpoint_context.keyjar,
                iss=self.endpoint_context.issuer,
                sign=sign,
                sign_alg=sign_alg,
                encrypt=encrypt,
                enc_enc=enc_enc,
                enc_alg=enc_alg,
            )

            resp = _jwt.pack(response_args, recv=client_id)
            content_type = "application/jwt"
        else:
            if isinstance(response_args, dict):
                resp = json.dumps(response_args)
            else:
                resp = response_args.to_json()
            content_type = "application/json"

        http_headers = [("Content-type", content_type)]
        http_headers.extend(OAUTH2_NOCACHE_HEADERS)

        return {"response": resp, "http_headers": http_headers}
예제 #22
0
def test_jwt_pack_and_unpack_unknown_key():
    alice = JWT(key_jar=ALICE_KEY_JAR, iss=ALICE, sign_alg="RS256")
    payload = {"sub": "sub"}
    _jwt = alice.pack(payload=payload)

    kj = KeyJar()
    kj.add_kb(ALICE, KeyBundle())
    bob = JWT(key_jar=kj, iss=BOB, allowed_sign_algs=["RS256"])
    with pytest.raises(NoSuitableSigningKeys):
        info = bob.unpack(_jwt)
예제 #23
0
    def sign_encrypt(
        self,
        session_info,
        client_id,
        code=None,
        access_token=None,
        user_info=None,
        sign=True,
        encrypt=False,
        lifetime=None,
        extra_claims=None,
    ):
        """
        Signed and or encrypt a IDToken

        :param session_info: Session information
        :param client_id: Client ID
        :param code: Access grant
        :param access_token: Access Token
        :param user_info: User information
        :param sign: If the JWT should be signed
        :param encrypt: If the JWT should be encrypted
        :param extra_claims: Extra claims to be added to the ID Token
        :return: IDToken as a signed and/or encrypted JWT
        """

        _cntx = self.endpoint_context

        client_info = _cntx.cdb[client_id]
        alg_dict = get_sign_and_encrypt_algorithms(_cntx,
                                                   client_info,
                                                   "id_token",
                                                   sign=sign,
                                                   encrypt=encrypt)

        _authn_event = session_info["authn_event"]

        _idt_info = self.payload(
            session_info,
            acr=_authn_event["authn_info"],
            alg=alg_dict["sign_alg"],
            code=code,
            access_token=access_token,
            user_info=user_info,
            auth_time=_authn_event["authn_time"],
            lifetime=lifetime,
            extra_claims=extra_claims,
        )

        _jwt = JWT(_cntx.keyjar,
                   iss=_cntx.issuer,
                   lifetime=_idt_info["lifetime"],
                   **alg_dict)

        return _jwt.pack(_idt_info["payload"], recv=client_id)
예제 #24
0
def create_entity_statement(iss,
                            sub,
                            key_jar,
                            metadata=None,
                            metadata_policy=None,
                            authority_hints=None,
                            lifetime=86400,
                            aud='',
                            include_jwks=True,
                            constraints=None,
                            **kwargs):
    """

    :param iss: The issuer of the signed JSON Web Token
    :param sub: The subject which the metadata describes
    :param key_jar: A KeyJar instance
    :param metadata: The entity's metadata organised as a dictionary with the
        entity type as key
    :param metadata_policy: Metadata policy
    :param authority_hints: A dictionary with immediate superiors in the
        trust chains as keys and lists of identifier of trust roots as values.
    :param lifetime: The life time of the signed JWT.
    :param aud: Possible audience for the JWT
    :param include_jwks: Add JWKS
    :param constraints: A dictionary with constraints.
    :return: A signed JSON Web Token
    """

    msg = {'sub': sub}
    if metadata:
        msg['metadata'] = metadata

    if metadata_policy:
        msg['metadata_policy'] = metadata_policy

    if authority_hints:
        msg['authority_hints'] = authority_hints

    if aud:
        msg['aud'] = aud

    if constraints:
        msg['constraints'] = constraints

    if kwargs:
        msg.update(kwargs)

    if include_jwks:
        # The public signing keys of the subject
        msg['jwks'] = key_jar.export_jwks(issuer_id=sub)

    packer = JWT(key_jar=key_jar, iss=iss, lifetime=lifetime)

    return packer.pack(payload=msg)
예제 #25
0
def test_jwt_pack_unpack_sym():
    _kj = KeyJar()
    _kj.add_symmetric(ALICE, 'hemligt ordsprak', usage=['sig'])
    alice = JWT(key_jar=_kj, iss=ALICE, sign_alg="HS256")
    payload = {'sub': 'sub2'}
    _jwt = alice.pack(payload=payload)

    _kj = KeyJar()
    _kj.add_symmetric(ALICE, 'hemligt ordsprak', usage=['sig'])
    bob = JWT(key_jar=_kj, iss=BOB, sign_alg="HS256")
    info = bob.unpack(_jwt)
    assert info
예제 #26
0
def test_with_jti():
    _kj = KeyJar()
    _kj.add_symmetric(ALICE, "hemligt ordsprak", usage=["sig"])

    alice = JWT(key_jar=_kj, iss=ALICE, sign_alg="HS256")
    alice.with_jti = True
    payload = {"sub": "sub2"}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=_kj, iss=BOB, sign_alg="HS256")
    info = bob.unpack(_jwt)
    assert "jti" in info
예제 #27
0
def test_msg_cls():
    _kj = KeyJar()
    _kj.add_symmetric(ALICE, "hemligt ordsprak", usage=["sig"])

    alice = JWT(key_jar=_kj, iss=ALICE, sign_alg="HS256")
    payload = {"sub": "sub2"}
    _jwt = alice.pack(payload=payload)

    bob = JWT(key_jar=_kj, iss=BOB, sign_alg="HS256")
    bob.msg_cls = DummyMsg
    info = bob.unpack(_jwt)
    assert isinstance(info, DummyMsg)
예제 #28
0
    def test_jws_authn_method_wrong_key(self):
        client_keyjar = KeyJar()
        client_keyjar[CONF["issuer"]] = KEYJAR.issuer_keys[""]
        # Fake symmetric key
        client_keyjar.add_symmetric("", "client_secret:client_secret", ["sig"])

        _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256")
        _assertion = _jwt.pack({"aud": [CONF["issuer"]]})

        request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER}

        with pytest.raises(NoSuitableSigningKeys):
            self.method.verify(request=request, key_type='private_key')
예제 #29
0
    def sign_encrypt(
        self,
        session_id,
        client_id,
        code=None,
        access_token=None,
        sign=True,
        encrypt=False,
        lifetime=None,
        extra_claims=None,
    ) -> str:
        """
        Signed and or encrypt a IDToken

        :param lifetime: How long the ID Token should be valid
        :param session_id: Session information
        :param client_id: Client ID
        :param code: Access grant
        :param access_token: Access Token
        :param sign: If the JWT should be signed
        :param encrypt: If the JWT should be encrypted
        :param extra_claims: Extra claims to be added to the ID Token
        :return: IDToken as a signed and/or encrypted JWT
        """

        _context = self.server_get("endpoint_context")

        client_info = _context.cdb[client_id]
        alg_dict = get_sign_and_encrypt_algorithms(_context,
                                                   client_info,
                                                   "id_token",
                                                   sign=sign,
                                                   encrypt=encrypt)

        _payload = self.payload(
            session_id=session_id,
            alg=alg_dict["sign_alg"],
            code=code,
            access_token=access_token,
            extra_claims=extra_claims,
        )

        if lifetime is None:
            lifetime = self.lifetime

        _jwt = JWT(_context.keyjar,
                   iss=_context.issuer,
                   lifetime=lifetime,
                   **alg_dict)

        return _jwt.pack(_payload, recv=client_id)
예제 #30
0
    def pack(self, req, receiver='', iss='', lifetime=0, sign=True,
             sign_alg='', encrypt=False, enc_enc="A128CBC-HS256",
             enc_alg="RSA1_5", aud=None):
        """

        :param req: Original metadata statement as a 
            :py:class:`MetadataStatement` instance
        :param receiver: The immediate receiver of the JWS
        :param iss:
        :param lifetime:
        :param sign:
        :param sign_alg:
        :param encrypt:
        :param enc_alg:
        :param enc_enc:
        :param aud: The audience, a list of receivers.
        :return: A dictionary with a signed JWT as value with the key 'sms'
        """
        if not iss:
            iss = self.iss
        if not lifetime:
            lifetime = self.lifetime

        keyjar = self.keyjar

        # Own copy
        _metadata = copy.deepcopy(req)
        if self.add_ons:
            _metadata.update(self.add_ons)

        args = {}
        if sign:
            if sign_alg:
                args['sign_alg'] = sign_alg
            else:
                args['sign_alg'] = self.alg
        if encrypt:
            args['enc_enc'] = enc_enc
            args['enc_alg'] = enc_alg

        _jwt = JWT(keyjar, iss=iss, msg_cls=_metadata.__class__,
                   lifetime=lifetime, **args)
        # _jwt.sign_alg = self.alg

        if iss in keyjar.issuer_keys:
            owner = iss
        else:
            owner = ''

        return _jwt.pack(payload=_metadata.to_dict(), owner=owner,
                         recv=receiver, aud=aud)