Captive Portal API
Extracted elements (30)
HTTPS is used for the API connection for two reasons: it encrypts the exchange against passive listeners on the local network, and it provides an opportunity to authenticate the API server via its certificate, binding it to the provisioned hostname.
Per-client distinct URIs are used when the Captive Portal system cannot otherwise identify the client from visible IP addresses, allowing the API server to correlate requests with the correct portal session without requiring additional authentication headers.
The 'bytes-remaining' count represents total IP layer 3 bytes (sent and received, including IP headers); captive portal systems might not count traffic to whitelisted servers such as the API server, but clients cannot rely on this behavior.
This document defines only the API server interaction phase of the captive portal workflow; discovery of the API server URI is handled separately by RFC 8910 (Captive-Portal Identification in DHCP and RA).
A captive network SHOULD permit connections to OCSP responders or CRLs referenced by API server certificates, and SHOULD also permit NTP connections to allow clients to validate certificates accurately.
All communication between clients and the Captive Portal API server MUST be encrypted; the API server MUST present a valid certificate on which the client can perform revocation checks.
Captive Portal API servers SHOULD set the Cache-Control header field to 'private' or a more restrictive value (such as 'no-store') to prevent caching of per-client data in intermediaries.
Certificates with missing intermediates that rely on AIA extension URIs SHOULD NOT be used by the API server; if AIA is required, the captive network MUST allow client access to the AIA host.
Clients SHOULD include 'application/captive+json' as an Accept header in GET requests; servers MUST mark this media type as their Content-Type header in responses.
If a client receives a key it does not recognize in the JSON response, it MUST ignore the key and any associated values.
If the API server needs information about client identity not otherwise visible, the URI provided during provisioning SHOULD be distinct per client, making it unique for each host and between sessions.
If the client does not receive valid JSON from the API server (due to error or no response), it SHOULD continue applying the most recent valid content received, or interact with the network as if API capabilities were absent.
If the client is unable to validate the certificate presented by the API server, it MUST NOT proceed with any API interaction and will behave as if API capabilities were not present.
OCSP stapling using the TLS Certificate Status Request extension (RFC 6066) SHOULD be used to allow revocation checks without initiating new connections.
The API server endpoint MUST be accessed over HTTP using an https URI and SHOULD use the default https port.
The 'captive' boolean key MUST be included in the top-level JSON structure returned by the API server, indicating whether the client is in a captive state.
The client SHOULD NOT assume that the URI of the API server for a given network will stay the same and SHOULD rely on the discovery or provisioning process each time it joins the network.
The hostname of the user-facing web portal is provided by the API server, not typed by the user, and may contain confusable characters (see RFC 8264 Section 12.5) that could mislead users despite TLS authentication.
The user-facing web portal may collect personal information such as full names and credit card details; both the web portal and the API server pointing to it MUST be accessed over encrypted connections.
The 'bytes-remaining' integer field (optional) indicates the sum of IP layer 3 bytes (including IP headers) remaining before captivity; SHOULD be included for non-captive byte-limited sessions and omitted otherwise.
The 'can-extend-session' boolean field (optional) signals that the user-portal-url allows session extension, hinting the client to suggest visiting the portal when time or bytes are near the session limit.
The 'captive' boolean field (required) indicates whether the client has not yet satisfied conditions for external network access. A captive client (captive=true) retains enough access to perform server authentication.
The 'seconds-remaining' integer field (optional) indicates how many seconds remain before the client is placed into captivity; SHOULD be included for non-captive time-limited sessions and omitted for captive clients or unlimited sessions.
The 'user-portal-url' string field (optional) provides the URL of a TLS-accessed web portal through which a user can interact to exit captivity.
The 'venue-info-url' string field (optional) provides a URL (SHOULD be TLS) for operator-provided information such as store info, maps, or entertainment to share with the user.
IANA created the 'Captive Portal API Keys' registry for JSON keys used in Captive Portal API data structures, administered under the Specification Required policy. Each entry has Key, Type, Description, and Reference fields.
IANA registered the 'application/captive+json' media type for Captive Portal API JSON text, with no required or optional parameters and encoding identical to 'application/json'.
Certificate validation confirms the API server matches the hostname provisioned via DHCP or IPv6 RA (RFC 8910), but does not validate the security of those provisioning mechanisms or the user's trust relationship to the network.
TLS-encrypted connections between clients and the API server protect traffic from passive listeners on the local network and enable server authentication via certificate validation against the provisioned hostname (DNS-ID per RFC 6125).
The Captive Portal API uses the 'application/captive+json' media type over HTTPS. Requests are HTTP GET; responses contain a JSON object with mandatory 'captive' boolean and optional keys defined in the Captive Portal API Keys registry.