When does an OpenID Connect UserInfo response arrive as `application/jwt` instead of `application/json`?
answer
- the media type is the signal
- json unless the client registered otherwise
- application/jwt covers three cases
- sign first, then encrypt
- iss and aud inside a signed one
basics
~20 sWhen the client registered for a signed or encrypted response. Plain claims come back as a JSON object with media type application/json; signed, encrypted, or signed-then-encrypted claims come back as a token with media type application/jwt.
solid answer
~40 sBy default the endpoint answers with a JSON object and the media type `application/json`. If the client registered for a signed and/or encrypted response, the claims are returned inside a token instead and the media type is `application/jwt`. Encryption without signing is permitted; when both are asked for, the response is **signed first and then encrypted**, producing a nested token the relying party unwraps in the reverse order. A signed response carries `iss` — the provider's issuer identifier — and `aud`, the client's own identifier, so the relying party can check who produced it and who it was produced for. What a provider can sign with is advertised as `userinfo_signing_alg_values_supported` in its configuration document. None of this replaces the `sub` comparison.
code
http · 11 linesGET /userinfo HTTP/1.1
Host: op.example.com
Authorization: Bearer SlAV32hkKG
HTTP/1.1 200 OK
Content-Type: application/jwt
eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.eyJpc3MiOiJodHRwc
zovL29wLmV4YW1wbGUuY29tIiwiYXVkIjoiczZCaGRSa3F0MyIsInN1YiI6I
jI0ODI4OTc2MTAwMSJ9.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgd
qrOOF4daGU96Sr_P6qJp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwLgo deeper
Know only that the default answer is a JSON object, and that a token-shaped answer with a different media type is possible when a client has registered for one.
Be able to name the three shapes and the media type each uses, and to state the sign-then-encrypt order with the reason the order is fixed.
Argue when it is worth the key management at all: the signed form earns its place when the claims outlive the connection that delivered them, and not otherwise.
The judgment is where identity claims are allowed to travel in your estate, and whether integrity should ride with the data or be re-established at every boundary that receives it.
Most deployments never see anything but a JSON object come back from the UserInfo endpoint. The specification allows two more shapes, and knowing why they exist — and what they change — is the refinement that separates someone who has read the endpoint's definition from someone who has only called it. ## Three shapes of the same answer | shape | media type | integrity of the body | who can read it | |---|---|---|---| | plain claims | `application/json` | none in the body; the TLS channel carries it | anyone the channel terminates at | | signed claims | `application/jwt` | the provider's signature travels with the body | anyone who receives it | | encrypted claims | `application/jwt` | present only if it was also signed | only the holder of the decryption key | Two consequences fall straight out of the table. First, a plain JSON response has **no integrity of its own** — if it is copied out of the connection into a log, a queue or a cache, nothing downstream can tell whether it was altered. Second, a signed response keeps its integrity wherever it is carried, which is the reason to ask for one: not because the channel is untrusted, but because the body outlives the channel. ## The order matters when both are asked for - **Signed only.** The claims sit in a signed token. Anyone can read them; nobody can change them undetected. - **Encrypted only.** This is permitted. The claims are confidential to the intended reader, but the body carries no signature, so its integrity rests on the same channel a plain JSON body would have relied on. - **Both.** The response is **signed, then encrypted** — a nested token. The relying party decrypts the outer layer first and verifies the inner signature second. Getting that order backwards is the classic mistake, and the reason the order is fixed is easy to state: a signature applied to ciphertext proves only that someone encrypted some bytes. A signature applied to the claims and then hidden inside the encryption proves that the provider asserted **those claims**, and the assertion survives being decrypted. ## What a signed response carries beyond the claims A signed UserInfo response carries `iss` and `aud` as members alongside the claims about the end user: - `iss` is the provider's issuer identifier, compared by the relying party against the issuer it believes it is talking to. - `aud` is or includes the relying party's own client identifier, so a response produced for one client cannot be replayed into another. That is the same three-way habit this whole branch is built on — the body names its origin, the body names its audience, and the receiver checks both against what it knows rather than against what the body says about itself. ## Finding out what a provider will do The provider's configuration document advertises its capability: `userinfo_signing_alg_values_supported` lists the algorithms it can sign a UserInfo response with, and the absence of the member says the provider does not offer signed responses at all. The endpoint's own location is the `userinfo_endpoint` member of the same document. Whether a given client actually receives signed or encrypted responses is fixed by that client's registration, not chosen per request — which is why two clients at one provider can legitimately see different media types. ## What does not change This is the part candidates skip. Wrapping the claims changes the body's integrity and confidentiality; it changes nothing about **whose** claims they are. 1. The response still carries `sub`, and the relying party still compares it with the ID token's `sub` before using a single member. 2. A verified signature proves origin and integrity, not that the presented access token belonged to the person who signed in. 3. The endpoint is still a protected resource reached over TLS with a bearer credential; the response format is not a substitute for the channel. ## When it is worth asking for Ask for a signed response when the claims will be stored, forwarded or replayed somewhere the original connection no longer vouches for them — an audit record, a message on a queue, a profile handed to another component. Ask for encryption when the body will cross something you do not want reading it. In a straightforward server-side relying party that reads the claims and throws the body away, the plain JSON form is the honest default, and adding a token format buys nothing but key management.
- A UserInfo response is encrypted but not signed. What has the relying party actually gained?Confidentiality of the body against anyone who is not the intended reader, and nothing else. With no signature there is no integrity carried in the body itself, so the response is no more self-vouching than a plain JSON one — its authenticity still rests on the protected connection to the provider's endpoint.
- Why does the specification fix the order as sign-then-encrypt rather than the reverse?A signature over ciphertext only attests that someone encrypted some bytes; it does not attest to the claims. Signing the claims and then encrypting the result means the assertion is about the claims themselves and survives decryption, so the relying party ends up holding a statement it can verify and keep.
- How does a relying party learn whether a provider can sign a UserInfo response?From `userinfo_signing_alg_values_supported` in the provider's configuration document, which lists the algorithms available for this endpoint specifically. If the member is absent, the provider is not offering signed responses. Whether a given client receives one is then fixed by that client's registration rather than chosen per call.
saying these in an interview costs you the question
- Thinks every UserInfo response is a signed token by default.
- Says the response is encrypted first and then signed.
- Treats a verified signature as removing the subject comparison.
- Believes encryption without signing also provides integrity.
- Assumes the media type is chosen per request rather than by registration.