RADIUSdesk

CoovaChilli JSON Interface

Introduction

  • If CoovaChilli is compiled with JSON support it exposes a JSON interface on the controller.
  • This document will discuss the technical workings of the JSON interface.
  • In order to have access to the JSON interface you have to be on the same network served by CoovaChilli, this means you have to be connected to the hotspot in plain english.

Accessing the JSON interface

Specifying a Callback

jQuery33105641008201093548_1612410177983({"versio......28-D2-44-20-04-8D"}})

The JSON interface methods

  • The JSON interface has three endpoints exposed. They are
    • status Report on the current status of the client from which you are making the call
    • logon Used to log a user onto the captive portal. Needs a valid RADIUS username and encrypted password.
    • logoff Used to disconnect a user that has an active session on the captive portal.

We will now unpack each of these endpoints in their own dedicated session

status

  • The reply of a status call will indicate the current connection status of a client / user from where the call was made.
  • Here is a typical reply when the user is not connected
{
   "version":"1.0",
   "clientState":0,
   "nasid":"ZA-VM1",
   "challenge":"0caeb2c0240fca8f430ea54e6423151e",
   "location":{"name":"My HotSpot"},
   "redir":{
      "originalURL":"http://detectportal.firefox.com/success.txt",
      "redirectionURL":"",
      "logoutURL":"http://10.1.0.1:3990/logoff",
      "ipAddress":"10.1.0.2",
      "macAddress":"28-D2-44-70-04-00"
    }
}
  • Here is a typical reply when the user is connected
{
   "version":"1.0",
   "clientState":1,
   "nasid":"ZA-VM1",
   "redir": {
      "originalURL":"http://detectportal.firefox.com/success.txt",
      "redirectionURL":"",
      "logoutURL":"http://10.1.0.1:3990/logoff",
      "ipAddress":"10.1.0.2",
      "macAddress":"28-D2-44-70-04-00"
   },
   "session":{
      "sessionId":"161241022400000001",
      "userName":"click_to_connect@demo1",
      "startTime":1612410289,
      "sessionTimeout":0,"terminateTime":0,
      "idleTimeout":0,
      "maxTotalOctets":249823541
   },
   "accounting":{
      "sessionTime":15,
      "idleTime":0,
      "inputOctets":144606,
      "outputOctets":85859,
      "inputGigawords":0,
      "outputGigawords":0,
      "viewPoint":"client"
   }
}
  • The item that indicates if there is an active session is the value of ClientState
    • 0 No active session
    • 1 Active session

logon

  • The logon process consists of three calls
    • Doing a status call to get the latest challenge from the status reply
    • Doing a call the the UAM encryption service on the RADIUSdesk back-end by calling the uam.php script.
    • Using the returned hash value together with the username to to a call to the JSON login end-point.

Get the latest challenge

  • Each time we do a call to the status end point we get a new challenge in the reply.
  • CoovaChilli remembers the last challenge it generated for a client (when they are not logged in) and uses that during the login process.
  • This is why its good practice to do a status call as step one of the login process to get a fresh challenge from CoovaChilli. (There is an expiry on the challenge which is why we go this route to ensure we have a current value that has not expired yet)
  • The call to the status end point was already covered earlier in the document. From it you can see there is a challenge item.

Encrypt the Challenge and Password

jQuery331012987580313312852_1612418453858(
   {
       'response':'7215ee77b34e83ced8f816ec3f2bf2c3'
    }
)
  • You will replace hotspot.radiusdesk.com with the FQDN or IP Address of your own server

Call the logon JSON endpoint

{
	"GET": {
		"scheme": "http",
		"host": "10.1.0.1:3990",
		"filename": "/json/logon",
		"query": {
			"callback": "jQuery331036884032348716045_1612421095535",
			"username": "click_to_connect@demo1",
			"password": "7215ee77b34e83ced8f816ec3f2bf2c3",
			"_": "1612421095539"
		},
		"remote": {
			"Address": "10.1.0.1:3990"
		}
	}
}
  • And here's the response of a successful logon
{
	"version": "1.0",
	"clientState": 1,
	"nasid": "ZA-VM1",
	"redir": {
		"originalURL": "http://detectportal.firefox.com/success.txt",
		"redirectionURL": "",
		"logoutURL": "http://10.1.0.1:3990/logoff",
		"ipAddress": "10.1.0.2",
		"macAddress": "28-D2-44-20-04-8D"
	},
	"session": {
		"sessionId": "161241843700000001",
		"userName": "click_to_connect@demo1",
		"startTime": 1612418460,
		"sessionTimeout": 180,
		"terminateTime": 0,
		"idleTimeout": 0
	},
	"accounting": {
		"sessionTime": 0,
		"idleTime": 0,
		"inputOctets": 0,
		"outputOctets": 0,
		"inputGigawords": 0,
		"outputGigawords": 0,
		"viewPoint": "client"
	}
}

logoff

{
	"GET": {
		"scheme": "http",
		"host": "10.1.0.1:3990",
		"filename": "/json/logon",
		"query": {
			"callback": "jQuery331036884032348716045_1612421095535",
			"username": "click_to_connect@demo1",
			"password": "d24ae9fbf467e62642d1f4963016aca6",
			"_": "1612421095539"
		},
		"remote": {
			"Address": "10.1.0.1:3990"
		}
	}
}
  • Repsonse
{
	"version": "1.0",
	"clientState": 0,
	"nasid": "ZA-VM1",
	"challenge": "efad131ebc031da777a4b7957eb58299",
	"session": {
		"sessionId": "161242107800000001",
		"userName": "click_to_connect@demo1",
		"startTime": 1612421102,
		"sessionTimeout": 180,
		"terminateTime": 0,
		"idleTimeout": 0
	},
	"accounting": {
		"sessionTime": 0,
		"idleTime": 0,
		"inputOctets": 0,
		"outputOctets": 0,
		"inputGigawords": 0,
		"outputGigawords": 0,
		"viewPoint": "client"
	}
}
  • As you can see the reply is pretty much the same than logon but the clientstate is now 0 meaning it logged off fine.