def test_required_claims(self, claim): """ Verify that tokens that do not carry 'exp' or 'iat' claims are rejected """ # Deletes required claim from payload del self.payload[claim] token = generate_jwt_token(self.payload) with self.assertRaises(jwt.MissingRequiredClaimError): # Decode to see if MissingRequiredClaimError exception is raised or not jwt_decode_handler(token)
def test_unsupported_jwt_version(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token version is not supported. """ with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger') as patched_log: with self.assertRaises(jwt.InvalidTokenError): token = generate_jwt_token(self.payload) jwt_decode_handler(token) msg = "Token decode failed due to unsupported JWT version number [%s]" patched_log.info.assert_any_call(msg, '1.1.0')
def test_failure_invalid_token(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token cannot be decoded """ # Create tokens using each invalid issuer and attempt to decode them against # the valid issuers list, which won't work with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger') as patched_log: with self.assertRaises(jwt.InvalidTokenError): # Attempt to decode an invalid token, which will fail with an InvalidTokenError jwt_decode_handler("invalid.token") patched_log.exception.assert_any_call("Token verification failed.")
def test_unsupported_jwt_version(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token version is not supported. """ with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger' ) as patched_log: with self.assertRaises(jwt.InvalidTokenError): token = generate_jwt_token(self.payload) jwt_decode_handler(token) msg = "Token decode failed due to unsupported JWT version number [%s]" patched_log.info.assert_any_call(msg, '1.1.0')
def test_failure_invalid_token(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token cannot be decoded """ # Create tokens using each invalid issuer and attempt to decode them against # the valid issuers list, which won't work with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger' ) as patched_log: with self.assertRaises(jwt.InvalidTokenError): # Attempt to decode an invalid token, which will fail with an InvalidTokenError jwt_decode_handler("invalid.token") patched_log.exception.assert_any_call("Token verification failed.")
def test_supported_jwt_version(self, jwt_version): """ Verifies the JWT is decoded successfully with different supported versions in the token. """ jwt_payload = generate_latest_version_payload(self.user, version=jwt_version) token = generate_jwt_token(jwt_payload) self.assertDictEqual(jwt_decode_handler(token), jwt_payload)
def test_supported_jwt_version(self, jwt_version): """ Verifies the JWT is decoded successfully with different supported versions in the token. """ jwt_payload = generate_latest_version_payload(self.user, version=jwt_version) token = generate_jwt_token(jwt_payload) self.assertDictEqual(jwt_decode_handler(token), jwt_payload)
def test_failure_invalid_issuer(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token cannot be decoded """ # Create tokens using each invalid issuer and attempt to decode them against # the valid issuers list, which won't work with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger') as patched_log: with self.assertRaises(jwt.InvalidTokenError): self.payload['iss'] = 'invalid-issuer' signing_key = 'invalid-secret-key' # Generate a token using the invalid issuer data token = generate_jwt_token(self.payload, signing_key) # Attempt to decode the token against the entries in the valid issuers list, # which will fail with an InvalidTokenError jwt_decode_handler(token) patched_log.exception.assert_any_call("Token verification failed.")
def test_valid_token_multiple_valid_issuers(self, jwt_issuer): """ Validates that a valid token is properly decoded given a list of multiple valid issuers """ # Verify that each valid issuer is properly matched against the valid issuers list # and used to decode the token that was generated using said valid issuer data self.payload['iss'] = jwt_issuer['ISSUER'] token = generate_jwt_token(self.payload, jwt_issuer['SECRET_KEY']) self.assertEqual(jwt_decode_handler(token), self.payload)
def test_get_decoded_jwt_from_existing_cookie(self): user = UserFactory() payload = generate_latest_version_payload(user) jwt = generate_jwt_token(payload) expected_decoded_jwt = jwt_decode_handler(jwt) mock_request_with_cookie = mock.Mock(COOKIES={'edx-jwt-cookie': jwt}) decoded_jwt = cookies.get_decoded_jwt(mock_request_with_cookie) self.assertEqual(expected_decoded_jwt, decoded_jwt)
def test_get_decoded_jwt_from_existing_cookie(self): user = UserFactory() payload = generate_latest_version_payload(user) jwt = generate_jwt_token(payload) expected_decoded_jwt = jwt_decode_handler(jwt) mock_request_with_cookie = mock.Mock(COOKIES={'edx-jwt-cookie': jwt}) decoded_jwt = cookies.get_decoded_jwt(mock_request_with_cookie) self.assertEquals(expected_decoded_jwt, decoded_jwt)
def test_valid_token_multiple_valid_issuers(self, jwt_issuer): """ Validates that a valid token is properly decoded given a list of multiple valid issuers """ # Verify that each valid issuer is properly matched against the valid issuers list # and used to decode the token that was generated using said valid issuer data self.payload['iss'] = jwt_issuer['ISSUER'] token = generate_jwt_token(self.payload, jwt_issuer['SECRET_KEY']) self.assertEqual(jwt_decode_handler(token), self.payload)
def test_failure_invalid_issuer(self): """ Verifies the function logs decode failures, and raises an InvalidTokenError if the token cannot be decoded """ # Create tokens using each invalid issuer and attempt to decode them against # the valid issuers list, which won't work with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger' ) as patched_log: with self.assertRaises(jwt.InvalidTokenError): self.payload['iss'] = 'invalid-issuer' signing_key = 'invalid-secret-key' # Generate a token using the invalid issuer data token = generate_jwt_token(self.payload, signing_key) # Attempt to decode the token against the entries in the valid issuers list, # which will fail with an InvalidTokenError jwt_decode_handler(token) patched_log.exception.assert_any_call("Token verification failed.")
def get_decoded_jwt_from_auth(request): """ Grab jwt from request.auth in request if possible. Returns a decoded jwt dict if it can be found. Returns None if the jwt is not found. """ if not is_jwt_authenticated(request): return None return jwt_decode_handler(request.auth)
def test_upgrade(self): """ Verifies the JWT is upgraded when an old (starting) version is provided. """ jwt_payload = generate_unversioned_payload(self.user) token = generate_jwt_token(jwt_payload) upgraded_payload = generate_latest_version_payload(self.user, version='1.0.0') # Keep time-related values constant for full-proof comparison. upgraded_payload['iat'], upgraded_payload['exp'] = jwt_payload['iat'], jwt_payload['exp'] self.assertDictEqual(jwt_decode_handler(token), upgraded_payload)
def get_decoded_jwt(request): """ Grab jwt from jwt cookie in request if possible. Returns a decoded jwt dict if it can be found. Returns None if the jwt is not found. """ jwt_cookie = request.COOKIES.get(jwt_cookie_name(), None) if not jwt_cookie: return None return jwt_decode_handler(jwt_cookie)
def get_decoded_jwt_from_request(request): """ Grab jwt from request if possible. Returns a decoded jwt dict if it finds it. Returns a None if it does not. """ jwt_cookie = request.COOKIES.get(jwt_cookie_name(), None) or getattr( request, 'auth', None) if not jwt_cookie: return None return jwt_decode_handler(jwt_cookie)
def test_failure_invalid_issuer(self): """ Verifies the function logs decode failures with invalid issuer, and raises an InvalidTokenError if the token cannot be decoded """ # Create tokens using each invalid issuer and attempt to decode them against # the valid issuers list, which won't work with mock.patch('edx_rest_framework_extensions.auth.jwt.decoder.logger' ) as patched_log: with self.assertRaises(jwt.InvalidTokenError): self.payload['iss'] = 'invalid-issuer' # signing key of None will use the default valid signing key valid_signing_key = None # Generate a token using the invalid issuer data token = generate_jwt_token(self.payload, valid_signing_key) # Attempt to decode the token against the entries in the valid issuers list, # which will fail with an InvalidTokenError jwt_decode_handler(token) msg = "Token decode failed due to mismatched issuer [%s]" patched_log.info.assert_any_call(msg, 'invalid-issuer')
def test_upgrade(self): """ Verifies the JWT is upgraded when an old (starting) version is provided. """ jwt_payload = generate_unversioned_payload(self.user) token = generate_jwt_token(jwt_payload) upgraded_payload = generate_latest_version_payload(self.user, version='1.0.0') # Keep time-related values constant for full-proof comparison. upgraded_payload['iat'], upgraded_payload['exp'] = jwt_payload[ 'iat'], jwt_payload['exp'] self.assertDictEqual(jwt_decode_handler(token), upgraded_payload)
def test_get_decoded_jwt_from_auth(self, is_jwt_authentication): """ Verify get_decoded_jwt_from_auth returns the appropriate value. """ # Mock out the `is_jwt_authenticated` method authentication.is_jwt_authenticated = lambda request: is_jwt_authentication jwt_token = self._get_test_jwt_token() mock_request_with_cookie = mock.Mock(COOKIES={}, auth=jwt_token) expected_decoded_jwt = jwt_decode_handler( jwt_token) if is_jwt_authentication else None decoded_jwt = authentication.get_decoded_jwt_from_auth( mock_request_with_cookie) self.assertEqual(expected_decoded_jwt, decoded_jwt)
def _assert_recreate_jwt_from_cookies(self, response, can_recreate): """ If can_recreate is True, verifies that a JWT can be properly recreated from the 2 separate JWT-related cookies using the JwtAuthCookieMiddleware middleware and returns the recreated JWT. If can_recreate is False, verifies that a JWT cannot be recreated. """ self._copy_cookies_to_request(response, self.request) JwtAuthCookieMiddleware().process_view(self.request, None, None, None) assert (cookies_api.jwt_cookies.jwt_cookie_name() in self.request.COOKIES) == can_recreate if can_recreate: jwt_string = self.request.COOKIES[ cookies_api.jwt_cookies.jwt_cookie_name()] jwt = jwt_decode_handler(jwt_string) assert jwt['scopes'] == ['user_id', 'email', 'profile']
def _assert_recreate_jwt_from_cookies(self, response, can_recreate): """ If can_recreate is True, verifies that a JWT can be properly recreated from the 2 separate JWT-related cookies using the JwtAuthCookieMiddleware middleware and returns the recreated JWT. If can_recreate is False, verifies that a JWT cannot be recreated. """ self._copy_cookies_to_request(response, self.request) JwtAuthCookieMiddleware().process_request(self.request) self.assertEqual( cookies_api.jwt_cookies.jwt_cookie_name() in self.request.COOKIES, can_recreate, ) if can_recreate: jwt_string = self.request.COOKIES[cookies_api.jwt_cookies.jwt_cookie_name()] jwt = jwt_decode_handler(jwt_string) self.assertEqual(jwt['scopes'], ['email', 'profile'])
def test_get_decoded_jwt_from_auth(self, is_jwt_authentication): """ Verify get_decoded_jwt_from_auth returns the appropriate value. """ # Mock out the `is_jwt_authenticated` method authentication.is_jwt_authenticated = lambda request: is_jwt_authentication user = factories.UserFactory() payload = generate_latest_version_payload(user) jwt = generate_jwt_token(payload) mock_request_with_cookie = mock.Mock(COOKIES={}, auth=jwt) expected_decoded_jwt = jwt_decode_handler( jwt) if is_jwt_authentication else None decoded_jwt = authentication.get_decoded_jwt_from_auth( mock_request_with_cookie) self.assertEqual(expected_decoded_jwt, decoded_jwt)
def test_success(self): """ Confirms that the format of the valid response from the token decoder matches the payload """ self.assertDictEqual(jwt_decode_handler(self.jwt), self.payload)
def test_success(self): """ Confirms that the format of the valid response from the token decoder matches the payload """ self.assertDictEqual(jwt_decode_handler(self.jwt), self.payload)
def test_supported_jwt_version_not_specified(self): """ Verifies the JWT is decoded successfully when the JWT_SUPPORTED_VERSION setting is not specified. """ token = generate_jwt_token(self.payload) self.assertDictEqual(jwt_decode_handler(token), self.payload)
def test_supported_jwt_version_not_specified(self): """ Verifies the JWT is decoded successfully when the JWT_SUPPORTED_VERSION setting is not specified. """ token = generate_jwt_token(self.payload) self.assertDictEqual(jwt_decode_handler(token), self.payload)