REFERENCE
On-Session vs Off-Session Payments
How payment sessions differ, why it matters for fraud prevention, and the 3DS authentication requirements. When a payment is made off-session, the customer is not present to confirm — future renewals, late fees, and merchant-initiated charges are all off-session.
A naive off-session attempt without prior setup is significantly less likely to succeed. To combat this, Stripe looks for the first successful on-session transaction with the card, then references it — proving same merchant, same amount, approved, no chargeback.
| Factor | On-Session | Off-Session |
|---|---|---|
| CVV | Requires the physical card; PCI standards forbid vaulting | Not available — customer not present |
| 3DS | Out-of-band authentication between cardholder and issuer | Cannot complete — no browser to redirect |
| Captcha | Stripe may request additional verification | Not possible without user interaction |
| Net Effect | These factors differentiate our payment attempt from fraudulent requests | Without prior on-session success, the charge looks indistinguishable from fraud |
- User goes through checkout on-session. 2. Initial payment is collected. 3. At renewal, Stripe references that original payment. 4. Off-session payment succeeds.
When payment isn't required at checkout (e.g. free trials), we need credentials set up for future off-session use. SetupIntents create a real $0 authorization request sent to the card network. If successful, this on-session authorization can be referenced off-session.
A saved card doesn't guarantee the charge succeeds without interaction. The issuer might require 3DS on the PaymentIntent — a separate decision from whether 3DS was needed to save the card. When Stripe requires 3DS, it transitions the PaymentIntent into requires_action and provides a redirect link. This transition will not happen when off_session=true — instead, the payment fails.
A payment method on file before calling subscriptions-api. The subscription needs to be created and the first invoice charged without further user interaction.
When Stripe requires 3DS on the PaymentIntent, it returns requires_action with a redirect URL. But subscriptions-api is making this call server-side — there's no browser to redirect.
The solution: subscribe first, collect payment with the customer present. Users can initiate subscription changes without a payment method on file. Instead of charging server-side, subscriptions-api returns the PaymentIntent's client_secret to the frontend. Dashboard uses the client secret to confirm via Stripe.js. If 3DS is required, the customer is right there.
| Framework | Description | Relevance |
|---|---|---|
| 3DS Protocol | Created by Visa (c. 2001). The acquirer (Stripe) asks the issuer for a redirect link. The customer authenticates directly with the issuer, usually via OTP. | On-session authentication factor |
| SCA (Strong Customer Authentication) | Requires many online card payments go through another-factor authentication. Provides exemptions for recurring and merchant-initiated transactions. | EU/EEA regulatory requirement |
| RBI e-mandates | Requires customer consent (an e-mandate) prior to saving a credit card. AFA must be used while collecting this consent, hence 3DS in on-session flows. | India regulatory requirement |
Collect the authentication when the customer is in front of you. Everything downstream depends on that first on-session interaction.