serverProtect Your API

Integrating DPoP to our resource server.

circle-info

What you'll build: A FastAPI resource server that validates DPoP-bound Keycloak access tokens, rejecting requests that cannot prove possession of the client’s private key.

chevron-rightPrerequisiteshashtag

This example requires completion of all setup steps listed on the Prerequisitesarrow-up-right page. To summarize:

Setup Keycloak

Create docker-compose.yml :

services:
  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
    ports:
      - "8080:8080"
    command:
      - start-dev
      - --import-realm
    volumes:
      - ./realm-export.json:/opt/keycloak/data/import/realm-export.json
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"]
      interval: 10s
      timeout: 5s
      retries: 5

Create realm-export.json :

Start keycloak:

5-Line Core

Essential code to integrate DPoP using Keycloak provider.

Step-by-Step

1

Configure Environment

Create .env file:

2

Setup Provider

3

Protect Endpoints

4

Run The Server

5

Test The API

Before you can access the protected resource, refer to Generate Proof page to understand how DPoP proof generation works.

circle-check

Complete Example

Create main.py:

Run it:

Error Code Table

Error
Meaning

401

Missing / invalid DPoP proof

401 + DPoP-Nonce

Nonce required

403

Token bound to different key

Common Pitfalls

Pitfall
Symptom
Solution

Using get_current_user instead of get_current_user_with_dpop

DPoP proofs are ignored and bearer tokens are accepted

Use get_current_user_with_dpop for endpoints that require proof-of-possession

Accepting Authorization: Bearer for DPoP endpoints

Stolen tokens can still be replayed

Require Authorization: DPoP <token> for DPoP-protected routes

DPoP provider not configured in the gateway

All DPoP requests fail validation

Ensure KeycloakDPoPProvider is passed to IAMGateway.from_fullstack_provider()

cnf.jkt missing in access token

Token is not bound to a client key

Verify that DPoP was used during the token request to Keycloak

Proof signature validates but request still fails

Key thumbprint mismatch

Confirm the client is using the same key pair used during token issuance

Forgetting to enable DPoP in DPoPConfig

DPoP headers are ignored

Set DPoPConfig(enabled=True) explicitly

Enabling nonce without client support

Clients fail after first request

Only enable nonce protection if clients implement retry logic

Assuming DPoP replaces authorization

Users can authenticate but access still fails

DPoP protects tokens; role checks and permissions are still enforced separately

Production Notes

Security Guidelines for Production Deployments

  • Avoid Key Generation at Runtime

    • Do not generate keys during runtime in production.

    • Each client must maintain a stable, persistent key pair.

  • Key Storage

    • Browsers: Use IndexedDB or WebCrypto-backed storage.

    • Non-browser clients: Utilize secure keystores or encrypted disk storage.

    • Important: Protect private keys as secrets.

  • Handling DPoP Private Keys

    • DPoP private keys are as sensitive as access tokens. Treat them with care:

      • Do not log them.

      • Do not commit them to version control.

      • Do not transmit them over the network.

  • Exclusively Use HTTPS

    • DPoP does not replace TLS. Always use HTTPS to secure headers, proofs, and tokens during transit.

  • Nonce Handling

    • If your server requires nonce-based replay protection:

      • Detect 401 responses with DPoP-Nonce.

      • Regenerate the proof including the nonce.

      • Retry the request as necessary.

  • Key Pair Segregation

    • Never share keys across users or devices.

    • Each user-agent instance should have its own key pair to maintain DPoP security guarantees.


circle-info

Found an issue on this page? Report it on our feedback formarrow-up-right.

Last updated

Was this helpful?