def test_verify_client_client_secret_basic(self):
     _token = "{}:{}".format(client_id, client_secret)
     token = as_unicode(base64.b64encode(as_bytes(_token)))
     authz_token = "Basic {}".format(token)
     res = verify_client(self.endpoint_context, {}, authorization_info=authz_token,
                         endpoint="token")
     assert set(res.keys()) == {"method", "client_id"}
     assert res["method"] == "client_secret_basic"
Beispiel #2
0
def _add_passwd(keyjar, conf, kid):
    if keyjar:
        _keys = keyjar.get_encrypt_key(key_type="oct", kid=kid)
        if _keys:
            pw = as_unicode(_keys[0].k)
            if "kwargs" in conf:
                conf["kwargs"]["password"] = pw
            else:
                conf["password"] = pw
def test_client_secret_basic():
    _token = "{}:{}".format(client_id, client_secret)
    token = as_unicode(base64.b64encode(as_bytes(_token)))

    authz_token = "Basic {}".format(token)

    authn_info = ClientSecretBasic(endpoint_context).verify({}, authz_token)

    assert authn_info["client_id"] == client_id
Beispiel #4
0
def factory(ec, code=None, token=None, refresh=None, jwks_def=None, **kwargs):
    """
    Create a token handler

    :param code:
    :param token:
    :param refresh:
    :param jwks_def:
    :return: TokenHandler instance
    """

    TTYPE = {"code": "A", "token": "T", "refresh": "R"}

    if jwks_def:
        kj = init_key_jar(**jwks_def)
    else:
        kj = None

    args = {}

    if code:
        if kj:
            _keys = kj.get_encrypt_key(key_type="oct", kid="code")
            if _keys:
                code["password"] = as_unicode(_keys[0].k)
        args["code_handler"] = init_token_handler(ec, code, TTYPE["code"])

    if token:
        if kj:
            _keys = kj.get_encrypt_key(key_type="oct", kid="token")
            if _keys:
                token["password"] = as_unicode(_keys[0].k)
        args["access_token_handler"] = init_token_handler(
            ec, token, TTYPE["token"])

    if refresh:
        if kj:
            _keys = kj.get_encrypt_key(key_type="oct", kid="refresh")
            if _keys:
                refresh["password"] = as_unicode(_keys[0].k)
        args["refresh_token_handler"] = init_token_handler(
            ec, refresh, TTYPE["refresh"])

    return TokenHandler(**args)
    def test_csb_wrong_secret(self):
        _token = "{}:{}".format(client_id, "pillow")
        token = as_unicode(base64.b64encode(as_bytes(_token)))

        authz_token = "Basic {}".format(token)

        assert self.method.is_usable(authorization_token=authz_token)

        with pytest.raises(AuthnFailure):
            self.method.verify(authorization_token=authz_token)
    def test_client_secret_basic(self):
        _token = "{}:{}".format(client_id, client_secret)
        token = as_unicode(base64.b64encode(as_bytes(_token)))

        authz_token = "Basic {}".format(token)

        assert self.method.is_usable(authorization_token=authz_token)
        authn_info = self.method.verify(authorization_token=authz_token)

        assert authn_info["client_id"] == client_id
    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)
Beispiel #8
0
def new_cookie(endpoint_context, cookie_name=None, **kwargs):
    if endpoint_context.cookie_dealer:
        _val = as_unicode(b64e(as_bytes(json.dumps(kwargs))))
        return endpoint_context.cookie_dealer.create_cookie(
            _val,
            typ="sso",
            cookie_name=cookie_name,
            ttl=endpoint_context.sso_ttl)
    else:
        return None
Beispiel #9
0
def verify_cookie_signature(sig, key, *parts):
    """Constant time verifier for signatures

       :param sig: The signature hexdigest to check
       :type sig: str
       :param key: The HMAC key to use.
       :type key: bytes
       :param parts: List of parts to include in the MAC
       :type parts: list of bytes or strings
       :raises: `InvalidCookieSign` when the signature is wrong
    """
    return safe_str_cmp(as_unicode(sig), cookie_signature(key, *parts))
Beispiel #10
0
def basic_authn(authorization_token):
    if not authorization_token.startswith("Basic "):
        raise AuthnFailure("Wrong type of authorization token")

    _tok = as_bytes(authorization_token[6:])
    # Will raise ValueError type exception if not base64 encoded
    _tok = base64.b64decode(_tok)
    part = [unquote_plus(p) for p in as_unicode(_tok).split(":")]
    if len(part) == 2:
        return dict(zip(["id", "secret"], part))
    else:
        raise ValueError("Illegal token")
Beispiel #11
0
def parse_cookie(name, seed, kaka, enc_key=None):
    """Parses and verifies a cookie value

    Parses a cookie created by `make_cookie` and verifies
    it has not been tampered with.

    You need to provide the same `seed` and `enc_key`
    used when creating the cookie, otherwise the verification
    fails. See `make_cookie` for details about the verification.

    :param seed: A seed key used for the HMAC signature
    :type seed: bytes
    :param kaka: The cookie
    :param enc_key: The encryption key used.
    :type enc_key: bytes or None
    :raises InvalidCookieSign: When verification fails.
    :return: A tuple consisting of (payload, timestamp) or None if parsing fails
    """
    if not kaka:
        return None

    seed = as_unicode(seed)

    parts = cookie_parts(name, kaka)
    if parts is None:
        return None
    elif len(parts) == 3:
        # verify the cookie signature
        cleartext, timestamp, sig = parts
        if not verify_cookie_signature(sig, seed, cleartext, timestamp):
            raise InvalidCookieSign()
        return cleartext, timestamp
    elif len(parts) == 4:
        # encrypted and signed
        timestamp = parts[0]
        iv = base64.b64decode(parts[1])
        ciphertext = base64.b64decode(parts[2])
        tag = base64.b64decode(parts[3])
        ct = ciphertext + tag

        # Make sure the key is 32-Bytes long
        key = _make_hashed_key((enc_key, seed))
        aesgcm = AESGCM(key)

        # timestamp does not need to be encrypted, just MAC'ed,
        # so we add it to 'Associated Data' only.
        aad = timestamp.encode('utf-8')
        try:
            cleartext = aesgcm.decrypt(iv, ct, aad)
        except JWEException:
            raise InvalidCookieSign()
        return cleartext.decode('utf-8'), timestamp
    return None
Beispiel #12
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))
    def test_verify_client_client_secret_basic(self):
        _token = "{}:{}".format(client_id, client_secret)
        token = as_unicode(base64.b64encode(as_bytes(_token)))
        authz_token = "Basic {}".format(token)
        http_info = {"headers": {"authorization": authz_token}}

        res = verify_client(
            self.endpoint_context,
            {},
            http_info=http_info,
            endpoint=self.server.server_get("endpoint", "token"),
        )
        assert set(res.keys()) == {"method", "client_id"}
        assert res["method"] == "client_secret_basic"
Beispiel #14
0
def cookie_parts(name, kaka):
    """
    Give me the parts of the cookie payload

    :param name: A name of a cookie object
    :param kaka: The cookie
    :return: A list of parts or None if there is no cookie object with the
        given name
    """
    cookie_obj = SimpleCookie(as_unicode(kaka))
    morsel = cookie_obj.get(name)
    if morsel:
        return morsel.value.split("|")
    else:
        return None
Beispiel #15
0
def backchannel_logout(client, request='', request_args=None):
    """

    :param request: URL encoded logout request
    :return:
    """

    if request:
        req = BackChannelLogoutRequest().from_urlencoded(as_unicode(request))
    else:
        req = BackChannelLogoutRequest(**request_args)

    kwargs = {
        'aud':
        client.service_context.get('client_id'),
        'iss':
        client.service_context.get('issuer'),
        'keyjar':
        client.service_context.keyjar,
        'allowed_sign_alg':
        client.service_context.get('registration_response').get(
            "id_token_signed_response_alg", "RS256")
    }

    try:
        req.verify(**kwargs)
    except (MessageException, ValueError, NotForMe) as err:
        raise MessageException('Bogus logout request: {}'.format(err))

    # Find the subject through 'sid' or 'sub'

    try:
        sub = req[verified_claim_name('logout_token')]['sub']
    except KeyError:
        try:
            sid = req[verified_claim_name('logout_token')]['sid']
        except KeyError:
            raise MessageException('Neither "sid" nor "sub"')
        else:
            _state = client.session_interface.get_state_by_sid(sid)
    else:
        _state = client.session_interface.get_state_by_sub(sub)

    return _state
Beispiel #16
0
def modify_json_message(token):
    part = [as_bytes(p) for p in token.split('.')]
    _txt = utils.b64d(part[1])
    msg = json.loads(as_unicode(_txt))
    for k, v in msg.items():
        msg_copy = msg.copy()
        del msg_copy[k]

        for _k in modify_str(k):
            msg_copy[_k] = v
            part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
            yield b'.'.join([as_bytes(p) for p in part])

        if isinstance(v, str):
            for _v in modify_str(v):
                msg_copy[k] = _v
                part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
                yield b'.'.join([as_bytes(p) for p in part])
        elif isinstance(v, int):
            _v = v + 1
            msg_copy[k] = _v
            part[1] = utils.b64e(as_bytes(json.dumps(msg_copy)))
            yield b'.'.join([as_bytes(p) for p in part])
Beispiel #17
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}
Beispiel #18
0
 def decrypt(self, ciphertext):
     dec_text = self.core.decrypt(ciphertext)
     dec_text = dec_text.rstrip(b' ')
     return as_unicode(dec_text)
    def from_jwt(self, txt, keyjar, verify=True, **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
        """

        algarg = {}
        if 'encalg' in kwargs:
            algarg['alg'] = kwargs['encalg']
        if 'encenc' in kwargs:
            algarg['enc'] = kwargs['encenc']
        _decryptor = jwe_factory(txt, **algarg)

        if _decryptor:
            logger.debug("JWE headers: %s", _decryptor.jwt.headers)

            dkeys = keyjar.get_decrypt_key(owner="")

            logger.debug('Decrypt class: %s', _decryptor.__class__)
            _res = _decryptor.decrypt(txt, dkeys)
            logger.debug('decrypted message: %s', _res)
            if isinstance(_res, tuple):
                txt = as_unicode(_res[0])
            elif isinstance(_res, list) and len(_res) == 2:
                txt = as_unicode(_res[0])
            else:
                txt = as_unicode(_res)
            self.jwe_header = _decryptor.jwt.headers

        if kwargs.get('sigalg'):
            _verifier = jws_factory(txt, alg=kwargs['sigalg'])
        else:
            _verifier = jws_factory(txt)

        if _verifier:
            _jwt = _verifier.jwt
            jso = _jwt.payload()
            _header = _jwt.headers

            key = []
            # if "sender" in kwargs:
            #     key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

            logger.debug("Raw JSON: %s", jso)
            logger.debug("JWS header: %s", _header)
            if _header["alg"] == "none":
                pass
            elif verify:
                if keyjar:
                    key.extend(keyjar.get_jwt_verify_keys(_jwt, **kwargs))

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

                logger.debug("Found signing key.")
                try:
                    _verifier.verify_compact(txt, key)
                except NoSuitableSigningKeys:
                    if keyjar:
                        keyjar.update()
                        key = keyjar.get_jwt_verify_keys(_jwt, **kwargs)
                        _verifier.verify_compact(txt, key)

            self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        self.jwt = txt
        return self.from_dict(jso)
Beispiel #20
0
    def authz_part2(self, user, authn_event, request, **kwargs):
        """
        After the authentication this is where you should end up

        :param user:
        :param request: The Authorization Request
        :param sid: Session key
        :param kwargs: possible other parameters
        :return: A redirect to the redirect_uri of the client
        """
        sid = setup_session(self.endpoint_context,
                            request,
                            user,
                            authn_event=authn_event)

        try:
            resp_info = self.post_authentication(user, request, sid, **kwargs)
        except Exception as err:
            return self.error_response({}, "server_error", err)

        if "check_session_iframe" in self.endpoint_context.provider_info:
            ec = self.endpoint_context
            salt = rndstr()
            if not ec.sdb.is_session_revoked(sid):
                authn_event = ec.sdb.get_authentication_event(
                    sid)  # use the last session
                _state = b64e(
                    as_bytes(
                        json.dumps({"authn_time": authn_event["authn_time"]})))

                session_cookie = ec.cookie_dealer.create_cookie(
                    as_unicode(_state),
                    typ="session",
                    cookie_name=ec.cookie_name["session_management"],
                    same_site="None",
                    http_only=False)

                opbs = session_cookie[ec.cookie_name["session_management"]]

                logger.debug(
                    "compute_session_state: client_id=%s, origin=%s, opbs=%s, salt=%s",
                    request["client_id"],
                    resp_info["return_uri"],
                    opbs.value,
                    salt,
                )

                _session_state = compute_session_state(opbs.value, salt,
                                                       request["client_id"],
                                                       resp_info["return_uri"])

                if "cookie" in resp_info:
                    if isinstance(resp_info["cookie"], list):
                        resp_info["cookie"].append(session_cookie)
                    else:
                        append_cookie(resp_info["cookie"], session_cookie)
                else:
                    resp_info["cookie"] = session_cookie

                resp_info["response_args"]["session_state"] = _session_state

        # Mix-Up mitigation
        resp_info["response_args"]["iss"] = self.endpoint_context.issuer
        resp_info["response_args"]["client_id"] = request["client_id"]

        return resp_info
Beispiel #21
0
    def setup_auth(self,
                   request,
                   redirect_uri,
                   cinfo,
                   cookie,
                   acr=None,
                   **kwargs):
        """

        :param request: The authorization/authentication request
        :param redirect_uri:
        :param cinfo: client info
        :param cookie:
        :param acr: Default ACR, if nothing else is specified
        :param kwargs:
        :return:
        """

        res = self.pick_authn_method(request, redirect_uri, acr, **kwargs)

        authn = res["method"]
        authn_class_ref = res["acr"]

        try:
            _auth_info = kwargs.get("authn", "")
            if "upm_answer" in request and request["upm_answer"] == "true":
                _max_age = 0
            else:
                _max_age = max_age(request)

            identity, _ts = authn.authenticated_as(cookie,
                                                   authorization=_auth_info,
                                                   max_age=_max_age)
        except (NoSuchAuthentication, TamperAllert):
            identity = None
            _ts = 0
        except ToOld:
            logger.info("Too old authentication")
            identity = None
            _ts = 0
        else:
            if identity:
                try:  # If identity['uid'] is in fact a base64 encoded JSON string
                    _id = b64d(as_bytes(identity["uid"]))
                except BadSyntax:
                    pass
                else:
                    identity = json.loads(as_unicode(_id))

                    session = self.endpoint_context.sdb[identity.get("sid")]
                    if not session or "revoked" in session:
                        identity = None

        authn_args = authn_args_gather(request, authn_class_ref, cinfo,
                                       **kwargs)

        # To authenticate or Not
        if identity is None:  # No!
            logger.info("No active authentication")
            logger.debug("Known clients: {}".format(
                list(self.endpoint_context.cdb.keys())))

            if "prompt" in request and "none" in request["prompt"]:
                # Need to authenticate but not allowed
                return {
                    "error": "login_required",
                    "return_uri": redirect_uri,
                    "return_type": request["response_type"],
                }
            else:
                return {"function": authn, "args": authn_args}
        else:
            logger.info("Active authentication")
            if re_authenticate(request, authn):
                # demand re-authentication
                return {"function": authn, "args": authn_args}
            else:
                # I get back a dictionary
                user = identity["uid"]
                if "req_user" in kwargs:
                    sids = self.endpoint_context.sdb.get_sids_by_sub(
                        kwargs["req_user"])
                    if (sids and user !=
                            self.endpoint_context.sdb.get_authentication_event(
                                sids[-1]).uid):
                        logger.debug("Wanted to be someone else!")
                        if "prompt" in request and "none" in request["prompt"]:
                            # Need to authenticate but not allowed
                            return {
                                "error": "login_required",
                                "return_uri": redirect_uri,
                            }
                        else:
                            return {"function": authn, "args": authn_args}

        authn_event = create_authn_event(
            identity["uid"],
            identity.get("salt", ""),
            authn_info=authn_class_ref,
            time_stamp=_ts,
        )
        if "valid_until" in authn_event:
            vu = time.time() + authn.kwargs.get("expires_in", 0.0)
            authn_event["valid_until"] = vu

        return {"authn_event": authn_event, "identity": identity, "user": user}
Beispiel #22
0
def cookie_value(b64):
    return json.loads(as_unicode(b64d(as_bytes(b64))))
def test_basic_auth():
    _token = "{}:{}".format(client_id, client_secret)
    token = as_unicode(base64.b64encode(as_bytes(_token)))

    res = basic_authn("Basic {}".format(token))
    assert res
def test_basic_auth_wrong_label():
    _token = "{}:{}".format(client_id, client_secret)
    token = as_unicode(base64.b64encode(as_bytes(_token)))

    with pytest.raises(AuthnFailure):
        basic_authn("Expanded {}".format(token))