diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py
index 63df22940862c0eb1b013a26fa516c20f0f55a7d..984ae85097cf6f5a96ae91ef20143bb100d8c843 100644
--- a/common/lib/xmodule/xmodule/seq_module.py
+++ b/common/lib/xmodule/xmodule/seq_module.py
@@ -19,12 +19,14 @@ from pkg_resources import resource_string
 from pytz import UTC
 from six import text_type
 from web_fragments.fragment import Fragment
+
 from xblock.completable import XBlockCompletionMode
 from xblock.core import XBlock
 from xblock.exceptions import NoSuchServiceError
 from xblock.fields import Boolean, Integer, List, Scope, String
 
 from openedx.core.djangoapps.waffle_utils import WaffleFlag
+from openedx.core.lib.graph_traversals import traverse_pre_order
 
 from .exceptions import NotFoundError
 from .fields import Date
@@ -189,6 +191,7 @@ class ProctoringFields(object):
 @XBlock.needs('user')
 @XBlock.needs('bookmarks')
 @XBlock.needs('i18n')
+@XBlock.wants('content_type_gating')
 class SequenceModule(SequenceFields, ProctoringFields, XModule):
     """
     Layout module which lays out content in a temporal sequence
@@ -279,6 +282,79 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
             datetime.now(UTC) < date
         )
 
+    def gate_sequence_if_it_is_a_timed_exam_and_contains_content_type_gated_problems(self):
+        """
+        Problem:
+        Content type gating for FBE (Feature Based Enrollments) previously only gated individual blocks.
+        This was an issue because audit learners could start a timed exam
+        and then be unable to complete it because the graded content would be gated.
+        Even if they later upgraded, they could still be unable to complete the exam
+        because the timer could have expired.
+
+        Solution:
+        Gate the entire sequence when we think the above problem can occur.
+
+        If:
+        1. This sequence is a timed exam
+        2. And this sequence contains problems which this user cannot load due to content type gating
+        Then:
+        We will gate access to the entire sequence.
+        Otherwise, learners would have the ability to start their timer for an exam,
+        but then not have the ability to complete it.
+
+        We are displaying the gating fragment within the sequence, as is done for gating for prereqs,
+        rather than content type gating the entire sequence because that would remove the next/previous navigation.
+
+        When gated_sequence_fragment is not set to None, the sequence will be gated.
+
+        This functionality still needs to be replicated in the frontend-app-learning courseware MFE
+        The ticket to track this is https://openedx.atlassian.net/browse/REV-1220
+        Note that this will break compatability with using sequences outside of edx-platform
+        but we are ok with this for now
+        """
+        if not self.is_time_limited:
+            self.gated_sequence_fragment = None
+            return
+
+        try:
+            user = User.objects.get(id=self.runtime.user_id)
+            course_id = self.runtime.course_id
+            content_type_gating_service = self.runtime.service(self, 'content_type_gating')
+            if not (content_type_gating_service and
+                    content_type_gating_service.enabled_for_enrollment(user=user, course_key=course_id)):
+                self.gated_sequence_fragment = None
+                return
+
+            def leaf_filter(block):
+                # This function is used to check if this is a leaf block
+                # Blocks with children are not currently gated by content type gating
+                # Other than the outer function here
+                return (
+                    block.location.block_type not in ('chapter', 'sequential', 'vertical') and
+                    not block.has_children
+                )
+
+            def get_children(parent):
+                # This function is used to get the children of a block in the traversal below
+                if parent.has_children:
+                    return parent.get_children()
+                else:
+                    return []
+
+            # If any block inside a timed exam has been gated by content type gating
+            # then gate the entire sequence.
+            # In order to avoid scope creep, we are not handling other potential causes
+            # of access failures as part of this work.
+            for block in traverse_pre_order(self, get_children, leaf_filter):
+                gate_fragment = content_type_gating_service.content_type_gate_for_block(user, block, course_id)
+                if gate_fragment is not None:
+                    self.gated_sequence_fragment = gate_fragment
+                    return
+                else:
+                    self.gated_sequence_fragment = None
+        except User.DoesNotExist:
+            self.gated_sequence_fragment = None
+
     def student_view(self, context):
         _ = self.runtime.service(self, "i18n").ugettext
         context = context or {}
@@ -288,30 +364,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
         prereq_meta_info = {}
 
         if TIMED_EXAM_GATING_WAFFLE_FLAG.is_enabled():
-            # Content type gating for FBE previously only gated individual blocks
-            # This was an issue because audit learners could start a timed exam and then be unable to complete the exam
-            # even if they later upgrade because the timer would have expired.
-            # For this reason we check if content gating is enabled for the user
-            # and gate the entire sequence in that case
-            # This functionality still needs to be replicated in the frontend-app-learning courseware MFE
-            # The ticket to track this is https://openedx.atlassian.net/browse/REV-1220
-            # Note that this will break compatability with using sequences outside of edx-platform
-            # but we are ok with this for now
-            if self.is_time_limited:
-                try:
-                    user = User.objects.get(id=self.runtime.user_id)
-                    # importing here to avoid a circular import
-                    from openedx.features.content_type_gating.models import ContentTypeGatingConfig
-                    from openedx.features.content_type_gating.helpers import CONTENT_GATING_PARTITION_ID
-                    if ContentTypeGatingConfig.enabled_for_enrollment(user=user, course_key=self.runtime.course_id):
-                        # Get the content type gating locked content fragment to render for this sequence
-                        partition = self.descriptor._get_user_partition(CONTENT_GATING_PARTITION_ID)  # pylint: disable=protected-access
-                        user_group = partition.scheme.get_group_for_user(self.runtime.course_id, user, partition)
-                        self.gated_sequence_fragment = partition.access_denied_fragment(
-                            self.descriptor, user, user_group, []
-                        )
-                except User.DoesNotExist:
-                    pass
+            self.gate_sequence_if_it_is_a_timed_exam_and_contains_content_type_gated_problems()
 
         if self._required_prereq():
             if self.runtime.user_is_staff:
diff --git a/common/lib/xmodule/xmodule/tests/test_sequence.py b/common/lib/xmodule/xmodule/tests/test_sequence.py
index 03919a5d4d69277aba0439936ca5c05f8050d11a..318d78815794fe4c4327945d62b1959162355778 100644
--- a/common/lib/xmodule/xmodule/tests/test_sequence.py
+++ b/common/lib/xmodule/xmodule/tests/test_sequence.py
@@ -14,6 +14,7 @@ from django.utils.timezone import now
 from freezegun import freeze_time
 from mock import Mock, patch
 from six.moves import range
+from web_fragments.fragment import Fragment
 
 from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
 from student.tests.factories import UserFactory
@@ -76,10 +77,12 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
         for _ in range(3):
             xml.VerticalFactory.build(parent=sequence_3_1)
 
-        xml.SequenceFactory.build(
+        sequence_5_1 = xml.SequenceFactory.build(
             parent=chapter_5,
             is_time_limited=str(True)
         )
+        vertical_5_1 = xml.VerticalFactory.build(parent=sequence_5_1)
+        xml.ProblemFactory.build(parent=vertical_5_1)
 
         return course
 
@@ -181,6 +184,65 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
             )
             mocked_user.assert_called_once()
 
+    @override_waffle_flag(TIMED_EXAM_GATING_WAFFLE_FLAG, active=True)
+    @patch('xmodule.seq_module.User.objects.get', return_value=UserFactory.build())
+    def test_that_timed_sequence_gating_respects_access_configurations(self, mocked_user):  # pylint: disable=unused-argument
+        """
+        Verify that if a time limited sequence contains content type gated problems, we gate the sequence
+        Verify that if a time limited sequence does not contain content type gated problems, we do not gate the sequence
+        """
+        # the one problem in this sequence needs to have graded set to true in order to test content type gating
+        self.sequence_5_1.get_children()[0].get_children()[0].graded = True
+        gated_fragment = Fragment('i_am_gated')
+
+        # When a time limited sequence contains content type gated problems, the sequence itself is gated
+        self.sequence_5_1.runtime._services['content_type_gating'] = Mock(return_value=Mock(  # pylint: disable=protected-access
+            enabled_for_enrollment=Mock(return_value=True),
+            content_type_gate_for_block=Mock(return_value=gated_fragment)
+        ))
+        view = self._get_rendered_view(
+            self.sequence_5_1,
+            extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'),
+            view=STUDENT_VIEW
+        )
+        self.assertIn('i_am_gated', view)
+        # check a few elements to ensure the correct page was loaded
+        self.assertIn("seq_module.html", view)
+        self.assertIn('NextSequential', view)
+        self.assertIn('PrevSequential', view)
+
+        # When enabled_for_enrollment is false, the sequence itself is not gated
+        self.sequence_5_1.runtime._services['content_type_gating'] = Mock(return_value=Mock(  # pylint: disable=protected-access
+            enabled_for_enrollment=Mock(return_value=False),
+            content_type_gate_for_block=Mock(return_value=gated_fragment)
+        ))
+        view = self._get_rendered_view(
+            self.sequence_5_1,
+            extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'),
+            view=STUDENT_VIEW
+        )
+        self.assertNotIn('i_am_gated', view)
+        # check a few elements to ensure the correct page was loaded
+        self.assertIn("seq_module.html", view)
+        self.assertIn('NextSequential', view)
+        self.assertIn('PrevSequential', view)
+
+        # When content_type_gate_for_block returns None, the sequence itself is not gated
+        self.sequence_5_1.runtime._services['content_type_gating'] = Mock(return_value=Mock(  # pylint: disable=protected-access
+            enabled_for_enrollment=Mock(return_value=True),
+            content_type_gate_for_block=Mock(return_value=None)
+        ))
+        view = self._get_rendered_view(
+            self.sequence_5_1,
+            extra_context=dict(next_url='NextSequential', prev_url='PrevSequential'),
+            view=STUDENT_VIEW
+        )
+        self.assertNotIn('i_am_gated', view)
+        # check a few elements to ensure the correct page was loaded
+        self.assertIn("seq_module.html", view)
+        self.assertIn('NextSequential', view)
+        self.assertIn('PrevSequential', view)
+
     @ddt.unpack
     @ddt.data(
         {'view': STUDENT_VIEW},
diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py
index 56bdccb55d3941d986b63313d1681861d44bce95..39bd0f47eff25da9b377531192181fe58b58956a 100644
--- a/lms/djangoapps/courseware/module_render.py
+++ b/lms/djangoapps/courseware/module_render.py
@@ -87,6 +87,7 @@ from openedx.core.lib.xblock_utils import request_token as xblock_request_token
 from openedx.core.lib.xblock_utils import wrap_xblock
 from openedx.features.course_duration_limits.access import course_expiration_wrapper
 from openedx.features.discounts.utils import offer_banner_wrapper
+from openedx.features.content_type_gating.services import ContentTypeGatingService
 from student.models import anonymous_id_for_user, user_by_anonymous_id
 from student.roles import CourseBetaTesterRole
 from track import contexts
@@ -821,6 +822,7 @@ def get_module_system_for_user(
             'gating': GatingService(),
             'grade_utils': GradesUtilService(course_id=course_id),
             'user_state': UserStateService(),
+            'content_type_gating': ContentTypeGatingService(),
         },
         get_user_role=lambda: get_user_role(user, course_id),
         descriptor_runtime=descriptor._runtime,  # pylint: disable=protected-access
diff --git a/openedx/features/content_type_gating/services.py b/openedx/features/content_type_gating/services.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1c8f6622b5ca1461ceb0832ebf29363b3ad5e85
--- /dev/null
+++ b/openedx/features/content_type_gating/services.py
@@ -0,0 +1,32 @@
+"""
+Content Type Gating service.
+"""
+
+from lms.djangoapps.courseware.access import has_access
+from openedx.features.content_type_gating.models import ContentTypeGatingConfig
+
+
+class ContentTypeGatingService(object):
+    """
+    Content Type Gating uses Block Transformers to gate sections of the course outline
+    and field overrides to gate course content.
+    This service was created as a helper class for handling timed exams that contain content type gated problems.
+    """
+    def enabled_for_enrollment(self, **kwargs):
+        """
+        Returns whether content type gating is enabled for a given user/course pair
+        """
+        return ContentTypeGatingConfig.enabled_for_enrollment(**kwargs)
+
+    def content_type_gate_for_block(self, user, block, course_id):
+        """
+        Returns a Fragment of the content type gate (if any) that would appear for a given block
+        """
+        problem_eligible_for_content_gating = (getattr(block, 'graded', False) and
+                                               block.has_score and
+                                               getattr(block, 'weight', 0) != 0)
+        if problem_eligible_for_content_gating:
+            access = has_access(user, 'load', block, course_id)
+            if (not access and access.error_code == 'incorrect_user_group'):
+                return access.user_fragment
+            return None
diff --git a/openedx/features/content_type_gating/tests/test_access.py b/openedx/features/content_type_gating/tests/test_access.py
index 10b59e7f9a5dad860101b7175d05fe4c43d1f059..8d4fde3986653651068c026719487e7e848ed685 100644
--- a/openedx/features/content_type_gating/tests/test_access.py
+++ b/openedx/features/content_type_gating/tests/test_access.py
@@ -45,6 +45,7 @@ from openedx.core.lib.url_utils import quote_slashes
 from openedx.features.content_type_gating.helpers import CONTENT_GATING_PARTITION_ID, CONTENT_TYPE_GATE_GROUP_IDS
 from openedx.features.content_type_gating.models import ContentTypeGatingConfig
 from openedx.features.content_type_gating.partitions import ContentTypeGatingPartition
+from openedx.features.content_type_gating.services import ContentTypeGatingService
 from student.models import CourseEnrollment, FBEEnrollmentExclusion
 from student.roles import CourseInstructorRole
 from student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory
@@ -1085,3 +1086,85 @@ class TestMessageDeduplication(ModuleStoreTestCase):
             is_gated=True,
             request_factory=self.request_factory,
         )
+
+
+@override_settings(FIELD_OVERRIDE_PROVIDERS=(
+    'openedx.features.content_type_gating.field_override.ContentTypeGatingFieldOverride',
+))
+class TestContentTypeGatingService(ModuleStoreTestCase):
+    """
+    The ContentTypeGatingService was originally created as a helper class for timed exams
+    to check whether a sequence contains content type gated blocks
+    The content_type_gate_for_block can be used to return the content type gate for a given block
+    """
+
+    def setUp(self):
+        super(TestContentTypeGatingService, self).setUp()
+
+        self.user = UserFactory.create()
+        self.request_factory = RequestFactory()
+        ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
+
+    def _create_course(self):
+        course = CourseFactory.create(run='test', display_name='test')
+        CourseModeFactory.create(course_id=course.id, mode_slug='audit')
+        CourseModeFactory.create(course_id=course.id, mode_slug='verified')
+        blocks_dict = {}
+        with self.store.bulk_operations(course.id):
+            blocks_dict['chapter'] = ItemFactory.create(
+                parent=course,
+                category='chapter',
+                display_name='Week 1'
+            )
+            blocks_dict['sequential'] = ItemFactory.create(
+                parent=blocks_dict['chapter'],
+                category='sequential',
+                display_name='Lesson 1'
+            )
+            blocks_dict['vertical'] = ItemFactory.create(
+                parent=blocks_dict['sequential'],
+                category='vertical',
+                display_name='Lesson 1 Vertical - Unit 1'
+            )
+        return {
+            'course': course,
+            'blocks': blocks_dict,
+        }
+
+    def test_content_type_gate_for_block(self):
+        ''' Verify that the method returns a content type gate when appropriate '''
+        course = self._create_course()
+        blocks_dict = course['blocks']
+        CourseEnrollmentFactory.create(
+            user=self.user,
+            course_id=course['course'].id,
+            mode='audit'
+        )
+        blocks_dict['graded_1'] = ItemFactory.create(
+            parent=blocks_dict['vertical'],
+            category='problem',
+            graded=True,
+            metadata=METADATA,
+        )
+        blocks_dict['not_graded_1'] = ItemFactory.create(
+            parent=blocks_dict['vertical'],
+            category='problem',
+            graded=False,
+            metadata=METADATA,
+        )
+
+        # The method returns a content type gate for blocks that should be gated
+        self.assertIn(
+            'content-paywall',
+            ContentTypeGatingService().content_type_gate_for_block(
+                self.user, blocks_dict['graded_1'], course['course'].id
+            ).content
+        )
+
+        # The method returns None for blocks that should not be gated
+        self.assertEquals(
+            None,
+            ContentTypeGatingService().content_type_gate_for_block(
+                self.user, blocks_dict['not_graded_1'], course['course'].id
+            )
+        )