# Automating preauthorization using the API

**URL:** <https://hub.mender.io/t/automating-preauthorization-using-the-api/3152>\
**Category:** General Discussions\
**Tags:** raspberry-pi-4, preauthorization\
**Created:** [January 28, 2021, 10:38pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152 "2021-01-28T22:38:00Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 5, 2021, 7:26pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/21 "2021-02-05T19:26:45Z")

</div>

> [@drewmoseley](#):
>
> cat keys-client-generated/public.key | sed -e :a -e ‘N;s/\n/\n/;ta’

this returns;

```
sed: 1: "‘N
": invalid command code ?
zsh: no such file or directory: s/n/n/
zsh: command not found: ta’

```

I’m running Catalina 10.15.7 on my Mac, and Rasbian Buster v10 on the RPi I’m trying to Preauth.

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 5, 2021, 7:29pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/22 "2021-02-05T19:29:58Z")

</div>

This was after having re-ran the `./keygen-client` and

```
DEVICE_PUBLIC_KEY="$(cat keys-client-generated/public.key | sed -e :a -e 'N;s/\n/\\n/;ta')"

```

to format it in my environment variable.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 5, 2021, 8:19pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/23 "2021-02-05T20:19:14Z")

</div>

Interesting. It looks like the sed syntax in this command is specific to GNU sed and does not work with the MacOS version of sed. I was able to get a similar error on my Big Sur machine.

If you have homebrew installed and the sed from there installed as “gsed” you can modify the command to use that instead.

Alternately it looks like using:

```auto
DEVICE_PUBLIC_KEY="$(cat keys-client-generated/public.key | awk 1 ORS='\\n')"

```

will work. Can you give that a shot?

Drew

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 5, 2021, 11:11pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/24 "2021-02-05T23:11:41Z")

</div>

That got the public key set to my `DEVICE_PUBLIC_KEY` variable and running;

```
curl -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" -X POST -d "{ \"identity_data\" : $DEVICE_IDENTITY_JSON_OBJECT_STRING, \"pubkey\" : \"$DEVICE_PUBLIC_KEY\" }" $MENDER_SERVER_URI/api/management/v2/devauth/devices

```

now adds the device to my Preauthorized devices in hosted Mender. Thanks for the support! Now I just have to add the formatted public key to my Google Cloud function and make sure the call from there works as well.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 6, 2021, 3:56pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/25 "2021-02-06T15:56:02Z")

</div>

Awesome. I’ll submit a docs change with that fix.  
Drew

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 8, 2021, 1:58am UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/26 "2021-02-08T01:58:13Z")

</div>

So the code I posted earlier that makes the API call from my Firebase Function still fails to put the device in the Preauthoried column of my dashboard after having copy-pasted the formatted public key used in the `curl` request that worked.

I’ve tried adding the public key to the call from my environment several different ways;

```
"identity_data": {
    "sku": `"${deviceId}"`,
    "sn": `"${sn}"`
  },
  "pubkey": `"${process.env.MENDER_PUBKEY}"`,
};

 "identity_data": {
    "sku": `'${deviceId}'`,
    "sn": `'${sn}'`
  },
  "pubkey": `'${process.env.MENDER_PUBKEY}'`,
};

 "identity_data": {
    "sku": `${deviceId}`,
    "sn": `${sn}`
  },
  "pubkey": `${process.env.MENDER_PUBKEY}`,
};

```

But they all return the response `body: {"size":0, "timeout":0}` as seen in my earlier post.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 9, 2021, 12:45am UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/27 "2021-02-09T00:45:23Z")

</div>

Hi @bradw the only thing I see different from our [JavaScript example code](https://docs.mender.io/api/?javascript#preauthorize) is that _pubkey_ needs to be quoted as a string.  
Drew

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 9, 2021, 5:00pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/28 "2021-02-09T17:00:25Z")

</div>

That’s what I was showing in my last post. I tried it the three ways shown there. Using string interpolation I pass it from my `process.env` using single, double and no quotes. All three return the same result.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 10, 2021, 2:19pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/29 "2021-02-10T14:19:15Z")

</div>

Sorry but I don’t know much about Javascript. Perhaps @mzedel can comment on that.

Does Firebase have any kind of logging so we can see exactly what the API call looks like on the wire?

Drew

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 10, 2021, 3:43pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/30 "2021-02-10T15:43:57Z")

</div>

Just what I’ve taken screenshots of earlier.

 ![Screen Shot 2021-02-10 at 7.42.30 AM](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/b/bc94496673550c0b8553765baef17bfc2b921a1b.png)

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 10, 2021, 10:54pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/31 "2021-02-10T22:54:59Z")

</div>

Can you generate another screenshot with the full details of the preauth call? It looks like there is a twistout to show more details.

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 11, 2021, 12:09pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/32 "2021-02-11T12:09:47Z")

</div>

The point where it says “function execution took ms, finished with status ‘ok’” and “Function execution started” doesn’t expand with nay additional info, even though there is an expand arrow there. The same with where it says `body: {"size": 0, "timeout:0)`

Here is the other where it says `menderPreauth` with the sensitive info blacked out;

 ![Screen Shot 2021-02-11 at 3.58.20 AM](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/b/b06299f58e84b8bd1d93af763c1f2c38990b957e.png)

I think that it may be related to the actual deployment of the function to FIrebase Cloud Functions.

---

<div class="post-metadata">

**Author:** ![mzedel](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/mzedel/32/261_2.png) [@mzedel](https://hub.mender.io/u/mzedel)\
**Post date:** [February 11, 2021, 1:54pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/33 "2021-02-11T13:54:56Z")

</div>

Heyho @bradw,  
just now I used your code to get devices accepted and it was pretty close to working, the issues I found were the auth header needs to have the `Bearer ` part in:

```auto
const headers = {
      'Content-Type':'application/json',
      'Accept':'application/json',
      'Authorization':`Bearer ${process.env.MENDER_API_KEY}`
}

```

Apart from that `node-fetch` didn’t stringify the body automatically so I had to change the request options to:

```auto
{
        method: 'POST',
        body: JSON.stringify(inputBody),
        headers: headers
}

```

and finally, the response body will be empty if successful, with the headers containing the location of the newly created device:

```auto
.then(res => {
    const deviceId = res.headers.get('Location').substring(res.headers.get('Location').indexOf('/') + 1);
    console.log(`deviceId: ${deviceId}`);
    return Promise.resolve(deviceId);
})

```

Looking at the docs I see that the bearer part in the header is missing there and the `res.json()` is misleading there… While I fear this is due to the underlying docs generator we use, I’ll create a ticket to get this fixed!

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 11, 2021, 5:04pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/34 "2021-02-11T17:04:06Z")

</div>

I knew it had to be something simple like that. Thanks so much for looking into this for me. I’ll plug this all in to my code, give it a go and let you know how it works out.

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 12, 2021, 5:09pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/35 "2021-02-12T17:09:12Z")

</div>

When I update my code with what you’ve shown it now hits my `catch()` block and returns `Error: {}`.

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 12, 2021, 5:22pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/36 "2021-02-12T17:22:10Z")

</div>

Here is the code that produces `Error:{}` from the `catch()` block

```
const fetch = require('node-fetch');
const functions = require('firebase-functions');

module.exports = functions.pubsub.topic('menderPreauthorize').onPublish((message) => {
  const deviceId = message.data ? Buffer.from(message.data, 'base64').toString() : null;
  let response
  if (deviceId) {
    const sn = deviceId.split('y')[1]
    const inputBody = {
    "identity_data": {
        "sku": deviceId,
        "sn": sn
      },
      "pubkey": process.env.MENDER_PUBKEY,
    };
    const headers = {
      'Content-Type':'application/json',
      'Accept':'application/json',
      'Authorization':`Bearer ${process.env.MENDER_API_KEY}`
    };
    response = fetch ('https://hosted.mender.io/api/management/v2/devauth/devices',
    {
      method: 'POST',
      body: JSON.stringify(inputBody),
      headers: headers
    })
    .then(res => {
        const deviceId = res.headers.get('Location').substring(res.headers.get('Location').indexOf('/') + 1);
        console.log(`deviceId: ${deviceId}`);
        return Promise.resolve(deviceId);
    })
    .catch((err) => {
      console.log(`Error: ${JSON.stringify(err)}`)
      return err
    })
  } else {
    response = 'deviceId was null.'
  }
  return response
})
```

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 16, 2021, 1:09am UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/37 "2021-02-16T01:09:20Z")

</div>

After some investigation I found this [Stack Overflow post](https://stackoverflow.com/a/58734908/2041665) that notes `node-fetch` not playing nicely with `Firebase Functions` and is now suggesting `axios` as a better alternative. I was also getting the `{size:0, timeout:0}` and `body` related errors some mention in the comments under the solution using `node-fetch`.

Using `axios` and the same `MENDER_PUBKEY` and `MENDER_API_KEY` as when I had successfully made the call using `curl`, I updated my code to the following;

```
const axios = require('axios');
const functions = require('firebase-functions');

module.exports = functions.pubsub.topic('menderPreauthorize').onPublish((message) => {
  const deviceId = message.data ? Buffer.from(message.data, 'base64').toString() : null;
  let response
  if (deviceId) {
    const sn = deviceId.split('y')[1]
    const inputBody = {
    "identity_data": {
        "sku": deviceId,
        "sn": sn
      },
      "pubkey": process.env.MENDER_PUBKEY,
    };
    const headers = {
      'content-type':'application/json',
      'Accept':'application/json',
      'Authorization':`Bearer ${process.env.MENDER_API_KEY}`
    };
    response = axios({
      method: 'post',
      url: 'https://hosted.mender.io/api/management/v2/devauth/devices',
      data: JSON.stringify(inputBody),
      headers: headers
    })
    .then((res) => {
        return res.data
    })
    .catch((err) => {
      if (err.response) {
        console.log(`error data: ${JSON.stringify(err.response.data)}`)
        console.log(`error status: ${err.response.status}`)
        console.log(`error headers: ${JSON.stringify(err.response.headers)}`)
      } else if (err.request) {
        console.log(`error response: Request was made but no response received, ${err.request}`)
      } else {
        console.log(`Error: ${err.message}`)
      }
    })
  } else {
    response = 'deviceId was null.'
    console.log('deviceId was null')
  }
  return response
})

```

Now I receive a `401` error status code, `Unauthorized` as shown here;

 ![Screen Shot 2021-02-15 at 5.08.21 PM](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/3/3dce3a1aae26baabe13662d173d98c8e18fac2a4.png)

---

<div class="post-metadata">

**Author:** ![bradw](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/bradw/32/933_2.png) [@bradw](https://hub.mender.io/u/bradw)\
**Post date:** [February 16, 2021, 7:41pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/38 "2021-02-16T19:41:55Z")

</div>

@drewmoseley I updated `JWT` again as you show [here](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/23), verified I could call the API via `curl`, regenerated my `MENDER_PUBKEY` and updated it and `MENDER_API_KEY` accordingly in my Firebase Function’s environment variables and still get this `401 Unauthorized` error (which is at least a more descriptive error than I had been getting).

I’ve tried it with `data` in lieu of `body` in the `axios` request per their docs and tried both with and without `JSON.stringify()` around the `inputBody`. Any other ideas?

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 16, 2021, 7:56pm UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/39 "2021-02-16T19:56:30Z")

</div>

I don’t have any ideas. Perhaps @mzedel, @Alan or @peter know more.

---

<div class="post-metadata">

**Author:** ![tranchitella](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/tranchitella/32/606_2.png) [@tranchitella](https://hub.mender.io/u/tranchitella)\
**Post date:** [February 17, 2021, 5:01am UTC](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152/40 "2021-02-17T05:01:13Z")

</div>

@bradw can you please dump the full request and paste it here, removing the JWT token?

[Previous page](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152.md?page=1)

[Next page](https://hub.mender.io/t/automating-preauthorization-using-the-api/3152.md?page=3)
