On mobile OSes, the captive portal is opened in a sandboxed embedded browser. OS designers want to prevent the captive portal from being used maliciously, so they understandably block off a lot of functionality. Problem is they don’t tell you what features they turn off. I.e As far as I can tell iOS blocks off external links and ajax requests (!)
On iOS you can’t close the captive portal programmatically. The user must submit an html form (or similar) and navigate to a new page. Only then will the OS check /mobile-hotspot-detect and realize that the user is connected to the internet and present the user a button to close the captive portal. This is very clunky and makes it impossible to make a sleek user experience
Android automatically closes the captive portal when it detects a connection. This often confuses the user (why did my page suddenly disappear?) and makes it impossible to make a consistent mobile captive portal experience between iOS and android
Androids kernel seems to have two separate, independent captive portal checks
iOS only checks the content of the connectivity check endpoint, while android also checks for any form of a DNS redirect in its requests
Microsoft checks against two different domains for a captive portal
Many Non-stock android distros check against their own custom (and undocumented) endpoints
There was a dhcp option recently introduced to help clean up this mess. Problem is, nobody supports it. Not even Apple (who seemed to have played a hand in the RFC) supports it
Linux is a lost cause
Figuring this all out took over a month of trial and error. Even then many of my conclusions are probably wrong. None of this is documented or standardized!
I've been there. I can relate to everything you said!
The DHCP standard was such a waste of time. Ignore it completely, no client support whatsoever.
Intercepting all plain HTTP traffic (just drop https) and responding with a 30x redirect to your captive portal web page seems to be the ad-hoc "standard". Your captive portal domain can be served under secured HTTPS just fine.
I fully agree with the sandboxed browsers pain and absolute impossibility to get a nice consistent UX across platforms.
Totally agree. Like you said the method we converged on is to just redirect DNS requests + 303 users depending on if they’ve gotten through the portal yet. It seems to work fine. What’s most frustrating is that most off-the-shelf FOSS dns programs don’t let you do DNS redirects on a per-mac basis, leading us to in-house a decent amount of DNS code.
I mean, captive portals started out as a hack, then captive portal detection was a hack against that hack... It's effectively an antagonistic relationship.