skip to content

Why must an authorization server accept any port on a native client's loopback redirect URI at request time?

level: middleimportance: should knowfreq 42%

answer

  1. the app did not pick the number
  2. it asked the operating system for one
  3. a fixed port may already be taken
  4. scheme, host and path stay fixed
  5. try both 127.0.0.1 and [::1]

basics

~20 s

Because the native client does not choose the port: it asks the operating system for an available one when it opens its temporary listener, so the number is unknown until the flow starts. RFC 8252 section 7.3 therefore allows any port at request time.

solid answer

~50 s

A loopback redirect works by the application opening a short-lived HTTP listener on the device and having the browser call it. It cannot reserve a fixed port, because on a shared machine that port may already be taken, so it takes an ephemeral one from the operating system at the moment it starts listening. The port number therefore cannot be part of what was registered ahead of time, and RFC 8252 section 7.3 requires the authorization server to allow any port to be specified at request time for a loopback redirect URI. Everything else about the URI is still fixed — this is a carve-out for the port alone, not a licence to vary the path. A client should also not assume which loopback address the device offers: `127.0.0.1` and `[::1]` are both in scope, and the literal address is used rather than a name.

code

http · 7 lines
http
GET /authorize?response_type=code&client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=http%3A%2F%2F127.0.0.1%3A51004%2Foauth2redirect HTTP/1.1
Host: as.example.gov

HTTP/1.1 302 Found
Location: http://127.0.0.1:51004/oauth2redirect?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj

go deeper

for a junior

Recall that a loopback redirect means the application is briefly listening on the device itself, and that the port number is not known until it starts.

for a middle

Explain why an ephemeral port is taken from the operating system and state the allowance precisely: any port at request time, on a loopback redirect, and nothing else about the URI.

for a senior

Demonstrate the operational edges — closing the listener promptly, trying both loopback addresses, and knowing that the exposure here is another local process rather than anything on the network.

for a principal

The angle is where this form belongs in a client estate at all: it suits long-running software on a general-purpose computer and is the wrong default for devices where a background listener is not permitted.

## What a loopback redirect actually is In the loopback form, the native client is briefly a server. Before it sends the authorization request, it opens an HTTP listener on the device's own loopback interface and registers a `redirect_uri` of the shape `http://127.0.0.1:{port}/{path}` or `http://[::1]:{port}/{path}`. When the **authorization server** issues its redirect, the browser makes an ordinary HTTP request to that local address, and the application reads `code` and `state` off the query string. Unlike the other two forms, nothing on the device is dispatching or diverting anything. The binding between the response and the right process is simply *which process is holding that port*. ## Why the port cannot be fixed in advance - A general-purpose computer runs other software. A port the developer picked may already be bound by something else, and the flow would then fail on exactly the machines that are busiest. - Two profiles, two accounts, or two copies of the same application may be running at once. - A fixed, well-known port is a fixed, well-known target for any other local process that would like to hold it first. So the application asks the operating system for an available **ephemeral** port at the moment it starts listening, and only then knows what its own `redirect_uri` looks like. Registration happened long before that. ## The consequence in the specification RFC 8252 section 7.3 states it as an obligation on the server side: for loopback redirect URIs, the **authorization server must allow any port to be specified at the time of the request**, to accommodate clients that take an available port from the operating system. This is a narrow allowance and it is worth being precise about its edges: 1. It applies to **loopback** redirect URIs — `127.0.0.1` and `[::1]` — and not to redirects in general. 2. It covers the **port component only**. The scheme, the host and the path are not made flexible by it. 3. It is about what the server accepts **at request time**, not about what the client registered. ## Which loopback address, and why the literal A client should not assume that a given device supports a particular version of IP. Some devices will offer the IPv4 loopback, some the IPv6 loopback, and a robust client tries both rather than hard-coding one and failing on half its installations. The address is written as a literal — `127.0.0.1` or `[::1]` — rather than as a loopback *name*. A name has to be resolved, and name resolution on a device can be redirected by local configuration; the literal address cannot point anywhere but the host itself. This is also why plain `http` is acceptable in this one place: the request never leaves the machine, so there is no network segment on which to observe or tamper with it. ## What the form is exposed to The loopback form's local character is exactly its weakness. Any other process on the same device can attempt to bind a port, and a listener is reachable by anything running locally, including software running as another user on a shared machine. The exposure is a **local** one; it is not that some remote host can reach the listener, because the loopback interface is host-local by definition. | Question | Loopback form's answer | |---|---| | Who routes the response? | Nobody — the browser makes a direct local request | | What binds it to the right process? | Holding the port at that moment | | Who can interfere? | Another process on the same device | | Who cannot? | Anything off the device | ## Where it fits This form belongs to applications running on a general-purpose computer, where holding a socket for the length of a sign-in is normal. On a mobile device it is usually the wrong choice: the platform may not allow a background listener at all, and the two dispatch-based forms exist precisely because the device can route a URI to an installed application without one. A client shipped across both kinds of device registers both kinds of redirect and uses whichever suits the build.

  • Does the port allowance extend to the path as well?
    No. The allowance in RFC 8252 section 7.3 is for the port component of a loopback redirect URI, because that is the part the operating system decides at run time. The scheme, the host and the path are not loosened by it, and treating the carve-out as general flexibility is the mistake it invites.
  • Why use the literal 127.0.0.1 rather than a loopback hostname?
    A name must be resolved, and resolution on a device can be overridden by local configuration, so a name is not a guarantee that the connection stays on the host. The literal address is: it can only mean this machine, which is also what makes plain `http` defensible for this form.
  • What should the application do with its listener once the code arrives?
    Close it. It exists only to catch one authorization response, and leaving it bound extends the window in which another local process could interact with it. Returning a small confirmation page to the browser and shutting the socket immediately afterwards is the expected shape.

saying these in an interview costs you the question

  • Says the authorization server must reject an unregistered port on a loopback redirect.
  • Registers one fixed port and assumes it is always free on every machine.
  • Believes another device on the network can reach the loopback listener.
  • Assumes every device offers the IPv6 loopback address.
  • Thinks allowing any port means the path may vary too.