SolarNode External Login - SolarNetwork/solarnetwork GitHub Wiki
This guide describes how you can provide credentials and log into SolarNode via a web API on SolarNode. This can be used to integrate the SolarNode GUI into another web application. See the SolarNode External Login Demo application that uses this API to try this out with your own node.
The external login process works like this:
- Request a login key for a specific user.
- Use the returned key data to AES encrypt the user's password.
- Log the user in using the encrypted password.
The AES-256 encryption algorithm is used, in CBC mode with PKCS#7 padding. This is a common and widely supported scheme.
The first step required is to generate a login key for the SolarNode user you want to log in as.
This is accomplished by performing a GET
request to the /pub/session/key
endpoint.
GET | /pub/session/key |
---|---|
username |
The SolarNode username to authenticate as. |
salt |
Exactly 12 bytes of random data, encoded into a Base64 string. |
For example:
/pub/session/key?username=example%40localhost&salt=LokLfTFaO1yj4MzK
This will return a standard SolarNetwork API response object, where the data
property is an object
with the following properties:
Property | Type | Description |
---|---|---|
iv |
string | Base64 encoded bytes used as the initialisation vector the AES cipher. |
key |
string | Base64 encoded key used to encrypt the password. |
{
"success": true,
"data": {
"iv": "9a9mFuAUCzatjL+jC5Gk8A==",
"key": "yP/cGXqvqtW4GMaqLULKIscryEw25umA8ahMkLtwEBU="
}
}
⚠️ Note: the key is only valid for a short amount of time. Each time you want to log in using this API, you must generate a new key and then call the/pub/session/login
endpoint immediately afterwards.
The next step is to encrypt the user's password using the AES-256 algorithm, in CBC mode with PKCS#7
padding. The iv
value returned from /pub/session/key
in the previous step (decoded from Base64)
is used as the AES initialisation vector, and the key
value (also decoded from Base64) is the key.
In pseudo-code, the process looks like this:
import { Base64Decode, Base64Encode, AESEncrypt } from "super-crypto-lib";
const username = "example@localhost";
const password = "supersecret";
// keyData is returned from the /pub/session/key API
const keyData = {iv:"9a9mFuAUCzatjL+jC5Gk8A==", key:"yP/cGXqvqtW4GMaqLULKIscryEw25umA8ahMkLtwEBU="};
// decode IV & key
const key = Base64Decode(keyData.key);
const iv = Base64Decode(keyData.iv);
// encrypt password
const encryptedPassword = Base64Encode(AESEncrypt(iv, key, password));
// now encryptedPassword == "RnUyxgKor9/63LKpQu2jSA=="
The final step is to log in. You'll need to pass the encrypted password generated in the previous step, and a "salted" username.
This is accomplished by performing a GET
request to the /pub/session/login
endpoint. Note
this endpoint will return HTML, and is designed to be loaded directly by a browser.
GET | /pub/session/login |
---|---|
username |
The same salt value previously passed to the /pub/session/key endpoint concatenated with the UTF-8 bytes of the SolarNode username to authenticate as, all encoded into a Base64 string. |
password |
The encrypted password as outlined in the previous section, encoded into a Base64 string. |
In pseudo-code, the process looks like this:
import { Base64Decode, Base64Encode, Utf8Bytes } from "super-crypto-lib";
// encryptedPassword calculated in previous section
const encryptedPassword == "RnUyxgKor9/63LKpQu2jSA==";
// same salt value as passed to /pub/session/key at start of this process
const salt = "LokLfTFaO1yj4MzK";
const username = "example@localhost";
const saltyUsername = Base64Encode(Base64Decode(salt).concat(Utf8Bytes(username)));
const loginUrl = "http://solarnode/pub/session/login?username="
+ encodeURIComponent(saltyUsername)
+ "&password="
+ encodeURIComponent(encryptedPassword);
Assuming the login credentials are correct, then you should have successfully logged into SolarNode at this point.