Skip to content

Commit

Permalink
Pvt key conversions and http errors (#12)
Browse files Browse the repository at this point in the history
* Update .env.sample

* Added functions for pvt key conversion. Handled errs for http requests. Updated readme

* Added Biscuit public key. Fixed DDL example.

* Added example files

* Axios vulnerability fix
  • Loading branch information
chilaraiSxt authored Nov 20, 2024
1 parent db2ec10 commit 82cdfe4
Show file tree
Hide file tree
Showing 15 changed files with 2,948 additions and 231 deletions.
4 changes: 2 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
BASEURL="https://<base_url>" # Space and Time Base API Endpoint before v1/v2
SCHEMA=ed25519
BASEURL_GENERAL="https://<base_url>" # Space and Time Base API Endpoint before v1/v2
SCHEME=ed25519
11 changes: 8 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
## SxT-NodeJS-SDK (v.2.0.7)

## SxT-NodeJS-SDK

JavaScript(NodeJS) SDK for Space and Time Gateway (javascript version >= 19.8.0)

Expand All @@ -17,6 +16,13 @@ or
yarn add sxt-nodejs-sdk
```

Then add the following environment values to your `.env` file

```sh
BASEURL_GENERAL="SXT_BASE_URL"
SCHEMA=ed25519
```

#### Working with source code

_Note: Before running the code, rename `.env.sample` to `.env` and ensure that your credentials are setup in the `.env` file properly_
Expand Down Expand Up @@ -219,7 +225,6 @@ const dropTable = await sqlAPI.DDL(`DROP TABLE ${resourceName}`, biscuitArray);
Discovery SDK calls need a user to be logged in.

```js

const discovery = sxt.DiscoveryAPI();

// List schemas
Expand Down
53 changes: 34 additions & 19 deletions dist/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,39 @@ const CheckExistingSession = async (sessionFilePath, sxt) => {
* Authentication process
*/
const AuthUtil = async (userId, sxt) => {
// Auth code
const authentication = sxt.Authentication();
const authCode = await authentication.GenerateAuthCode(userId);
// console.log("Auth Code", authCode.data.authCode);
// Check user
const userExists = await authentication.CheckUser(userId);
const authorization = sxt.Authorization();
if (!userExists.data) {
// Generate new key pair
const keyPair = await authorization.GenerateKeyPair();
keypair = keyPair;
try {
const authentication = sxt.Authentication();
const authorization = sxt.Authorization();
// Check user
const userExists = await authentication.CheckUser(userId);
if (!userExists.data) {
// Generate new key pair
const keyPair = await authorization.GenerateKeyPair();
keypair = keyPair;
}
else {
console.error("The user exists but you have misplaced the session.json and credentials.json files. Please create them in the root folder of the sdk. Example can be found here https://github.com/spaceandtimelabs/SxT-NodeJS-SDK/tree/main/dist/examples");
return undefined;
}
// Auth code
const authCode = await authentication.GenerateAuthCode(userId);
console.log("Auth Code", authCode.data, keypair);
if (typeof authCode.data === "undefined") {
console.log(authCode);
return undefined;
}
// Sign message
const sign = await authorization.GenerateSignature(authCode.data.authCode, keypair.privateKey_64);
console.log("Signature", sign.signature);
// Get access token
const accessToken = await authentication.GenerateToken(userId, authCode.data.authCode, sign.signature, keypair.publicKeyB64_32);
console.log("Access Token", accessToken);
return accessToken.data;
}
catch (e) {
console.log("ERR", e);
return undefined;
}
// Sign message
const sign = await authorization.GenerateSignature(new TextEncoder().encode(authCode.data.authCode), keypair.privateKey_64);
// console.log("Signature", sign.signature);
// Get access token
const accessToken = await authentication.GenerateToken(userId, authCode.data.authCode, sign.signature, keypair.publicKeyB64_32);
// console.log("Access Token", accessToken);
return accessToken.data;
};
/**
* Example
Expand Down Expand Up @@ -116,6 +130,7 @@ const SQLAPIUtil = async (sxt, keypair) => {
resource: resourceName,
biscuit: biscuit.data[0],
biscuitPrivateKeyHex_32: keypair.biscuitPrivateKeyHex_32,
biscuitPublicKeyHex_32: keypair.biscuitPublicKeyHex_32,
};
const storage = sxt.Storage();
storage.WriteCredentials(JSON.stringify(credentialsString), credentialsFilePath);
Expand All @@ -124,7 +139,7 @@ const SQLAPIUtil = async (sxt, keypair) => {
let resourceArray = [resourceName];
// SQL operations
// Create
const createTable = await sqlAPI.DDL(`CREATE TABLE ${resourceName} (id INT PRIMARY KEY, test VARCHAR)`, biscuitArray);
const createTable = await sqlAPI.DDL(`CREATE TABLE ${resourceName} (id INT PRIMARY KEY, test VARCHAR) WITH "public_key=${keypair.biscuitPublicKeyHex_32},access_type=public_append"`, biscuitArray);
// console.log("CREATE TABLE", createTable);
// Insert
const insertData = await sqlAPI.DML(`INSERT INTO ${resourceName} VALUES (5, 'x5')`, biscuitArray, resourceArray);
Expand Down
37 changes: 35 additions & 2 deletions dist/src/authorization/authorization.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default class Authorization {
privateKeyB64_64: Buffer.from(secretKey).toString("base64"),
publicKeyB64_32: Buffer.from(publicKey).toString("base64"),
biscuitPrivateKeyHex_32: Buffer.from(trimmedSecretKey).toString("hex"),
biscuitPublicKeyHex_32: Buffer.from(publicKey).toString("hex"),
};
};
// Generate Ed25519 keypair from provided string
Expand All @@ -49,16 +50,48 @@ export default class Authorization {
privateKeyB64_64: keypair.privateKeyB64_64,
publicKeyB64_32: keypair.publicKeyB64_32,
biscuitPrivateKeyHex_32: keypair.biscuitPrivateKeyHex_32,
biscuitPublicKeyHex_32: keypair.biscuitPublicKeyHex_32,
};
};
// Generate signature
this.GenerateSignature = async (authCode, privkey) => {
const signatureArray = nacl.sign(authCode, privkey);
this.GenerateSignature = async (authCode, privKey) => {
// Ensure inputs are Uint8Array
const message = new TextEncoder().encode(authCode); // Convert authCode to Uint8Array
const privateKey = Uint8Array.from(Buffer.from(privKey, "hex")); // Convert privKey (hex string) to Uint8Array
// Generate signature
const signatureArray = nacl.sign(message, privateKey);
let signature = Buffer.from(signatureArray.buffer, signatureArray.byteOffset, signatureArray.byteLength).toString("hex");
signature = signature.slice(0, 128);
return {
signature: signature,
};
};
// Convert private-key-64-bytes to private-key-32-bytes
// input is base64 encoded private key
this.ConvertKey64To32 = (pvtKey) => {
const pvtBinaryString = atob(pvtKey);
const bytes = new Uint8Array(pvtBinaryString.length);
for (let i = 0; i < pvtBinaryString.length; i++) {
bytes[i] = pvtBinaryString.charCodeAt(i);
}
const pvtkey32 = bytes.slice(0, 32);
return Buffer.from(pvtkey32).toString("base64");
};
// Convert private-key-32-bytes to private-key-64-bytes
// input strings are base64 encoded
this.ConvertKey32To64 = (pvtKey, pubKey) => {
const pvtBinaryString = atob(pvtKey);
const pvtBytes = new Uint8Array(pvtBinaryString.length);
for (let i = 0; i < pvtBinaryString.length; i++) {
pvtBytes[i] = pvtBinaryString.charCodeAt(i);
}
const pubBinaryString = atob(pubKey);
const pubBytes = new Uint8Array(pubBinaryString.length);
for (let i = 0; i < pubBinaryString.length; i++) {
pubBytes[i] = pubBinaryString.charCodeAt(i);
}
const mergedPvtKey = new Uint8Array([...pvtBytes, ...pubBytes]);
return Buffer.from(mergedPvtKey).toString("base64");
};
}
}
2 changes: 1 addition & 1 deletion dist/src/helpers/queryhelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const QueryHelper = async (options, httpOk = 0) => {
}
catch (err) {
output = {
error: new Error(`${err.response.status}: ${err.response.data.title}. Detail: ${err.response.data.detail}`),
error: err,
};
}
return output;
Expand Down
1 change: 0 additions & 1 deletion dist/tests/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ describe("Check if user exists", () => {
it("should return true", async () => {
const auth = new Authentication();
const check = await auth.CheckUser("test-trial-1");
console.log(check);
assert.equal(check.data, true);
});
});
9 changes: 9 additions & 0 deletions examples/credentials_sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"userid": "SOME_RANDOM_USERID",
"privateKeyB64_64": "SAMPLE_w1lcWOZOdYDBwhCUnm1pkMhZi8D0Yuuh+8NCVoMZkolJEEH1lVNJpJtayo/hGQO/7NlIBdpYZj3QT5FfjvYFA==",
"publicKeyB64_32": "SAMPLE_SRBB9ZVTSaSbWsqP4RkDv+zZSAXaWGY90E+RX472BQ=",
"resource": "ETHEREUM.TRANSACTIONS",
"biscuit": "SAMPLE_twCCvEBCg5zeHQ6Y2FwYWJpbGl0eQoKZGRsX2NyZWF0ZQoVRVRIRVJFVU0uVFJBTlNBQ1RJT05TCghkZGxfZHJvcAoJZGRsX2FsdGVyCgpkbWxfaW5zZXJ0CgpkbWxfZGVsZXRlCgpkbWxfdXBkYXRlCgpkcWxfc2VsZWN0GAMiDwoNCIAIEgMYgQgSAxiCCCIPCg0IgAgSAxiDCBIDGIIIIg8KDQiACBIDGIQIEgMYgggiDwoNCIAIEgMYhQgSAxiCCCIPCg0IgAgSAxiGCBIDGIIIIg8KDQiACBIDGIcIEgMYgggiDwoNCIAIEgMYiAgSAxiCCBIkCAASIOMZrCZZrup2nz_XRgQWD5EtNGm51vPiGN6-OdDhEHIxGkCCCIRKKwtyd3qPU8yE_xOJwnKvVxXHrdjh6__G-y6H3J2gcoCzxwxix1A4XGtzmxOHl4C4fR4gFhrioXskX2wDIiIKIAptVyvBaTrQtFCLqOghUjDNa0BFX9hxv9lbWmMmqEas",
"biscuitPrivateKeyHex_32": "SAMPLE_f0d6571639939d6030708425279b5a64321662f03d18bae87ef0d095a0c664a",
"biscuitPublicKeyHex_32": "SAMPLE_5244107d6554d26926d6b2a3f84640effb3652017696198f7413e457e3bd814"
}
74 changes: 45 additions & 29 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,38 +44,53 @@ const CheckExistingSession = async (
* Authentication process
*/
const AuthUtil = async (userId: string, sxt: any): Promise<any> => {
// Auth code
const authentication = sxt.Authentication();
try {
const authentication = sxt.Authentication();
const authorization = sxt.Authorization();

const authCode = await authentication.GenerateAuthCode(userId);
// console.log("Auth Code", authCode.data.authCode);
// Check user
const userExists = await authentication.CheckUser(userId);

// Check user
const userExists = await authentication.CheckUser(userId);
if (!userExists.data) {
// Generate new key pair
const keyPair = await authorization.GenerateKeyPair();
keypair = keyPair;
} else {
console.error(
"The user exists but you have misplaced the session.json and credentials.json files. Please create them in the root folder of the sdk. Example can be found here https://github.com/spaceandtimelabs/SxT-NodeJS-SDK/tree/main/examples"
);
return undefined;
}

const authorization = sxt.Authorization();
if (!userExists.data) {
// Generate new key pair
const keyPair = await authorization.GenerateKeyPair();
keypair = keyPair;
}
// Auth code
const authCode = await authentication.GenerateAuthCode(userId);
console.log("Auth Code", authCode.data, keypair);

// Sign message
const sign = await authorization.GenerateSignature(
new TextEncoder().encode(authCode.data.authCode),
keypair.privateKey_64
);
// console.log("Signature", sign.signature);

// Get access token
const accessToken = await authentication.GenerateToken(
userId,
authCode.data.authCode,
sign.signature,
keypair.publicKeyB64_32
);
// console.log("Access Token", accessToken);
return accessToken.data;
if (typeof authCode.data === "undefined") {
console.log(authCode);
return undefined;
}

// Sign message
const sign = await authorization.GenerateSignature(
authCode.data.authCode,
keypair.privateKey_64
);
console.log("Signature", sign.signature);

// Get access token
const accessToken = await authentication.GenerateToken(
userId,
authCode.data.authCode,
sign.signature,
keypair.publicKeyB64_32
);
console.log("Access Token", accessToken);
return accessToken.data;
} catch (e) {
console.log("ERR", e);
return undefined;
}
};

/**
Expand Down Expand Up @@ -159,6 +174,7 @@ const SQLAPIUtil = async (sxt: any, keypair: any): Promise<Boolean> => {
resource: resourceName,
biscuit: biscuit.data[0],
biscuitPrivateKeyHex_32: keypair.biscuitPrivateKeyHex_32,
biscuitPublicKeyHex_32: keypair.biscuitPublicKeyHex_32,
};

const storage = sxt.Storage();
Expand All @@ -175,7 +191,7 @@ const SQLAPIUtil = async (sxt: any, keypair: any): Promise<Boolean> => {
// SQL operations
// Create
const createTable = await sqlAPI.DDL(
`CREATE TABLE ${resourceName} (id INT PRIMARY KEY, test VARCHAR)`,
`CREATE TABLE ${resourceName} (id INT PRIMARY KEY, test VARCHAR) WITH "public_key=${keypair.biscuitPublicKeyHex_32},access_type=public_append"`,
biscuitArray
);
// console.log("CREATE TABLE", createTable);
Expand Down
6 changes: 6 additions & 0 deletions examples/session_sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"accessToken": "SAMPLE_eyJ0eXBlIjoiYWNjZXNzIiwia2lkIjoiZTUxNDVkYmQtZGNmYi00ZjI4LTg3NzItZjVmNjNlMzcwM2JlIiwiYWxnIjoiRVMyNTYifQ.eyJpYXQiOjE3MzIxMjAxNjgsIm5iZiI6MTczMjEyMDE2OCwiZXhwIjoxNzMyMTIxNjY4LCJ0eXBlIjoiYWNjZXNzIiwidXNlciI6ImNoaWxhcmFpLXByb2QxMDEiLCJzZXNzaW9uIjoiMTI4MWE5NmNmNTNjMzNlOGU1MjlkNzU1Iiwic3NuX2V4cCI6MTczMjIwNjU2ODgzNCwiaXRlcmF0aW9uIjoiNjNiNmViOWZmMTJmNzBhZGVmMjVmZjg2IiwidHJpYWwiOnRydWV9.XyRnDPjqo1qqHDJy5p2hASwXZR2CMr_CXVaxJ28bxJX9NqC_7nzp3sCqNCFO0ZskdIZaNpPxMf_VXosTKpGTAA",
"refreshToken": "SAMPLE_eyJ0eXBlIjoicmVmcmVzaCIsImtpZCI6ImU1MTQ1ZGJkLWRjZmItNGYyOC04NzcyLWY1ZjYzZTM3MDNiZSIsImFsZyI6IkVTMjU2In0.eyJpYXQiOjE3MzIxMjAxNjgsIm5iZiI6MTczMjEyMDE2OCwiZXhwIjoxNzMyMTIxOTY4LCJ0eXBlIjoicmVmcmVzaCIsInVzZXIiOiJjaGlsYXJhaS1wcm9kMTAxIiwic2Vzc2lvbiI6IjEyODFhOTZjZjUzYzMzZThlNTI5ZDc1NSIsInNzbl9leHAiOjE3MzIyMDY1Njg4MzQsIml0ZXJhdGlvbiI6IjYzYjZlYjlmZjEyZjcwYWRlZjI1ZmY4NiIsInRyaWFsIjp0cnVlfQ.wo1wsJWQz9OlvPwFjMqr7GzYjSt1h4qpeFn-9jeCdp82qhVCkyEitJ27nateUXT2ZZ5qUfuV-lWRiKAwdbJo0A",
"accessTokenExpires": 1732121668835,
"refreshTokenExpires": 1732121968835
}
Loading

0 comments on commit 82cdfe4

Please sign in to comment.