diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt
index 85b652cd915a8c26bbda6e26b5cdf88ca30d1d9c..0d4e8262138fb0d0efb24b92e4c201b98e57c14d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.ui.submission
 
 import android.Manifest
+import android.content.pm.PackageManager
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
@@ -38,6 +39,7 @@ class SubmissionQRCodeScanFragment : Fragment() {
     private val viewModel: SubmissionViewModel by activityViewModels()
     private var _binding: FragmentSubmissionQrCodeScanBinding? = null
     private val binding: FragmentSubmissionQrCodeScanBinding get() = _binding!!
+    private var showsPermissionDialog = false
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -112,14 +114,6 @@ class SubmissionQRCodeScanFragment : Fragment() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        if (!CameraPermissionHelper.hasCameraPermission(requireActivity())) {
-            if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
-                showCameraPermissionRationaleDialog()
-            } else {
-                requestCameraPermission()
-            }
-        }
-
         binding.submissionQrCodeScanTorch.setOnCheckedChangeListener { _, isChecked ->
             binding.submissionQrCodeScanPreview.setTorch(
                 isChecked
@@ -184,6 +178,25 @@ class SubmissionQRCodeScanFragment : Fragment() {
         DialogHelper.showDialog(invalidScanDialogInstance)
     }
 
+    override fun onRequestPermissionsResult(
+        requestCode: Int,
+        permissions: Array<String>,
+        grantResults: IntArray
+    ) {
+        if (requestCode == REQUEST_CAMERA_PERMISSION_CODE) {
+
+            // permission was denied
+            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED)) {
+                if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
+                    showCameraPermissionRationaleDialog()
+                } else {
+                    // user permanently denied access to the camera
+                    showCameraPermissionDeniedDialog()
+                }
+            }
+        }
+    }
+
     override fun onResume() {
         super.onResume()
         binding.submissionQrCodeScanContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
@@ -191,7 +204,32 @@ class SubmissionQRCodeScanFragment : Fragment() {
         if (CameraPermissionHelper.hasCameraPermission(requireActivity())) {
             binding.submissionQrCodeScanPreview.resume()
             startDecode()
+            return
         }
+
+        // we might already show a rational dialog (e.g. when onRequestPermissionsResult was denied
+        // then do nothing
+        if (showsPermissionDialog) {
+            return
+        }
+
+        requestCameraPermission()
+    }
+
+    private fun showCameraPermissionDeniedDialog() {
+        val permissionDeniedDialog = DialogHelper.DialogInstance(
+            requireActivity(),
+            R.string.submission_qr_code_scan_permission_denied_dialog_headline,
+            R.string.submission_qr_code_scan_permission_denied_dialog_body,
+            R.string.submission_qr_code_scan_permission_denied_dialog_button,
+            cancelable = false,
+            positiveButtonFunction = {
+                showsPermissionDialog = false
+                goBack()
+            }
+        )
+        showsPermissionDialog = true
+        DialogHelper.showDialog(permissionDeniedDialog)
     }
 
     private fun showCameraPermissionRationaleDialog() {
@@ -203,13 +241,16 @@ class SubmissionQRCodeScanFragment : Fragment() {
             R.string.submission_qr_code_scan_permission_rationale_dialog_button_negative,
             false,
             {
+                showsPermissionDialog = false
                 requestCameraPermission()
             },
             {
+                showsPermissionDialog = false
                 goBack()
             }
         )
 
+        showsPermissionDialog = true
         DialogHelper.showDialog(cameraPermissionRationaleDialogInstance)
     }
 
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index 6ad547687b66f07e4a82a1b061c50aba7309cb30..8c950aa76944631b1b2f06a625e1e01c752ddf1c 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -701,6 +701,14 @@
     <!-- XBUT: Dialog(QR Scan permission rationale) - negative button (left) -->
     <string name="submission_qr_code_scan_permission_rationale_dialog_button_negative">Nicht erlauben</string>
 
+    <!-- Permission Denied Dialog -->
+    <!-- XHED: Dialog headline QR Scan permission denied  -->
+    <string name="submission_qr_code_scan_permission_denied_dialog_headline">Kamera Zugriff benötigt</string>
+    <!-- YTXT: Dialog Body text for QR Scan permission denied -->
+    <string name="submission_qr_code_scan_permission_denied_dialog_body">Bitte gehen Sie in die Systemeinstellungen und erlauben Sie der App die Benutzung der Kamera, um den QR-Code zu scannen.</string>
+    <!-- XBUT: Dialog(QR Scan permission denied) - button -->
+    <string name="submission_qr_code_scan_permission_denied_dialog_button">OK</string>
+
     <!-- QR Code Scan Invalid Dialog -->
     <!-- XHED: Dialog headline for invalid QR code  -->
     <string name="submission_qr_code_scan_invalid_dialog_headline">QR-Code nicht korrekt</string>