skip to content

At the OpenID Connect UserInfo endpoint, which credential does a relying party present, and what comes back?

level: juniorimportance: must knowfreq 64%

answer

  1. a protected resource, not a special channel
  2. the credential the resource layer accepts
  3. over TLS, in a request header
  4. sub is always in the body
  5. application/json by default

basics

~20 s

The UserInfo endpoint is an OAuth 2.0 protected resource. The relying party presents the access token from the same sign-in as a bearer credential over TLS, and receives a JSON object of claims about that end user.

solid answer

~40 s

UserInfo is not a special identity channel — it is an ordinary protected resource that answers with identity claims. The relying party looks it up as the `userinfo_endpoint` member of the provider's configuration document, then calls it over TLS with the **access token** from the same grant, sent as a bearer credential in the `Authorization: Bearer` header. Not the ID token: that statement is addressed to the client, validated locally, and is never an API credential. The endpoint accepts `GET` and `POST`, with `GET` plus the header the recommended form. The default answer is a JSON object served as `application/json`, always carrying `sub` and whatever other members the end user's grant covers — `name`, `preferred_username`, `email`, `email_verified` and the like.

code

http · 14 lines
http
GET /userinfo HTTP/1.1
Host: op.example.com
Authorization: Bearer SlAV32hkKG

HTTP/1.1 200 OK
Content-Type: application/json

{
  "sub": "248289761001",
  "name": "Jane Doe",
  "preferred_username": "j.doe",
  "email": "[email protected]",
  "email_verified": true
}

go deeper

for a junior

Remember two things: the access token goes to the endpoint, and a JSON object of claims comes back. Being able to say why the ID token is the wrong credential already puts you ahead of most first-screen answers.

for a middle

Explain the layering out loud: an OAuth 2.0 protected resource guarded by a bearer credential over TLS, located from the provider's configuration document, answering with claims whose set depends on the grant.

for a senior

Show the operational side — the call sits on the login path, it depends on the provider being reachable, and the response is personal data crossing the network, so failure handling and logging both need thought.

for a principal

The angle worth owning is where identity attributes live across an estate: how many services call the provider directly versus read a profile your own platform keeps, and what that choice costs in coupling and in blast radius.

OpenID Connect gives a relying party two different ways to learn something about the person who has just signed in. One is the **ID token**: a signed statement, addressed to the relying party itself, minted during the sign-in exchange. The other is the **UserInfo endpoint**: somewhere the relying party can call afterwards and ask the provider for attributes about that same person. This question is about the second one — who it is for, what it is guarded by, and what it answers with. ## The endpoint is an OAuth 2.0 protected resource The most useful single sentence about UserInfo is that it is not an identity channel with rules of its own. It is an ordinary OAuth 2.0 protected resource that happens to answer with identity claims, and almost everything about calling it follows from that: - Its location is published as the `userinfo_endpoint` member of the provider's configuration document at `/.well-known/openid-configuration`, next to `issuer`, `token_endpoint` and `jwks_uri`. - Communication with it must use TLS. The credential rides in a request header, and a header is transport, not protection. - It accepts the access token as a bearer credential per `RFC 6750`, presented in the `Authorization: Bearer` header — one clause, and that is the whole carriage story here. - It accepts `GET` and `POST` requests; the specification recommends `GET` with the token in the header, and a `POST` sends the credential in the request body instead of the query string. - Its default body is a JSON object served with the media type `application/json`. ## Which token — and why it is not the ID token On this branch the word *token* is ambiguous, and this is precisely where the ambiguity bites. Two artefacts come out of one sign-in and they are addressed to different parties: | artefact | addressed to | what the relying party does with it | |---|---|---| | ID token | the relying party (the client) | validates it and reads it locally; never forwards it as a credential | | access token | the resource being called | presents it to a protected resource, including UserInfo | Presenting an ID token at UserInfo is the most common beginner error in this whole area, and a conforming provider rejects it: the endpoint is looking for a credential that authorises a read, not for a statement about who signed in. The reverse error is just as common — decoding an access token to find a user's name. An access token may be opaque, and even when it is not, what it says is what the bearer may do, not who the bearer is. ## What comes back By default the body is a JSON object. Its members are claims about the end user, and **`sub` is always one of them**. Which other members appear depends on what the end user's grant actually covers, so two clients calling the same endpoint for the same person can legitimately receive different sets. Typical members are `name`, `preferred_username`, `email`, `email_verified`, `picture` and `updated_at`. The response is identity data about a real person travelling over the network, which is the second reason TLS is not optional. The first is that the access token in the header is honoured on possession: anyone who can read it can make the same call. ## What the relying party still owns A 200 response is not the end of the work. 1. **Compare `sub` with the ID token's `sub`** from the same sign-in. The access token presented may not have been issued for the same end user, and nothing in the transport notices. This is the check that turns a convenience call into a safe one. 2. **Do not treat a plain JSON body as self-verifying.** When the media type is `application/json` there is no signature in the body at all; what authenticates the answer is the TLS connection to the provider's own endpoint. 3. **Do not read success as presence.** A UserInfo call succeeds because a grant exists and the credential is still usable. It says nothing about whether the person is sitting at a browser right now. ## Why an interviewer asks this early It separates candidates who have copied an integration from candidates who can say which party each artefact is addressed to. Someone who can answer "the access token, because UserInfo is a protected resource like any other API, and the ID token is mine to consume" has understood the layering: an authorization framework underneath, an identity layer laid on top, and one endpoint that belongs to both.

  • Which HTTP methods may a relying party use against the UserInfo endpoint, and which is recommended?
    Both `GET` and `POST` are accepted. `GET` with the access token in the `Authorization` header is the recommended form; a `POST` carries the credential in the request body instead. The choice changes nothing about the response: the same claims come back, with the same media-type rules.
  • Is `sub` always present in a UserInfo response?
    Yes. Whatever else the grant covers, the subject member is returned. That is not decoration — it is what makes the mandatory comparison against the ID token's `sub` possible at all. A response without it cannot be matched to the sign-in it is supposed to describe, so it cannot be used.
  • Why is UserInfo called an OAuth 2.0 protected resource rather than an OpenID Connect endpoint in its own right?
    Because it is guarded exactly like any other API: a bearer access token over TLS, and an authorization decision made from the grant behind that token. The identity layer contributes only the claim names it answers with and the rule that the relying party must match the subject against its ID token.

saying these in an interview costs you the question

  • Presents the ID token at the UserInfo endpoint as the credential.
  • Calls the endpoint over plain HTTP because the credential is in a header.
  • Assumes the plain JSON body is signed and therefore self-verifying.
  • Reads a successful call as proof the user is at the browser right now.
  • Expects the same members back for every client calling about one person.