diff --git a/app/controllers/lti.php b/app/controllers/lti.php
index e3fcab7387cc55f9677a706cbc10f6e9b69aba97..070682ef8a12c844a3c2ea6c84297fdbcc6153ac 100644
--- a/app/controllers/lti.php
+++ b/app/controllers/lti.php
@@ -32,11 +32,94 @@ class LtiController extends AuthenticatedController
     {
         $course_id = Request::option('custom_cid', $course_id);
         $course_id = Request::option('custom_course', $course_id);
+        $message_type = Request::option('lti_message_type');
 
-        if ($course_id) {
+        if ($message_type === 'ContentItemSelectionRequest') {
+            $_SESSION['ContentItemSelection'] = [
+                'oauth_consumer_key' => Request::get('oauth_consumer_key'),
+                'content_item_return_url' => Request::get('content_item_return_url'),
+                'document_targets' => Request::get('accept_presentation_document_targets'),
+                'data' => Request::get('data')
+            ];
+            $this->redirect('lti/content_item');
+        } else if ($course_id) {
             $this->redirect('course/enrolment/apply/' . $course_id);
         } else {
             $this->redirect('start');
         }
     }
+
+    /**
+     * Select course for ContentItemSelectionRequest message.
+     */
+    public function content_item_action()
+    {
+        PageLayout::setTitle(_('Veranstaltung verknüpfen'));
+        Navigation::activateItem('/browse/my_courses/content_item');
+
+        $this->document_targets = $_SESSION['ContentItemSelection']['document_targets'];
+        $this->target_labels = [
+            'embed'   => _('in Seite einbetten'),
+            'frame'   => _('gleiches Fenster oder Tab'),
+            'iframe'  => _('IFrame in der Seite'),
+            'window'  => _('neues Fenster oder Tab'),
+            'popup'   => _('Popup-Fenster'),
+            'overlay' => _('Dialog'),
+            'none'    => _('nicht anzeigen')
+        ];
+
+        $sql = "JOIN seminar_user USING(Seminar_id)
+                WHERE user_id = ? AND seminar_user.status IN ('dozent', 'tutor')
+                ORDER BY start_time DESC, Name";
+        $this->courses = Course::findBySQL($sql, [$GLOBALS['user']->id]);
+    }
+
+    /**
+     * Return the selected content item to the LTI consumer.
+     */
+    public function link_content_item_action()
+    {
+        CSRFProtection::verifyUnsafeRequest();
+        $course_id = Request::option('course_id');
+        $target = Request::option('target');
+        $course = Course::find($course_id);
+
+        $consumer_key = $_SESSION['ContentItemSelection']['oauth_consumer_key'];
+        $return_url = $_SESSION['ContentItemSelection']['content_item_return_url'];
+        $data = $_SESSION['ContentItemSelection']['data'];
+        unset($_SESSION['ContentItemSelection']);
+
+        $consumer_config = $GLOBALS['STUDIP_AUTH_CONFIG_LTI']['consumer_keys'][$consumer_key];
+        $consumer_secret = $consumer_config['consumer_secret'];
+        $signature_method = $consumer_config['signature_method'] ?? 'sha1';
+
+        $content_items = [
+            '@context' => 'http://purl.imsglobal.org/ctx/lti/v1/ContentItem',
+            '@graph' => []
+        ];
+
+        if (Request::submitted('link')) {
+            $content_items['@graph'][] = [
+                '@type' => 'LtiLinkItem',
+                'mediaType' => 'application/vnd.ims.lti.v1.ltilink',
+                'title' => $course->name,
+                'text' => $course->beschreibung,
+                'placementAdvice' => ['presentationDocumentTarget' => $target],
+                'custom' => ['course' => $course_id]
+            ];
+        }
+
+        // set up ContentItemSelection
+        $lti_link = new LtiLink($return_url, $consumer_key, $consumer_secret, $signature_method);
+        $lti_link->addLaunchParameters([
+            'lti_message_type' => 'ContentItemSelection',
+            'content_items' => json_encode($content_items),
+            'data' => $data
+        ]);
+
+        $this->launch_url = $lti_link->getLaunchURL();
+        $this->launch_data = $lti_link->getBasicLaunchData();
+        $this->signature = $lti_link->getLaunchSignature($this->launch_data);
+        $this->render_template('course/lti/iframe');
+    }
 }
diff --git a/app/views/lti/content_item.php b/app/views/lti/content_item.php
new file mode 100644
index 0000000000000000000000000000000000000000..d686052ce0618b73c18d2ae20ad5a7cd85f2d7ed
--- /dev/null
+++ b/app/views/lti/content_item.php
@@ -0,0 +1,38 @@
+<form class="default" action="<?= $controller->link_for('lti/link_content_item') ?>" method="POST">
+    <?= CSRFProtection::tokenTag() ?>
+
+    <fieldset>
+        <legend>
+            <?= _('Veranstaltung auswählen') ?>
+        </legend>
+
+        <label>
+            <?= _('Veranstaltung') ?>
+
+            <select name="course_id" class="nested-select">
+                <? foreach ($courses as $course): ?>
+                    <option value="<?= $course->id ?>">
+                        <?= htmlReady($course->getFullname('number-name-semester')) ?>
+                    </option>
+                <? endforeach ?>
+            </select>
+        </label>
+
+        <label>
+            <?= _('Art der Anzeige') ?>
+
+            <select name="target">
+                <? foreach (explode(',', $document_targets) as $target): ?>
+                    <option value="<?= htmlReady($target) ?>" <?= $target === 'window' ? 'selected' : '' ?>>
+                        <?= htmlReady($target_labels[$target] ?? $target) ?>
+                    </option>
+                <? endforeach ?>
+            </select>
+        </label>
+    </fieldset>
+
+    <footer>
+        <?= Studip\Button::createAccept(_('Verknüpfen'), 'link') ?>
+        <?= Studip\Button::createCancel(_('Abbrechen'), 'abort') ?>
+    </footer>
+</form>
diff --git a/lib/navigation/BrowseNavigation.php b/lib/navigation/BrowseNavigation.php
index 82b3ac6c282e6b0645d4cd14913667d525b2841c..69173041962269c1424c7537caab3d2b489be2c5 100644
--- a/lib/navigation/BrowseNavigation.php
+++ b/lib/navigation/BrowseNavigation.php
@@ -78,6 +78,10 @@ class BrowseNavigation extends Navigation
                 $navigation->addSubNavigation('archive', new Navigation(_('Archivierte Veranstaltungen'), 'dispatch.php/my_courses/archive'));
             }
 
+            if (isset($_SESSION['ContentItemSelection'])) {
+                $navigation->addSubNavigation('content_item', new Navigation(_('Veranstaltung verknüpfen'), 'dispatch.php/lti/content_item'));
+            }
+
             $this->addSubNavigation('my_courses', $navigation);
 
             if (Config::get()->MY_COURSES_ENABLE_STUDYGROUPS && !$GLOBALS['perm']->have_perm('admin')) {