diff --git a/src/Plugin/Commerce/CheckoutPane/StripeReview.php b/src/Plugin/Commerce/CheckoutPane/StripeReview.php
index 0d22dde..36a7480 100644
--- a/src/Plugin/Commerce/CheckoutPane/StripeReview.php
+++ b/src/Plugin/Commerce/CheckoutPane/StripeReview.php
@@ -43,6 +43,7 @@ class StripeReview extends CheckoutPaneBase {
     return [
       'button_id' => 'edit-actions-next',
       'auto_submit_review_form' => 0,
+      'setup_future_usage' => '',
     ] + parent::defaultConfiguration();
   }
 
@@ -58,7 +59,16 @@ class StripeReview extends CheckoutPaneBase {
     else {
       $summary .= $this->t('Auto submit: On');
     }
-
+    switch($this->configuration['setup_future_usage']) {
+      case 'on_session':
+        $summary .= $this->t('Setup future usage: On session');
+        break;
+      case 'off_session':
+        $summary .= $this->t('Setup future usage: Off session');
+        break;
+      case '':
+        $summary .= $this->t('Setup future usage: None');
+    }
     return $summary;
   }
 
@@ -81,7 +91,17 @@ class StripeReview extends CheckoutPaneBase {
       '#description' => $this->t('When this is checked, the form the Stripe Review pane is displayed in will automatically submit on load. This starts the SCA process without user intervention.'),
       '#default_value' => $this->configuration['auto_submit_review_form'],
     ];
-
+    $form['setup_future_usage'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Setup future usage'),
+      '#options' => [
+        'on_session' => 'On session',
+        'off_session' => 'Off session',
+      ],
+      '#empty_value' => '',
+      '#default_value' => $this->getConfiguration()['setup_future_usage'],
+      '#description' => 'The intended future usage of the provided payment method. See <a href="https://stripe.com/docs/payments/payment-intents#future-usage">Stripe documentation</a>.',
+    ];
     return $form;
   }
 
@@ -95,6 +115,7 @@ class StripeReview extends CheckoutPaneBase {
       $values = $form_state->getValue($form['#parents']);
       $this->configuration['button_id'] = $values['button_id'];
       $this->configuration['auto_submit_review_form'] = $values['auto_submit_review_form'];
+      $this->configuration['setup_future_usage'] = $values['setup_future_usage'];
     }
   }
 
@@ -135,8 +156,13 @@ class StripeReview extends CheckoutPaneBase {
     else {
       $payment_process_pane = $this->checkoutFlow->getPane('payment_process');
       assert($payment_process_pane instanceof CheckoutPaneInterface);
-      $capture = $payment_process_pane->getConfiguration()['capture'];
-      $intent = $stripe_plugin->createPaymentIntent($this->order, $capture);
+      $intent_params = [
+        'capture_method' => $payment_process_pane->getConfiguration()['capture'] ? 'automatic' : 'manual',
+      ];
+      if (!empty($this->getConfiguration()['setup_future_usage'])) {
+        $intent_params['setup_future_usage'] = $this->getConfiguration()['setup_future_usage'];
+      }
+      $intent = $stripe_plugin->createPaymentIntent($this->order, $intent_params);
     }
     if ($intent->status === PaymentIntent::STATUS_REQUIRES_PAYMENT_METHOD) {
       $payment_method = $this->order->get('payment_method')->entity;
diff --git a/src/Plugin/Commerce/PaymentGateway/Stripe.php b/src/Plugin/Commerce/PaymentGateway/Stripe.php
index fef51a6..b303ecc 100755
--- a/src/Plugin/Commerce/PaymentGateway/Stripe.php
+++ b/src/Plugin/Commerce/PaymentGateway/Stripe.php
@@ -205,19 +205,34 @@ class Stripe extends OnsitePaymentGatewayBase implements StripeInterface {
     $order = $payment->getOrder();
     assert($order instanceof OrderInterface);
     $intent_id = $order->getData('stripe_intent');
-    if(empty($intent_id)){
-      $intent = $this->createPaymentIntent($order);
+    if (empty($intent_id)) {
+      // We need to ensure we send the off_session param.
+      if ($order->bundle() === 'recurring') {
+        $intent = $this->createPaymentIntent($order, [
+          // By default assume customer is not available for SCA.
+          'confirm' => TRUE,
+          'off_session' => TRUE,
+          'capture_method' => $capture ? 'automatic' : 'manual',
+        ]);
+      }
+      else {
+        $intent = $this->createPaymentIntent($order);
+      }
       $intent_id = $intent['id'];
     }
     try {
       $intent = \Stripe\PaymentIntent::retrieve($intent_id);
+
       if ($intent->status === PaymentIntent::STATUS_REQUIRES_CONFIRMATION) {
         $intent = $intent->confirm();
       }
       if ($intent->status === PaymentIntent::STATUS_REQUIRES_ACTION) {
         throw new SoftDeclineException('The payment intent requires action by the customer for authentication');
       }
-      if (!in_array($intent->status, [PaymentIntent::STATUS_REQUIRES_CAPTURE, PaymentIntent::STATUS_SUCCEEDED], TRUE)) {
+      if (!in_array($intent->status, [
+        PaymentIntent::STATUS_REQUIRES_CAPTURE,
+        PaymentIntent::STATUS_SUCCEEDED
+      ], TRUE)) {
         $order->set('payment_method', NULL);
         $this->deletePaymentMethod($payment_method);
         if ($intent->status === PaymentIntent::STATUS_CANCELED) {
@@ -256,8 +271,7 @@ class Stripe extends OnsitePaymentGatewayBase implements StripeInterface {
 
       $order->unsetData('stripe_intent');
       $order->save();
-    }
-    catch (\Stripe\Exception\ApiErrorException $e) {
+    } catch (\Stripe\Exception\ApiErrorException $e) {
       ErrorHelper::handleException($e);
     }
   }
@@ -423,32 +437,25 @@ class Stripe extends OnsitePaymentGatewayBase implements StripeInterface {
   /**
    * {@inheritdoc}
    */
-  public function createPaymentIntent(OrderInterface $order, $capture = TRUE) {
-    /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */
-    $payment_method = $order->get('payment_method')->entity;
-
-    $payment_method_remote_id = $payment_method->getRemoteId();
-    $customer_remote_id = $this->getRemoteCustomerId($order->getCustomer());
-
-    $amount = $this->toMinorUnits($order->getTotalPrice());
-    $order_id = $order->id();
-    $capture_method = $capture ? 'automatic' : 'manual';
-    $intent_array = [
-      'amount' => $amount,
+  public function createPaymentIntent(OrderInterface $order, array $intent_params = []) {
+    $default_intent_params = [
+      'amount' => $this->toMinorUnits($order->getTotalPrice()),
       'currency' => strtolower($order->getTotalPrice()->getCurrencyCode()),
       'payment_method_types' => ['card'],
       'metadata' => [
-        'order_id' => $order_id,
+        'order_id' => $order->id(),
         'store_id' => $order->getStoreId(),
       ],
-      'payment_method' => $payment_method_remote_id,
-      'capture_method' => $capture_method,
+      'payment_method' => $order->get('payment_method')->entity->getRemoteId(),
+      'capture_method' => 'automatic',
     ];
+    $customer_remote_id = $this->getRemoteCustomerId($order->getCustomer());
     if (!empty($customer_remote_id)) {
-      $intent_array['customer'] = $customer_remote_id;
+      $default_intent_params['customer'] = $customer_remote_id;
     }
+    $intent_params = array_replace_recursive($default_intent_params, $intent_params);
     try {
-      $intent = \Stripe\PaymentIntent::create($intent_array);
+      $intent = \Stripe\PaymentIntent::create($intent_params);
       $order->setData('stripe_intent', $intent->id)->save();
     }
     catch (\Stripe\Exception\ApiErrorException $e) {
diff --git a/src/Plugin/Commerce/PaymentGateway/StripeInterface.php b/src/Plugin/Commerce/PaymentGateway/StripeInterface.php
index d342fe3..3e778e8 100755
--- a/src/Plugin/Commerce/PaymentGateway/StripeInterface.php
+++ b/src/Plugin/Commerce/PaymentGateway/StripeInterface.php
@@ -25,12 +25,12 @@ interface StripeInterface extends OnsitePaymentGatewayInterface, SupportsAuthori
    *
    * @param \Drupal\commerce_order\Entity\OrderInterface $order
    *   The order.
-   * @param bool $capture
-   *   Whether the created payment intent capture is automatic or manual.
+   * @param array $intent_params
+   *   (optional) Parameters to create the intent with.
    *
    * @return \Stripe\PaymentIntent
    *   The payment intent.
    */
-  public function createPaymentIntent(OrderInterface $order, $capture = TRUE);
+  public function createPaymentIntent(OrderInterface $order, array $intent_params = []);
 
 }
diff --git a/tests/src/Kernel/CreatePaymentTest.php b/tests/src/Kernel/CreatePaymentTest.php
index 62e0624..3e52fab 100644
--- a/tests/src/Kernel/CreatePaymentTest.php
+++ b/tests/src/Kernel/CreatePaymentTest.php
@@ -70,7 +70,7 @@ class CreatePaymentTest extends StripeIntegrationTestBase {
       'order_id' => $order->id(),
     ]);
 
-    $intent = $plugin->createPaymentIntent($order, $capture);
+    $intent = $plugin->createPaymentIntent($order, ['capture_method' => $capture ? 'automatic' : 'manual']);
     // Programmatically confirm the intent, the customer would be performing
     // this action on the client side.
     $intent->confirm();
diff --git a/tests/src/Kernel/PaymentIntentTest.php b/tests/src/Kernel/PaymentIntentTest.php
index 2968523..7751df3 100644
--- a/tests/src/Kernel/PaymentIntentTest.php
+++ b/tests/src/Kernel/PaymentIntentTest.php
@@ -53,7 +53,7 @@ class PaymentIntentTest extends StripeIntegrationTestBase {
     $order->setData('stripe_intent', Argument::containingString('pi_'))->willReturn($order->reveal());
     $order->save()->willReturn(NULL);
 
-    $intent = $plugin->createPaymentIntent($order->reveal(), $capture);
+    $intent = $plugin->createPaymentIntent($order->reveal(), ['capture_method' => $capture ? 'automatic' : 'manual']);
     $this->assertEquals($capture ? 'automatic' : 'manual', $intent->capture_method);
     $this->assertEquals($initial_status, $intent->status);
     $this->assertEquals($intent->currency, 'usd');
