Signed Authorization Requests (JAR) — Recommended
Signed requests are the production path. Instead of sending parameters as a query string, you put them inside a request object: a JSON Web Token (JWT) signed with your client's private key and passed in the request parameter (RFC 9101). OIDC Web verifies the signature against your registered public key and rejects anything that does not match. A forged or tampered authorization request is therefore rejected before any verification credit is spent.
Why signing matters. Anyone who sees a plain authorization URL can copy, edit, and replay it. Forged requests can never log anyone in. They can still burn your verification credits, exhaust your rate limit, and deny service to real users simply by arriving. Signing makes those requests bounce immediately. Configure your client to require signed requests in production.
Build and Sign the Request Object
Include the same parameters you would otherwise put in the URL as JWT claims. Sign the object with your private key:
import time, jwt # PyJWT
now = int(time.time())
request_object = {
"iss": CLIENT_ID,
"aud": ISSUER, # the "issuer" from discovery, e.g. $BASE/oidc/v1
"client_id": CLIENT_ID,
"response_type": "code",
"redirect_uri": "https://yourapp.example/callback",
"scope": "openid faceauth_dynamic_only",
"login_hint": "jane.doe@example.com",
"state": state,
"nonce": nonce,
"code_challenge": code_challenge, # from auth code flow step 1
"code_challenge_method": "S256",
"nbf": now, # required
"exp": now + 120,
}
signed_request = jwt.encode(request_object, PRIVATE_KEY_PEM, algorithm="ES256")
OIDC Web requires nbf, scope, and redirect_uri inside the signed request object. OIDC Web also verifies aud against the issuer. Values inside the signed object take precedence over any duplicated query parameters.
Redirect the Browser
Pass the signed object in request:
$BASE/oidc/v1/authorize?client_id=$CLIENT_ID&request=<signed_request_jwt>
From here the flow is identical to Auth Code Flow. The user verifies, and you receive code on your redirect URI. You then exchange the code at the token endpoint. Supported request-object signing algorithms are ES256, PS256, and RS256.