[SOLVED] No input on my emoncms - {"success":false,"message":"Username or password empty"}

Hi, I’m trying to have inputs from iotawatt to get to my emoncms instance, but my problem is I never get inputs showing on my emoncms, I get this error message back from my web server: {“success”:false,“message”:“Username or password empty”}

My emoncms is a self hosted instance on a internet server that I manage.
With tcpdump, I see packet arriving to emoncms server. Here is an example of an arriving packet and the answer:


09:37:54.244523 IP (tos 0x0, ttl 245, id 44491, offset 0, flags [none], proto TCP (6), length 1500)
[my_public_ip].51931 > [my_internet_server].com.http: Flags [P.], cksum 0xfb06 (correct), seq 1:1461, ack 1, win 5840, length 1460
E…>b…w.C.H…P.|…c…P…POST HTTP://energy.myserver.com/input/bulk HTTP/1.1
host:energy.myserver.com
Authorization:Bearer [my_readwrite_api_key]
Content-Type:application/x-www-form-urlencoded
Content-Length:2535

time=1551874570&data=[[0,“IotaWatt”,116.87,4551.54,4017.04,44.54,4129.55,2086.93,1433.59,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00],[10,“IotaWatt”,116.73,4070.76,3465.32,43.82,4118.81,1239.17,1353.19,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00],
… … …

09:37:54.284842 IP (tos 0x0, ttl 64, id 52412, offset 0, flags [DF], proto TCP (6), length 450)
[my_internet_server].http > [my_public_ip].51931: Flags [P.], cksum 0xedda (correct), seq 1:411, ack 2739, win 20440, length 410
E…@.@…C.H…w…P…c…|.xP.O…HTTP/1.1 200 OK

Date: Sat, 09 Mar 2019 14:37:54 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: EMONCMS_SESSID=8fb5266c8bddf67e676d23b79f; path=/; HttpOnly
Transfer-Encoding: chunked
Content-Type: application/json
38
{“success”:false,“message”:“Username or password empty”}

Alternatively, if I manually ‘post’ a json message to my emoncms with curl like this for example, it works:

curl --data “data=[[-10,16,1137],[-8,17,1437,3164],[-6,19,1412,3077]]&time=1552143454&apikey=[my_readwrite_api_key]” “http://energy.myserver.com/input/bulk

Is someone had this same issue ?

Iotawatt firmware is 02_03_21
Emoncms is hosted on an Cpanel web server

You’re going to have to unpack this information with more clarity because I can’t make sense of it. The transaction that you show from IoTaWatt gets a response of 200 OK. That’s what Emoncms sends to acknowledge successful receipt of a bulk post. I don’t know why you are not seeing the data in Emoncms, but it appears to be received OK.

The following bold face message is a mystery to me. Where does that come from? It looks like something having to do with a user session logging into Emoncms. IoTaWatt doesn’t send the bulk posts chunked.

Unfortunately, I’m not an Emoncms expert. If it comes to that, you would have to try to get some relief in the OEM forum. A word of advice, don’t lead off saying the data comes from an IoTaWatt. Just show the successful post transaction and see what they make of it.

Can I see the IoTaWatt message log for that period just to see that there isn’t something else going on?

Hello,

Here is some points and thoughts:

  1. the 200 OK answer is in fact an acknowledge for http protocol. It means, “Ok, I received your packet, I will check it.” It is not a “final” answer from emoncms.

  2. Chunked. IMHO, I think it’s because Iotawatt send 2 packets in a row. I just put one packet here but Iotawatt send a packet with data from 0 to 90 and then a second one from 100 to 190 (something like that).

  3. Bold message is the real answer from emoncms that returns {“success”:false,“message”:“Username or password empty”}
    although the API key is provided in authorization field.

  4. I’m going to check emoncms communities, reading the forums, I saw the kind of tension between the 2 communities. Will try.

  5. I don’t have logs available right know, I will get back to you later.

Thank you

Well, I’d disagree on that in the case of 200, I think that the response associated with it is the final answer, but I can now see that the bold type text in your post is actually part of that 200 OK response and consists of the response headers and chunked response. The two blank lines threw me off as a break in context. The CR LF delimiters are significant in the HTTP protocol.

That’s not important. I tried to post to Emoncms running on a Raspberry Pi with no API key.

image

Look familiar? Then if I post with an invalid APIkey, I get
image

So the major difference between the IotaWatt post and your curl post is that the apikey is sent in an authorization header from IotaWatt and it is sent as a keyword parameter as part of the payload in your curl post.

Both methods are currently acceptable, and IoTaWatt always uses the authorization header because it is a tiny bit more secure. In your case, it appears that your Emoncms is not recognizing the authorization header. What version of Emoncms are you running and is it very old? I don’t know when Emoncms started accepting the authorization headers, or if there ever was a time when it didn’t, but it does seem like that is the problem.

You can test this theory out by sending your read/write apikey as a header in curl to see what happens:

-H “Authorization:Bearer [your apikey]”

Great, You pointed me on the right direction.
It now works.

It is definitively something that can be changed on emoncms side when using a cpanel server.

According to this post: PHP does not see Authorization header
I see that, instead of getting a variable HTTP_AUTHORIZATION, I get REDIRECT_HTTP_AUTHORIZATION

So, I just had to change some code on emoncms index.php file to consider REDIRECT_HTTP_AUTHORIZATION like this:

This code is from emoncms version 9.9.8

// 3) User sessions
require("Modules/user/user_model.php");
$user = new User($mysqli,$redis);

$apikey = false;
$devicekey = false;
if (isset($_GET['apikey'])) {
    $apikey = $_GET['apikey'];
} else if (isset($_POST['apikey'])) {
    $apikey = $_POST['apikey'];
} else if (isset($_GET['devicekey'])) {
    $devicekey = $_GET['devicekey'];
} else if (isset($_POST['devicekey'])) {
    $devicekey = $_POST['devicekey'];
} else if (isset($_SERVER["REDIRECT_HTTP_AUTHORIZATION"])) {
    // Support passing apikey on Authorization header per rfc6750, like example:
    //      GET /resource HTTP/1.1
    //      Host: server.example.com
    //      Authorization: Bearer THE_API_KEY_HERE

    if (isset($_SERVER["CONTENT_TYPE"]) && $_SERVER["CONTENT_TYPE"]=="aes128cbc") {
        // If content_type is AES128CBC
    } else {
        $apikey = str_replace('Bearer ', '', $_SERVER["REDIRECT_HTTP_AUTHORIZATION"]);
    }
}

Thank you very much for your help