Example #1
0
    def validate_token(self):
        """Validate token"""
        LOG.info('Start of Validating Token')
        access_token = ""
        for item in self.metadata:
            if item.key == 'authorization':
                access_token = item.value

        if _BEGIN_STATEMENT in os.environ['JWT_VALIDATION_KEY'] and \
                _END_STATEMENT in os.environ['JWT_VALIDATION_KEY']:
            pub_key = os.environ['JWT_VALIDATION_KEY']
            final_public_key = pub_key[len(_BEGIN_STATEMENT):len(pub_key) -
                                       len(_END_STATEMENT)]
            formatted_key = _BEGIN_STATEMENT + "\n" + final_public_key + "\n" + _END_STATEMENT
        else:
            formatted_key = _BEGIN_STATEMENT + "\n" + os.environ['JWT_VALIDATION_KEY'] \
                            + "\n" + _END_STATEMENT

        token_manager = JWTTokenManager(None)
        zone_id = token_manager.extract_zone_id(access_token)
        LOG.info('zone id %s', zone_id)
        token_result, tkn = token_manager._offline_validate(
            access_token,
            public_key=formatted_key,
            scopes=[os.environ['SCOPES_REQUIRED']])
        return token_result, tkn
Example #2
0
def authorize_fs(original_token=None, request=None, fs_name=None):
    _validate_xs_uaa_config()
    try:
        if not fs_name:
            fs_name = os.environ[MLP_MLSERVICE_NAME]
        assert fs_name

        if not original_token:
            original_token = get_authorization_header(request)

        token_manager = JWTTokenManager(base_url=os.environ[MLP_UAA_BASE_URL])
        public_key = os.environ[MLP_UAA_PUBLIC_KEY] = os.getenv(
            MLP_UAA_PUBLIC_KEY) or token_manager.get_public_key()
        validation_scopes = [r'^.*\.{}$'.format(fs_name), r'^.*\.sapcustomer$']
        token_ok, access_token = token_manager.validate(
            access_token=original_token,
            scope_regex=validation_scopes,
            public_key=public_key,
            online=False)
        assert token_ok
        assert access_token == original_token
        LOG.info("Token is valid. Returning original token...")
        return access_token
    except Exception as err:
        raise SecurityError('Unable to authorize the request.',
                            root_cause=err,
                            code=getattr(err, 'code', 401)) from err
class TestValidateTokenOffline(unittest.TestCase):
    def setUp(self):
        self.tm = JWTTokenManager(None)
    

    def test_validate_token_offline_success(self):
        token_ok, access_token = self.tm.validate(token_expired_in_2085, public_key=public_key)
        self.assertTrue(token_ok)
        self.assertEqual(access_token, token_expired_in_2085)

    def test_validate_token_offline_success_with_scopes(self):
        token_ok, access_token = self.tm.validate(token_expired_in_2085, public_key=public_key, scopes=['mlptestclient'])
        self.assertTrue(token_ok)
        self.assertEqual(access_token, token_expired_in_2085)

    def test_validate_token_offline_invalid_alg(self):
        token_with_alg_hs256 = 'Bearer eyJhbGciOiAiSFMyNTYiLCAia2lkIjogImxlZ2FjeS10b2tlbi1rZXkiLCAidHlwIjogIkpXVCJ9.eyJqdGkiOiI4Yzk3YWZjM2I4Mzk0N2E5OWVhMjMyNzE3Y2U3ZTFjMyIsInN1YiI6Im1scHRlc3RjbGllbnQiLCJhdXRob3JpdGllcyI6WyJtbHB0ZXN0Y2xpZW50Il0sInNjb3BlIjpbIm1scHRlc3RjbGllbnQiXSwiY2xpZW50X2lkIjoibWxwdGVzdGNsaWVudCIsImNpZCI6Im1scHRlc3RjbGllbnQiLCJhenAiOiJtbHB0ZXN0Y2xpZW50IiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiJiNThjNWQ0ZiIsImlhdCI6MTQ4NjYzNDIzMSwiZXhwIjozNjMxMDgyMjMxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbIm1scHRlc3RjbGllbnQiXX0.nIl71Dxktizfb5B870Mlh_-62kN9_Wlda8WYbiz3iFaj22LzIUkQiRIAI57g3IwPXbJnJ1tlrf5_DIJpycRxzfxIZnW_GJW56sgY5L4mdPVHSIUHjeFh5v5tGwmOG6a1mYH_H0y8G-nHNolfSejcyvc4RYvcba4kS2nm-wDKKgfqDVaspM4Ktsa15eLHYn1P0LIUEsewTDm3qL_PgbJC3WKq_qgk02B5Or1n0doLkGBtccYlQEZ9lRixmkdov7_4Nl9UNTPgaYchC0AEaxd_RRCBK78FwC6tw3v1X3xJFXoYdJlMNOnTGdbQ4CVP5-Jd7gifPnUilPPPoJmITg0HZQ'
        self.assertRaises(SecurityError, self.tm.validate, token_with_alg_hs256,
                          public_key=public_key)


    def test_validate_token_offline_invalid_public_key(self):
        token =''
        self.assertRaises(SecurityError, self.tm.validate, token)

    def test_validate_token_offline_token_expired(self):
        token_expired = 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS1pZC0xIn0.eyJqdGkiOiIyYmZlYjYyOGVmNDk0MTFmYTk0ZTY1OTk4MjdiMjdiMCIsImV4dF9hdHRyIjp7ImVuaGFuY2VyIjoiWFNVQUEifSwic3ViIjoic2ItbWxmc2ctc3RkLTE4MDMhYjMxMyIsImF1dGhvcml0aWVzIjpbIm1sZnNnLXN0ZC0xODAzIWIzMTMucmV0cmFpbnNlcnZpY2UucmVhZCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMuc3RvcmFnZWFwaS5hbGwiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVscmVwby53cml0ZSIsIm1sZnNnLXN0ZC0xODAzIWIzMTMucmV0cmFpbnNlcnZpY2Uud3JpdGUiLCJ1YWEucmVzb3VyY2UiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLmZ1bmN0aW9uYWxzZXJ2aWNlLmFsbCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMubW9kZWxzZXJ2aWNlLnJlYWQiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVsbWV0ZXJpbmcucmVhZCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMubW9kZWxyZXBvLnJlYWQiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLmRhdGFtYW5hZ2VtZW50LndyaXRlIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5tb2RlbGRlcGxveW1lbnQuYWxsIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5kYXRhbWFuYWdlbWVudC5yZWFkIl0sInNjb3BlIjpbIm1sZnNnLXN0ZC0xODAzIWIzMTMucmV0cmFpbnNlcnZpY2UucmVhZCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMuc3RvcmFnZWFwaS5hbGwiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVscmVwby53cml0ZSIsIm1sZnNnLXN0ZC0xODAzIWIzMTMucmV0cmFpbnNlcnZpY2Uud3JpdGUiLCJ1YWEucmVzb3VyY2UiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLmZ1bmN0aW9uYWxzZXJ2aWNlLmFsbCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMubW9kZWxzZXJ2aWNlLnJlYWQiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVsbWV0ZXJpbmcucmVhZCIsIm1sZnNnLXN0ZC0xODAzIWIzMTMubW9kZWxyZXBvLnJlYWQiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLmRhdGFtYW5hZ2VtZW50LndyaXRlIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5tb2RlbGRlcGxveW1lbnQuYWxsIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5kYXRhbWFuYWdlbWVudC5yZWFkIl0sImNsaWVudF9pZCI6InNiLW1sZnNnLXN0ZC0xODAzIWIzMTMiLCJjaWQiOiJzYi1tbGZzZy1zdGQtMTgwMyFiMzEzIiwiYXpwIjoic2ItbWxmc2ctc3RkLTE4MDMhYjMxMyIsImdyYW50X3R5cGUiOiJjbGllbnRfY3JlZGVudGlhbHMiLCJyZXZfc2lnIjoiNmM5MWI4ZjEiLCJpYXQiOjE1MjMyNjg0MjUsImV4cCI6MTUyMzMxMTYyNSwiaXNzIjoiaHR0cDovL2ZvdW5kYXRpb24ubG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoiZm91bmRhdGlvbiIsImF1ZCI6WyJtbGZzZy1zdGQtMTgwMyFiMzEzLnN0b3JhZ2VhcGkiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVscmVwbyIsIm1sZnNnLXN0ZC0xODAzIWIzMTMubW9kZWxkZXBsb3ltZW50IiwidWFhIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5mdW5jdGlvbmFsc2VydmljZSIsIm1sZnNnLXN0ZC0xODAzIWIzMTMuZGF0YW1hbmFnZW1lbnQiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLm1vZGVsbWV0ZXJpbmciLCJzYi1tbGZzZy1zdGQtMTgwMyFiMzEzIiwibWxmc2ctc3RkLTE4MDMhYjMxMy5tb2RlbHNlcnZpY2UiLCJtbGZzZy1zdGQtMTgwMyFiMzEzLnJldHJhaW5zZXJ2aWNlIl19.e6zz6EeRi_5rpevEUsQNiEpsgy1WKebFw6SIAUZ7TCBGOHaQUPWo4bXPlpgVgtUZJBqKKaGe0Fs9WgPJXwbt7DBV1f8i6OTi6osKEnyB0RPWYfSAqr6H3qKDuGYD08aIALX-kRzE_an0QD6QgkJbZ6BLxidXbxNmI0PBZiSmaID9NrrG2batOuGNOWfORn8ztnURPvHZpl7o5Te28jeiris1blEJhfBmiOmuUb-trevWEztlkBgSjai7bI90H85gFyrbYLCQCr13qnJwOW6PSI1Two2syzOb7S92ZVhfDY6CQNkW7lTgQ64zzh7RUJQiTTciaBpH-N-90iSNx3DTow'
        self.assertRaises(SecurityError, self.tm.validate, token_expired)

    def test_validate_token_offline_insufficient_scope(self):
        self.assertRaises(SecurityError, self.tm.validate, token_expired_in_2085, scopes=['some-required-scope', 'mlptestclient'],
                          public_key=public_key)
Example #4
0
def authorize(original_token=None, request=None, xs_app_name=None, scopes=None):
    """
    To validate OAuth JWT.
    It checks JWT in `Authorization` header of the given `request` object
    against given `xs_app_name` and `scopes`

    This will be offline validation and a public key will be retrieved from configured UAA base URL
    and RSA256 algorithm will be used for validation.

    :param request: request object which should contain a `headers` property
    :param original_token: original token, can be specified explicitly if request object is not provided.
    :param xs_app_name: if not specified, will default to 'xsappname' configured in VCAP_SERVICES
    :param scopes: scopes to validate
    :return: validated `access_token`
    :raises SecurityError: If no authorization token or token is invalid.
    """
    if not use_xs_uaa():
        raise SecurityError('Application is expected to configure for XSUAA but configured for CFUAA.', code=500)

    if not xs_app_name:
        xs_app_name = os.getenv(MLP_MLSERVICE_XSAPPNAME)

    if not scopes:
        default_scopes = os.getenv(MLP_MLSERVICE_DEFAULT_SCOPES)
        if default_scopes:
            scopes = default_scopes.split(",")
        else:
            raise SecurityError('No default auth scopes defined. Parameter `scopes` need to be provided', code=500)

    if not xs_app_name or not scopes:
        raise SecurityError('XS App Name and Scopes are mandatory', code=500)

    try:
        if not original_token:
            original_token = get_authorization_header(request)

        validation_scopes = ['{}.{}'.format(xs_app_name, scope) for scope in scopes]
        token_manager = JWTTokenManager(base_url=os.getenv(MLP_UAA_BASE_URL))
        public_key = os.environ[MLP_UAA_PUBLIC_KEY] = os.getenv(MLP_UAA_PUBLIC_KEY) or token_manager.get_public_key()
        token_ok, access_token = token_manager.validate(access_token=original_token,
                                                        scopes=validation_scopes,
                                                        public_key=public_key,
                                                        online=False)
        assert token_ok
        assert access_token == original_token
        LOG.info("Token is valid. Returning original token...")
        return access_token
    except Exception as err:
        raise SecurityError('Unable to authorize the request.', root_cause=err,
                            code=getattr(err, 'code', 401)) from err
def authorize(request, *extra_scopes):
    """
    To validate OAuth JWT.
    It checks JWT in `Authorization` header of the given `request` object
    against given `training_names` (if any) and `tenantName` or `globalTenantName` (configurable).

    This will be offline validation and a public key will be retrieved from configured UAA base URL
    and RSA256 algorithm will be used for validation.

    :param request: request object which should contain a `headers` property
    :param extra_scopes: extra_scopes that should appear in scope list
    :return: `access_token` (with original type prefix, e.g.: `Bearer some_token`).
    :raises SecurityError: If no authorization token or no tenantName/globalTenantName in header or token is invalid.
    """
    _validate_cf_uaa_config()
    try:
        original_token = get_authorization_header(request)
        tenant_name, global_tenant_name = _check_tenant_info(request)
        token_manager = JWTTokenManager(
            base_url=os.environ[CLEA_UAA_SERVER_BASE_URL])
        public_key = os.environ[MLP_UAA_PUBLIC_KEY] = os.getenv(
            MLP_UAA_PUBLIC_KEY) or token_manager.get_public_key()
        validation_scopes = [global_tenant_name
                             ] if global_tenant_name else [tenant_name]
        validation_scopes.extend(extra_scopes)
        token_ok, access_token = token_manager.validate(
            access_token=original_token,
            scopes=validation_scopes,
            public_key=public_key,
            online=False)
        assert token_ok
        assert access_token == original_token
        LOG.info("Token is valid. Returning original token...")
        return access_token
    except Exception as err:
        raise SecurityError('Unable to authorize the request.',
                            root_cause=err,
                            code=getattr(err, 'code', 401)) from err
class TestValidateTokenOffline(unittest.TestCase):
    def setUp(self):
        self.tm = JWTTokenManager('https://www.some_url.com')

    def test_validate_token_offline_success(self):
        token_ok, access_token = self.tm.validate(token_expired_in_2085, public_key=public_key)
        self.assertTrue(token_ok)
        self.assertEqual(access_token, token_expired_in_2085)

    def test_validate_token_offline_success_with_scopes(self):
        token_ok, access_token = self.tm.validate(token_expired_in_2085, public_key=public_key, scopes=['mlptestclient'])
        self.assertTrue(token_ok)
        self.assertEqual(access_token, token_expired_in_2085)

    def test_validate_token_offline_success_with_scope_regex(self):
        token_ok, access_token = self.tm.validate(token_expired_in_2085, public_key=public_key, scope_regex=[r'^.*client$'])
        self.assertTrue(token_ok)
        self.assertEqual(access_token, token_expired_in_2085)

    def test_validate_token_offline_invalid_public_key(self):
        token = ''
        self.assertRaises(SecurityError, self.tm.validate, token)

    def test_validate_token_offline_invalid_alg(self):
        token_with_alg_hs256 = 'Bearer eyJhbGciOiAiSFMyNTYiLCAia2lkIjogImxlZ2FjeS10b2tlbi1rZXkiLCAidHlwIjogIkpXVCJ9.eyJqdGkiOiI4Yzk3YWZjM2I4Mzk0N2E5OWVhMjMyNzE3Y2U3ZTFjMyIsInN1YiI6Im1scHRlc3RjbGllbnQiLCJhdXRob3JpdGllcyI6WyJtbHB0ZXN0Y2xpZW50Il0sInNjb3BlIjpbIm1scHRlc3RjbGllbnQiXSwiY2xpZW50X2lkIjoibWxwdGVzdGNsaWVudCIsImNpZCI6Im1scHRlc3RjbGllbnQiLCJhenAiOiJtbHB0ZXN0Y2xpZW50IiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiJiNThjNWQ0ZiIsImlhdCI6MTQ4NjYzNDIzMSwiZXhwIjozNjMxMDgyMjMxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbIm1scHRlc3RjbGllbnQiXX0.nIl71Dxktizfb5B870Mlh_-62kN9_Wlda8WYbiz3iFaj22LzIUkQiRIAI57g3IwPXbJnJ1tlrf5_DIJpycRxzfxIZnW_GJW56sgY5L4mdPVHSIUHjeFh5v5tGwmOG6a1mYH_H0y8G-nHNolfSejcyvc4RYvcba4kS2nm-wDKKgfqDVaspM4Ktsa15eLHYn1P0LIUEsewTDm3qL_PgbJC3WKq_qgk02B5Or1n0doLkGBtccYlQEZ9lRixmkdov7_4Nl9UNTPgaYchC0AEaxd_RRCBK78FwC6tw3v1X3xJFXoYdJlMNOnTGdbQ4CVP5-Jd7gifPnUilPPPoJmITg0HZQ'
        self.assertRaises(SecurityError, self.tm.validate, token_with_alg_hs256,
                          public_key=public_key)

    def test_validate_token_offline_token_expired(self):
        token_expired = 'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLCJ0eXAiOiJKV1QifQ.eyJqdGkiOiI0YTQwZGFjN2VkMTM0YjJhYTBhZjZiMTg3MmVjOTgzZSIsInN1YiI6Im1scHRlc3RjbGllbnQiLCJhdXRob3JpdGllcyI6WyJtbHB0ZXN0Y2xpZW50Il0sInNjb3BlIjpbIm1scHRlc3RjbGllbnQiXSwiY2xpZW50X2lkIjoibWxwdGVzdGNsaWVudCIsImNpZCI6Im1scHRlc3RjbGllbnQiLCJhenAiOiJtbHB0ZXN0Y2xpZW50IiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiIyNDQ0ZDRiMCIsImlhdCI6MTQ4NjYzNTI0OSwiZXhwIjoxNDg2NjM1MjU5LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbIm1scHRlc3RjbGllbnQiXX0.DJisxENzMhZVh5ZyWuXpph1ffI3iuDJw4GT1WOfTA5vbxjqVw06LxRhV-061j7LtzyHaOQOjGVUG_QoyHvq-Hx2Ddo-FAYmjXnkUMChLsNNEi-Kb4IjYKs2yRvePRMuIiF673JPUJ0UhS1DS-EC4LZhyCqg41-5eAvOgzFxJIXWbCAAMPmApUVHv10QGqqjDZnTekAKcmJa9-I5XAZksylGyuhsKrN5r-vjsVpoVeGhtJ_ezzCku3PqdQvkYRxOsOZT9aJ5xanYqC7E50uVgG6lAyYIFXO6pfxomU62Iv_1OcqEA27Rvx2w7nEEqhQBYnZitK5c26vCd-UMK-EasQw'
        self.assertRaises(SecurityError, self.tm.validate, token_expired,
                          public_key=public_key)

    def test_validate_token_offline_insufficient_scope(self):
        self.assertRaises(SecurityError, self.tm.validate, token_expired_in_2085, scopes=['some-required-scope', 'mlptestclient'],
                          public_key=public_key)
Example #7
0
def authorize_bs(training_name,
                 original_token=None,
                 request=None,
                 bs_name=None):
    _validate_xs_uaa_config(is_bs=True)
    try:
        if not bs_name:
            bs_name = os.environ[MLP_MLSERVICE_NAME]
        assert bs_name

        if not original_token:
            original_token = get_authorization_header(request)

        token_manager = JWTTokenManager(base_url=os.environ[MLP_UAA_BASE_URL])
        public_key = os.environ[MLP_UAA_PUBLIC_KEY] = os.getenv(
            MLP_UAA_PUBLIC_KEY) or token_manager.get_public_key()
        tenant_name, suffix = token_manager.extract_tenant_name(original_token)
        validation_scopes = [r'.*\.{}$'.format(bs_name)]
        token_ok, access_token = token_manager.validate(
            access_token=original_token,
            scope_regex=validation_scopes,
            public_key=public_key,
            online=False)
        assert token_ok
        assert access_token == original_token
        LOG.info("Token is valid. Retrieving new token...")
        retrieval_scopes = [
            '{}!{}.{}'.format(bs_name, suffix, training_name),
            '{}!{}.{}'.format(bs_name, suffix, tenant_name)
        ]
        access_token = token_manager.retrieve_token_str(
            (os.environ[MLP_UAA_NEW_TOKEN_CLIENT_ID],
             os.environ[MLP_UAA_NEW_TOKEN_CLIENT_SECRET]),
            scopes=retrieval_scopes)
        assert access_token != original_token, 'Retrieved new token should be different from original token.'
        LOG.info('Returning new token...')
        return access_token
    except Exception as err:
        raise SecurityError('Unable to authorize the request.',
                            root_cause=err,
                            code=getattr(err, 'code', 401)) from err
 def setUp(self):
     self.tm = JWTTokenManager('https://www.some_url.com')
     self.tc = TokenCache()
     self.tc._clear()
class TestRetrieveToken(unittest.TestCase):
    def setUp(self):
        self.tm = JWTTokenManager('https://www.some_url.com')
        self.tc = TokenCache()
        self.tc._clear()

    def tearDown(self):
        if os.getenv(VCAP_SERVICES):
            del os.environ[VCAP_SERVICES]
        if os.getenv(MLP_FOUNDATION_SERVICE_NAME):
            del os.environ[MLP_FOUNDATION_SERVICE_NAME]
        if os.getenv(MLP_FOUNDATION_SERVICE_INSTANCE_NAME):
            del os.environ[MLP_FOUNDATION_SERVICE_INSTANCE_NAME]

    @patch('mlpkitsecurity.token_utils.urlopen',
           Mock(return_value=MockResponse('{"access_token":"some_token", "expires_in":100}')))
    def test_retrieve_token_str_with_cache(self):
        # cred is plain text
        cred = ['client', 'secret']
        token_str = self.tm.retrieve_token_str(token_retrieval_cred=cred,
                                               scopes=['scope'],
                                               use_cache=True)
        self.assertEqual(token_str, 'Bearer some_token')
        cache_key = 'mlp::{}scope'.format(str(cred))
        self.assertEqual(self.tc.__class__._tokens[cache_key][0], 'some_token')
        self.assertIsInstance(self.tc.__class__._tokens[cache_key][1], float)

        # cred is UaaBasicCredenticals
        cred = UaaBasicCredentials(self.tm.base_url, 'client', 'secret')
        token_str = self.tm.retrieve_token_str(token_retrieval_cred=cred,
                                               scopes=['scope'],
                                               use_cache=True)
        self.assertEqual(token_str, 'Bearer some_token')
        cache_key = 'mlp::{}scope'.format(str(cred))
        self.assertEqual(self.tc.__class__._tokens[cache_key][0], 'some_token')
        self.assertIsInstance(self.tc.__class__._tokens[cache_key][1], float)

    @patch('mlpkitsecurity.token_utils.urlopen',
           Mock(return_value=MockResponse('{"access_token":"some_token", "expires_in":100}')))
    def test_retrieve_token_str_without_cache(self):
        token_str = self.tm.retrieve_token_str(token_retrieval_cred=['client', 'secret'],
                                               scopes=['scope'],
                                               use_cache=False)
        self.assertEqual(token_str, 'Bearer some_token')

    @patch('mlpkitsecurity.token_utils.urlopen',
           Mock(return_value=MockResponse('{"access_token":"some_token", "expires_in":100}')))
    def test_parse_retrieve_response(self):
        res = self.tm.retrieve(token_retrieval_cred=['client', 'secret'])
        self.assertEqual(self.tm.parse_retrieve_response(res), 'some_token')

    @patch('mlpkitsecurity.token_utils.urlopen',
           Mock(return_value=MockResponse('{"access_token":"some_token", "expires_in":100}')))
    def test_retrieve_token_for_a_given_service_broker_instance_name(self):
        os.environ[VCAP_SERVICES] = VCAP_SERVICES_V2
        os.environ[MLP_FOUNDATION_SERVICE_NAME] = 'ml-foundation'
        os.environ[MLP_FOUNDATION_SERVICE_INSTANCE_NAME] = 'ml-foundation-std'
        token_str = retrieve_foundation_service_token()
        self.assertEqual(token_str, 'Bearer some_token')

    def test_retrieve_token_for_an_invalid_foundation_service_instance_name(self):
        os.environ[VCAP_SERVICES] = VCAP_SERVICES_V2
        os.environ[MLP_FOUNDATION_SERVICE_NAME] = 'ml-foundation'
        os.environ[MLP_FOUNDATION_SERVICE_INSTANCE_NAME] = 'invalid-name'
        with self.assertRaises(SecurityError) as context:
            retrieve_foundation_service_token()
        self.assertEqual(context.exception.code, 500)
        self.assertEqual(context.exception.detail_info,
                         'Unable to find service instance config for MLP_FOUNDATION_SERVICE_INSTANCE_NAME=invalid-name')

    def test_retrieve_token_expect_foundation_service_instance_name(self):
        os.environ[VCAP_SERVICES] = VCAP_SERVICES_V2
        os.environ[MLP_FOUNDATION_SERVICE_NAME] = 'ml-foundation'
        with self.assertRaises(SecurityError) as context:
            retrieve_foundation_service_token()
        self.assertEqual(context.exception.code, 500)
        self.assertEqual(context.exception.detail_info, 'MLP_FOUNDATION_SERVICE_INSTANCE_NAME is mandatory.')

    def test_retrieve_token_expect_foundation_service_name(self):
        os.environ[VCAP_SERVICES] = VCAP_SERVICES_V2
        os.environ[MLP_FOUNDATION_SERVICE_NAME] = 'invalid-foundation-service-name'
        os.environ[MLP_FOUNDATION_SERVICE_INSTANCE_NAME] = 'ml-foundation-std'
        with self.assertRaises(SecurityError) as context:
            retrieve_foundation_service_token()
        self.assertEqual(context.exception.code, 500)
        self.assertEqual(context.exception.detail_info,
                         'Unable to find service instance config for '
                         'MLP_FOUNDATION_SERVICE_NAME=invalid-foundation-service-name')
 def setUp(self):
     self.tm = JWTTokenManager('https://www.some_url.com')
class TestJWTTokenManager(unittest.TestCase):
    def setUp(self):
        self.tm = JWTTokenManager('https://www.some_url.com')

    @patch('mlpkitsecurity.token_utils.urlopen',
           Mock(return_value=MockResponse('{{"keys":[{{"value":"{}"}}]}}'.format(public_key.replace('\n', '\\n')))))
    def test_get_public_key(self):
        self.assertEqual(self.tm.get_public_key(), public_key)

    def test_extract_tenant_name(self):
        extracted_tenant, suffix = self.tm.extract_tenant_name(bs_token)
        self.assertEqual((extracted_tenant, suffix), ('some-uuid', 't53'))

    def test_extract_scopes(self):
        extracted_scopes = self.tm.extract_scopes(token_expired_in_2085)
        self.assertListEqual(extracted_scopes, ['mlptestclient'])

    def test_extract_scopes_func(self):
        extracted_scopes = extract_scopes(token_expired_in_2085)
        self.assertListEqual(extracted_scopes, ['mlptestclient'])

    def test_extract_zone_id(self):
        self.assertEqual('uaa', self.tm.extract_zone_id(token_expired_in_2085))
        self.assertEqual('uaa', self.tm.extract_zone_id(xs_token))

    def test_extract_zone_id_func(self):
        self.assertEqual('uaa', extract_zone_id(token_expired_in_2085))
        self.assertEqual('uaa', extract_zone_id(xs_token))

    def test_validate_scopes_ok(self):
        ok, tkn = self.tm.validate_scopes(bs_token, scopes=['some-uuid!t53.test_bs_name'])
        self.assertTrue(ok)
        self.assertEqual(tkn, bs_token)

        ok, tkn = self.tm.validate_scopes(bs_token, scope_regex=[r'^.*\.test_bs_name'])
        self.assertTrue(ok)
        self.assertEqual(tkn, bs_token)

        ok, tkn = self.tm.validate_scopes(token_expired_in_2085, scopes=['mlptestclient'])
        self.assertTrue(ok)
        self.assertEqual(tkn, token_expired_in_2085)

        ok, tkn = self.tm.validate_scopes(token_expired_in_2085, scope_regex=[r'mlptestclient'])
        self.assertTrue(ok)
        self.assertEqual(tkn, token_expired_in_2085)

    def test_validate_scopes_ok_func(self):
        ok, tkn = validate_scopes(bs_token, scopes=['some-uuid!t53.test_bs_name'])
        self.assertTrue(ok)
        self.assertEqual(tkn, bs_token)

        ok, tkn = validate_scopes(bs_token, scope_regex=[r'^.*\.test_bs_name'])
        self.assertTrue(ok)
        self.assertEqual(tkn, bs_token)

        ok, tkn = validate_scopes(token_expired_in_2085, scopes=['mlptestclient'])
        self.assertTrue(ok)
        self.assertEqual(tkn, token_expired_in_2085)

        ok, tkn = validate_scopes(token_expired_in_2085, scope_regex=[r'mlptestclient'])
        self.assertTrue(ok)
        self.assertEqual(tkn, token_expired_in_2085)

    def test_validate_scopes_invalid(self):
        self.assertRaises(SecurityError, self.tm.validate_scopes, bs_token, scopes=['invalid-scope'])
        self.assertRaises(SecurityError, self.tm.validate_scopes,
                          token_expired_in_2085, scopes=['mlptestclient', 'invalid-scope'])
        self.assertRaises(SecurityError, self.tm.validate_scopes,
                          token_expired_in_2085, scope_regex=[r'^.*\.test_bs_name'])

        # opaque token
        self.assertRaises(SecurityError, self.tm.validate_scopes, 'Bearer d1228d2e594e494db2b199c15038be31')

    def test_validate_scopes_invalid_func(self):
        self.assertRaises(SecurityError, validate_scopes, bs_token, scopes=['invalid-scope'])
        self.assertRaises(SecurityError, validate_scopes,
                          token_expired_in_2085, scopes=['mlptestclient', 'invalid-scope'])
        self.assertRaises(SecurityError, validate_scopes,
                          token_expired_in_2085, scope_regex=[r'^.*\.test_bs_name'])

        # opaque token
        self.assertRaises(SecurityError, validate_scopes, 'Bearer d1228d2e594e494db2b199c15038be31')
 def setUp(self):
     self.tm = JWTTokenManager(None)