KAHIBARO
Discord Login Register

15.2 HTTPS and TLS

Why HTTPS Matters for Backend Developers

Most modern websites use HTTPS by default. As a backend developer you must understand what it actually does, why it is required, and how it affects your API design and deployment.

HTTP is plain text. Anyone who can watch the traffic between client and server can read and modify everything. HTTPS is simply HTTP over TLS, which adds encryption and security on top of HTTP.

Backends that handle logins, tokens, payments, or personal data must use HTTPS in production. Browsers and mobile apps also expect HTTPS for modern features like Service Workers and HTTP/2.

Always require HTTPS in production for any application that deals with authentication or user data.

In this chapter you will learn the basics of TLS and certificates, what security guarantees HTTPS provides, and what you must do in your backend code and infrastructure to use HTTPS correctly.


What HTTPS Actually Protects

HTTPS gives three main security properties:

PropertyWhat it meansExample
ConfidentialityAttackers cannot read the trafficPasswords or tokens stay private
IntegrityTraffic cannot be silently modified in transitJSON responses cannot be altered
AuthenticationClient can verify the server it talks toapi.example.com is really yours

Confidentiality

With HTTP, a network observer can see:

With HTTPS:

Example:

Integrity

Without HTTPS, an attacker can:

With HTTPS, if any byte is changed in transit, the TLS layer detects it and the connection is aborted.

Example:

json
  {"user_id": 123, "role": "user"}

Authentication (of the server)

HTTPS uses certificates to prove that the client is indeed talking to api.example.com, not to an impostor.

This prevents:

Note that this authenticates the server to the client, not necessarily the client to the server. For client authentication you use sessions, tokens, or mutual TLS, which is out of scope here.


TLS Basics: The Protocol Under HTTPS

TLS (Transport Layer Security) is the protocol that provides the security for HTTPS.

You do not implement TLS in application code yourself. Your web server or reverse proxy (for example Nginx, Caddy, Apache, Traefik, a cloud load balancer) handles TLS.

However, you need to understand the pieces so you can configure it correctly.

TLS Versions

Main versions you will see:

VersionStatus
SSL 2/3Obsolete and insecure, never use
TLS 1.0Deprecated
TLS 1.1Deprecated
TLS 1.2Widely used, still considered secure
TLS 1.3Modern, faster, preferred

Only enable TLS 1.2 and 1.3 for public internet services. Disable SSL and older TLS versions.

In practice, most recommended server configurations today:

Very High-Level TLS Handshake Overview

A full handshake is complex, but conceptually:

  1. Client hello
    The client says: I want to talk using TLS, here are the cipher suites and TLS versions I support, and the server name (SNI).
  2. Server hello
    The server picks the protocol version and cipher suite and sends:
    • Its certificate (containing its public key and domain).
    • Some cryptographic parameters.
  3. Key exchange
    Client and server use asymmetric cryptography to establish a shared secret. With modern TLS, this is usually ephemeral Diffie‑Hellman.
  4. Session keys derived
    Both sides derive symmetric keys from the shared secret.
  5. Secure channel established
    From then on, all data is encrypted and authenticated with symmetric cryptography.

Mutual authentication (where the client also presents a certificate) is possible but rare for public APIs. Typically only the server is authenticated.


Certificates and Certificate Authorities

TLS uses public key cryptography. Each server has:

What Is a TLS Certificate?

A certificate binds:

In simplified form, a certificate says:

"The owner of api.example.com controls this public key, and I, the CA, vouch for it."

The browser or HTTP client verifies this statement using the CA's root certificate already built into the operating system or browser.

Fields you will commonly see in a certificate

Certificate Authorities (CAs)

A CA is a trusted third party that:

  1. Verifies that you control the domain (for example by DNS record or HTTP challenge).
  2. Issues a signed certificate.
  3. The CA's root certificate is trusted by browsers and operating systems.

Popular CAs include:

Do not create self-signed certificates for public production sites. Browsers will warn users, and security is weakened. Use a CA-issued certificate.

Self-signed certificates are fine for internal testing or secure internal systems where you control the trust store.


How the Browser Verifies HTTPS

When a browser connects to https://api.example.com:

  1. It receives the server's certificate.
  2. It checks:
    • Is the certificate issued by a CA that is in my trusted list?
    • Is the certificate currently valid (date range)?
    • Does the certificate's domain match the requested domain (api.example.com)?
    • Is the certificate signature valid?
  3. If any of these checks fail, the browser displays a warning such as "Your connection is not private".

As a backend developer, your job is to ensure:

How HTTPS Affects Your Backend Code

Most of your HTTPS work happens in server and infrastructure configuration, not inside your Python / application code. However, there are some important points that affect your backend logic.

Absolute vs Relative URLs

When generating URLs in responses or templates, avoid hardcoding http://. Use:

If your app runs behind a reverse proxy that terminates TLS, your backend might only see plain HTTP on the internal network. For example:

In that case, the backend must rely on headers like X-Forwarded-Proto to know that the original request was HTTPS. Frameworks often have configuration flags to handle this correctly.

Secure Cookies

Cookies that carry authentication or sensitive data must be configured to be used only over HTTPS.

Use these flags:

Example of a secure cookie in a response header:

http
Set-Cookie: session_id=abc123;
  Path=/;
  HttpOnly;
  Secure;
  SameSite=Lax

Never send authentication cookies without the Secure and HttpOnly flags in production.

HTTP Strict Transport Security (HSTS)

HSTS tells the browser:

"For this domain, always use HTTPS for the next N seconds, even if the user types http:// or clicks an old http:// link."

You set this with the Strict-Transport-Security header, for example:

http
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Meaning:

Benefits:

Use HSTS only when:

Common HTTPS Deployment Patterns

You will often not terminate TLS inside your application server. Instead, you use a reverse proxy or load balancer.

Pattern 1: TLS Termination at Reverse Proxy

Typical stack:

Flow:

  1. Client connects to https://api.example.com.
  2. Nginx handles the TLS handshake and decrypts the traffic.
  3. Nginx forwards the HTTP request to http://127.0.0.1:8000.
  4. Application handles the request and sends HTTP response back to Nginx.
  5. Nginx encrypts it and sends to the client as HTTPS.

Advantages:

Pattern 2: TLS Termination at a Cloud Load Balancer

If you use a cloud provider (AWS, GCP, Azure), you might use:

Example on AWS:

From your application's perspective, requests arrive as plain HTTP on an internal network, but externally users only see HTTPS.

Pattern 3: End-to-end TLS

In more secure environments you may:

This is common in regulated environments where traffic must be encrypted even on internal networks.


Practical HTTPS Guidelines for Backend Developers

When to Use HTTPS

Redirect HTTP to HTTPS

If clients connect to http://example.com, redirect them to https://example.com.

Example HTTP response:

http
HTTP/1.1 301 Moved Permanently
Location: https://example.com/

At your reverse proxy, you can:

Do not serve content on HTTP and HTTPS at the same time. That can confuse clients and weaken security.

Check Security After Deployment

After you set up HTTPS:

  1. Use a browser to check:
    • No security warnings.
    • The lock icon or security badge.
  2. Use tools like:
    • SSL Labs SSL Server Test (by Qualys).
    • curl -v https://your-domain.
  3. Confirm:
    • Only TLS 1.2 and 1.3 are enabled.
    • Strong cipher suites are preferred.
    • Certificate chain is complete.
    • Certificate is not expired and matches domain.

Example: HTTPS Impact on a Simple FastAPI App

Imagine you have a basic FastAPI app:

python
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/secure-data")
def secure_data():
    return JSONResponse({"secret": "only-over-https"})

Local development

You often run:

bash
uvicorn main:app --reload --host 0.0.0.0 --port 8000

And access http://localhost:8000/secure-data. This is fine for local development and testing. For real users, you still deploy behind HTTPS.

Production deployment behind Nginx

  1. Nginx has your certificate.
  2. Nginx is configured like:
nginx
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
    }
}
  1. Your app is still just listening on HTTP internally, but clients always use HTTPS.
  2. In your application, if you need to know whether the request was HTTPS, configure FastAPI / the ASGI server to trust X-Forwarded-Proto from Nginx (for example by using uvicorn --proxy-headers or similar).

Common HTTPS Pitfalls

Mixed Content

If your HTML page is loaded over HTTPS, but it tries to load resources over HTTP, such as:

html
<script src="http://example.com/script.js"></script>

Browsers will block or warn about "mixed content".

Always use:

Using HTTP for API Endpoints in JavaScript

If your frontend is served over HTTPS, calling an HTTP API endpoint from JavaScript is insecure and often blocked.

Example problematic code:

javascript
fetch("http://api.example.com/data")

Use:

javascript
fetch("https://api.example.com/data")

or a relative path if you serve frontend and backend from the same origin.

Expired Certificates

Certificates have an expiration date. If you use Let’s Encrypt, certificates are valid for 90 days. You must have an automatic renewal process.

If your certificate expires:

Summary

Views: 10

Comments

Please login to add a comment.

Don't have an account? Register now!