Force HTTPS ... please

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $9.00

Guess what? You could deploy this code right now. Sure - we have a lot more to talk about - like subscriptions & discounts - but the system is ready.

Oh, but there's just one thing that you cannot forget to do. And that's to force https to be used on your checkout page.

Right now, there is no little lock icon in my browser - this page is not secure. Of course it's not a problem now because I'm just coding locally.

But on production, different story. Even though you're not handling credit card information, Stripe does submit that token to our server. If that submit happens over a non-https connection, that's a security risk: there could be somebody in the middle reading that token. Regardless of what they might or might not be able to do with that, we need to avoid this.

There are a lot of ways to force HTTPs, but let me show you my favorite in Symfony. In OrderController, right above checkoutAction(), this @Route annotation is what defines the URL to this page. At the end of this, add a new option called schemes set to two curly braces and a set of double-quotes with https inside:

... lines 1 - 11
class OrderController extends BaseController
{
... lines 14 - 27
/**
* @Route("/checkout", name="order_checkout", schemes={"https"})
... line 30
*/
public function checkoutAction(Request $request)
{
... lines 34 - 68
}
}

OK, go back and refresh! Cool! Symfony automatically redirects me to https. Life is good.

No HTTPS in dev Please!

Wait, life is not good. I hate needing to setup SSL certificates on my local machine. I actually have one setup already, but other developers might not. That's a huge pain for them... for no benefit.

Fortunately, there's a trick. Replace https, with %secure_channel%:

... lines 1 - 11
class OrderController extends BaseController
{
... lines 14 - 27
/**
* @Route("/checkout", name="order_checkout", schemes={"%secure_channel%"})
... line 30
*/
public function checkoutAction(Request $request)
{
... lines 34 - 68
}
}

This syntax is referencing a parameter in Symfony, so basically a configuration variable. Open parameters.yml, add a new secure_channel parameter and set it to http:

... lines 1 - 3
parameters:
... lines 5 - 22
# set to https on production
secure_channel: http

And as you know, if you add a key here, also add it to parameters.yml.dist:

... lines 1 - 3
parameters:
... lines 5 - 22
# set to https on production
secure_channel: http

Ok, head back to the homepage: http://localhost:8000 and click to checkout. Hey! We're back in http. When you deploy, change that setting to https and boom, your checkout will be secure.

So there's your little trick for forcing https without being forced to hate your life while coding.

Leave a comment!

This tutorial uses an older version of Symfony of the stripe-php SDK. The majority of the concepts are still valid, though there *are* differences. We've done our best to add notes & comments that describe these changes.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9, <7.4",
        "symfony/symfony": "3.1.*", // v3.1.10
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "~2.0.1", // v2.0.1
        "stof/doctrine-extensions-bundle": "^1.2", // v1.2.2
        "stripe/stripe-php": "^3.15", // v3.23.0
        "doctrine/doctrine-migrations-bundle": "^1.1", // 1.1.1
        "twig/twig": "^1.24.1" // v1.35.2
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.2
        "hautelook/alice-bundle": "^1.3", // v1.3.1
        "doctrine/data-fixtures": "^1.2" // v1.2.1
    }
}