API Token, what does it mean? and how do i use it?

Hi everyone!
I created API TOKEN in the Application Server Web Interface. I get a TOKEN, if I put this token in the right corner of the ChirpStack Application Server REST API, I can use the API seamlessly from the web interface.

I realize that I can generate a new API token in /api/internal/login.

I’m confused, can someone explain to me?

What is each one? When to use one and when to use the other?

I think this explains the use of API tokens fairly well:

https://www.chirpstack.io/application-server/api/

Specifically, they are long-lived and revocable. They are the current preferred way to interface programmatically with the API.

The /api/internal/login endpoint provides an JWT token, which are shorter lived (24h by default, I believe) and are intended for use by the Application Server web UI. @brocaar has also made clear a couple times that the /internal endpoints are subject to change if needed, and should not be depended on.

Actually, this is my next port to sort as well when i get time.

I am running NS, GW, AS with docker in the cloud and have access to the api at the specified endpoint. However setting up the JWT token must require specific encoding to work in the API.

I tried the default set ‘verysecret’ as well as generating my own JWT in the docker compose setup however none of these work and return “authentication failed: jwt parse error: token contains an invalid number of segments” on test. I set and tried the global and organisational API keys generated in webUI but these also return the same.

Is there any documentation on how to structure the JWT correctly if you use docker?

You do not structure the JWT yourself, it is returned from either the /api/internal/api-keys or /api/internal/login endpoints. The key to which are you are referring is the signing key.

Sorry if i sound a little daft here… but I’m not exactly sure what you mean.

if i go to https://example.com/api/internal/api-keys
I have also tried…
https://example.com/api/internal/api-keys/{api-key}
https://example.com/api/internal/api-keys?{api-key}
https://example.com/api/internal/api-keys={api-key}
https://example.com/api/internal/{api-key}

all return a 401 on URL endpoint


"error": "authentication failed: get token from context error: no authorization-data in metadata",
"code": 16,
"message": "authentication failed: get token from context error: no authorization-data in metadata",
"details": []
}

if i go to https://example.com/api/internal/login

Method Not Allowed

Is there a simple step here i’m missing in setup or config to allow this?

If you navigate to /api on your Application Server, you will see all the OpenAPI (Swagger) docs.

More information here: https://www.chirpstack.io/application-server/api/ (second half)

Yes, I can access that end point no problems there seems to be some kind of authentication error when I try to use it. I haven’t moved on to writing any scripts to make use it yet because of this hurdle.

As no JWT is shown in the box as per documents on loading the page (which i hope would be correct!), the default set JWT of verysecret doesn’t work and if I set this using the one generated by openssl rand -bas64 32 as suggested in the docs it also returns a 401 error of…

{
  "error": "authentication failed: jwt parse error: token contains an invalid number of segments",
  "code": 16,
  "message": "authentication failed: jwt parse error: token contains an invalid number of segments",
  "details": []
}

Which would be correct as a quick check on the output of any openssl rand -base64 doesn’t produce a valid JWT token…

This is contents of my chirpstack-docker AS chirpstack-application-server.toml

[postgresql]
dsn="postgres://chirpstack_as:chirpstack_as@postgresql/chirpstack_as?sslmode=disable"

[redis]
url="redis://redis:6379"

[application_server.integration.mqtt]
server="tcp://mosquitto:1883"

[application_server.api]
public_host="chirpstack-application-server:8001"

[application_server.external_api]
bind="0.0.0.0:8080"
#jwt_secret="verysecret"
jwt_secret="vhW41eFiXYXHEWVgBsi4QOMq8l2fq+OTnPcAagUFIRw="

generate a random base64 string as instructed and place in…
chirpstack-application-server.toml file.

find following line in file for the jwt secret…
jwt_secret="verysecret"

now generate a secret with output of openssl rand -base64 32 as per docs and replace the above with your randomly generated secret. (example below).
jwt_secret="vhW41eFiXYXHEWVgBsi4QOMq8l2fq+OTnPcAagUFIRw="

with this set restart the service… head over to http swagger API…
example.com/api (this should load ChirpStack Application Server REST API page).


Enter your login details in place of above and click ‘Try it out!’ if your details are correct you should receive a 200 response with a JWT token.

{
  "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<truncated>"
}

copy your complete token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<truncated> and paste it in the top bar where is says ‘JWT TOKEN’.

You should now have access to use API from swagger http interface.
(Python post request to http://example.com/api/internal/login with a json structured payload will also return you the signed jwt…) for eg.

import requests
import jwt
login = {"email":"user@example.com", "password":"5ecr3t_passw0rd"}
token = requests.post('http://example.com/api/internal/login', json=login).json()
print(token['jwt'])
3 Likes

This is not the recommended way to interact with the API (it was a work-around before API tokens existed). Instead of using the login token, please generate an API token through the web-interface, which can be used in exactly the same way.

Thanks for feedback @brocaar I know you’re a busy guy!

I initially tried that way first, but I must of done it incorrectly… as the generated tokens in the webUI didn’t work. I think what I did was generated the API tokens then changed the JWT secret before i found the swagger API endpoint :joy: so everything generated wasn’t signed correctly.

Okay, I just deleted all my old API keys and created new ones with new tokens through the webUI and they work to access the API endpoints. I will do a quick writeup on the correct way to do this like above as well, I think it will be useful.

Is it best to use the WebUI token hard coded into any python scripts, rather then call for a token from the script and use that like the example above?

Correct, you generate a token through the web-interface and use that for your code :slight_smile:

hello,

is it possible that this stuff with /api/internal/login is no more available due to new software versions? I am not able to get a API token and it seems that all posts in the forum are out of date :frowning:

They are very much available in the latest versions.

Sorry my fault now i finally got my key.

it is definitely monday xD

2 Likes

Can the token be generated programmatically or can API keys only be generated through the web-interface?

Currently only through the API.

That’s a bit vague. When ChirpStack is started for the first time, must I use the web UI to generate an API key or can a RESTful call be made to generate the first API key?

Yes. There is nothing that the web UI does that isn’t available via the API(s). You do risk needing to update any use of /internal/* calls in the future, though.

What’s the recommended way of generating an API key through the API? Keys can’t be generated without another key unless it’s through /api/internal/login. Is using /internal/login the recommended method for generating the first key?

That’s what I do. As long as your development cycle is flexible enough to update if the endpoint changes in the future, I think you’re okay.