openwisp / openwisp-wifi-login-pages

Configurable captive page for public/private WiFi services providing login, sign up, social login, SMS verification, change password, reset password, change phone number and more.
https://openwisp.org
GNU General Public License v3.0
119 stars 74 forks source link

[change] Allow showing failure messages coming from captive portal #604

Open nemesifier opened 1 year ago

nemesifier commented 1 year ago

If form posted in the iframe responds with:

https://wifi-demo.openwisp.io/openwisp/login?res=failed&reason=reject&uamip=192.168.182.1&uamport=3990&called=80%3a3F%3a5D%3a9E%3a58%3a5C&mac=B4-69-21-D2-A6-D1&ip=192.168.182.3&reply=Your%20maximum%20daily%20usage%20time%20has%20been%20reached&nasid=chilli&sessionid=165791407900000003&ssl=https%3a%2f%2fwifiauth.openwisp.io.coova.org%3a3991%2f&userurl=http%3a%2f%2fdetectportal.firefox.com%2fcanonical.html

The actual implementation doesn't manage to show the message to the user.

Let's look for a solution.

nemesifier commented 1 year ago

We could allow configuring the following parameters in the captive_portal_login YAML part:

result_param_name: get parameter which if present indicates the result of authentication, can default to res reason_failed_value: (defaults to failed) if the value of the result GET param matches this value, we can consider the authentication as failed failure_message_param_name: get parameter which contains the reason for the failure, can default to reply

This should happen in the login component. If an auth failure is detected, we can simply use postMessage to communicate the failure and the failure reason to the parent frame as described here: https://github.com/openwisp/openwisp-wifi-login-pages#handling-captive-portal--radius-errors.

We should also update that README section to indicate that for captive portals like coova chilli which simply redirect to the login page with some GET parameters in the querystring (instead of showing a dedicated failure page) this method can be used.

nemesifier commented 1 year ago

This can be solved with the following extra JS file loaded for the whole application:

function _getParam(name){
   if(name=(new RegExp("[?&]"+encodeURIComponent(name)+"=([^&]*)")).exec(location.search))
      return decodeURIComponent(name[1]);
}

var res = _getParam("res"),
    reply = _getParam("reply");

if (res === "failed" && reply) {
  window.parent.postMessage(
    {type: "authError", message: reply},
    "https://<HOSTNAME>",
  );
}

It's good enough for me now.