Authdog

Backend requests

Last updated Jul 11, 2026
View as Markdown

Your backend never sees a password. Its job is to validate the session that Authdog already issued to the browser and to enforce access on protected routes. This page covers the verification model, protecting endpoints, service-to-service auth, and the SDKs that wrap it all.

What arrives at your backend

After a successful sign-in, Authdog issues a signed JWT session. Every request from your frontend carries it one of two ways:

  • The authdog-session cookie (set automatically by the browser SDK).
  • An Authorization: Bearer <token> header (for native apps and API clients).

Your backend reads whichever is present and validates it before trusting anything in the request.

The verification model

Backends validate a session with two inputs: your environment's public key (pk_...) and the identity provider's userinfo endpoint. The public key is parsed once at startup — a malformed key, or one whose identity host is not on the trusted allowlist, fails immediately rather than on the first request. For each request the SDK reads the token, verifies it against userinfo, and returns the current user. See Sessions & tokens and Authentication for the full model.

Protecting a route

Resolving a session is informational — it tells you who the caller is, or that there is no caller. The real enforcement point is a guard that rejects unauthenticated requests with a 401. In Python (FastAPI) that guard is a dependency:

Python
import os
from fastapi import Depends, FastAPI
from authdog.fastapi import Authdog

app = FastAPI()
authdog = Authdog(public_key=os.environ["PK_AUTHDOG"])

@app.get("/me")
async def me(user=Depends(authdog.require_auth)):
    # reached only for a valid session; 401 otherwise
    return user

Every SDK exposes the same shape: a resolver you can read for response shaping, and a require_auth gate that is the security boundary. Never treat "the session resolved" as authorization on its own — pair it with your environment's authorization model.

Service-to-service (M2M)

For requests with no end user — a cron job, a backend calling another backend — use machine-to-machine auth. An M2M application uses the OAuth2 client_credentials grant to obtain a token, which you then send as Authorization: Bearer <token>. The receiving service validates it exactly like a user session but resolves a service identity rather than a person.

Calling the REST API

Once a request is authenticated, your backend calls the Authdog REST API under /v1/... (base URL from NEXT_PUBLIC_API_ENDPOINT) to read users, organizations, and more. The backend SDKs are typed clients over this API, so you rarely construct raw requests yourself.

Shipped backend SDKs

All expose the same three primitives — session resolver, require_auth gate, and logout handler:

  • Node — Express and Fastify
  • Python — FastAPI, Django, Flask
  • Go
  • Rust
  • Java
  • .NET (C#)

Events and webhooks

Beyond request handling, identity emits events (user.created, user.signed_in, ...) your backend can subscribe to. Webhooks are HMAC-signed (X-Authdog-Signature: t=...,v1=...) with durable retry — verify the signature before acting on the payload.

Learn more