9.2 KiB
JLINC NodeJS SDK
The JLINC NodeJS SDK serves as a centralized vehicle for leveraging all aspects of the core JLINC protocol. This library will enable you to build client/server applications that leverage built-in secure identity management, agreement signing, and data exchange provided via the protocol.
Details of the JLINC protocol, schema, and context can be found at: https://protocol.jlinc.io/.
Installation
npm install @jlinc/sdk
Sample usage
The below code sample is a demonstration of the JLINC NodeJS SDK in action. As data moves through the system, it is cryptographically signed with a unique key for each element in the system, and zero-knowledge audit records are delivered to the JLINC Archive Server.
const {
jlincInit,
jlincProduceEvent,
jlincProcessEvent,
jlincProduceAgreement,
jlincProcessAgreement,
} = require("@jlinc/sdk");
async function main() {
const config = {
dataStoreApiUrl: process.env.JLINC_DATA_STORE_API_URL ?? "http://localhost:9090",
dataStoreApiKey: process.env.JLINC_DATA_STORE_API_KEY,
archiveApiUrl: process.env.JLINC_ARCHIVE_API_URL ?? "http://localhost:9090",
archiveApiKey: process.env.JLINC_ARCHIVE_API_KEY,
defaultAgreementId: "00000000-0000-0000-0000-000000000000",
systemPrefix: process.env.JLINC_SYSTEM_PREFIX ?? "TestJlinc",
debug: false,
}
jlincInit(config);
try {
let data;
let r;
// Define participants in this agreement and data exchange
const entity1 = `EntityOne`;
const entity2 = `EntityTwo`;
console.log(`\nAction: Produce (create and sign) agreement`)
data = {
uri: 'http://localhost:9090/agreements/05c93a30cc699cfaee9185f23a5f68ffb12305acce1ca4b9444758fc4d594828',
validRoles: ['provider', 'user'],
purposes: ['testing'],
caveats: ['production'],
requiredSigners: [entity1],
signer: entity1,
role: 'provider',
}
r = await jlincProduceAgreement(data)
if (r) {
if (printResults) {
console.log(`Result:`)
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.created && r.processed) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
const agreementId = r.created.agreementId
console.log(`\nAction: Process (cross sign) agreement`)
data = {
agreementId,
signer: entity2,
role: 'user',
}
r = await jlincProcessAgreement(data)
if (r) {
if (printResults) {
console.log(`Result:`)
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.auditData && r.auditData.audit.agreementId === agreementId) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
console.log(`\nAction: Produce (create and sign) event for data to be sent`)
data = {
from: entity1,
to: entity2,
agreementId,
payload: {
data: "testing",
},
}
r = await jlincProduceEvent(data)
if (r) {
if (printResults) {
console.log(`Result:`)
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.created && r.processed && r.created.agreementId === agreementId) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
const eventId = r.created.eventId;
console.log(`\nAction: Process (sign) by the receiver after data is sent`)
data = {
to: entity2,
eventId,
}
r = await jlincProcessEvent(data)
if (r) {
console.log(`Result:`)
if (printResults) {
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.auditData && r.auditData.audit.eventId === eventId) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
console.log(`\nAction: Produce (create and sign) event for data to be sent with successful auth`)
data = {
from: entity1,
to: entity2,
auth: {
subject: {
type: "user",
id: "tester",
},
action: {
name: "read",
},
resource: {
type: "data",
id: "1234",
properties: {
ownerID: "tester@test.com",
}
}
},
payload: {
data: "testing",
},
}
r = await jlincProduceEvent(data)
if (r) {
if (printResults) {
console.log(`Result:`)
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.created && r.processed) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
console.log(`\nAction: Produce (create and sign) event for data to be sent with failed auth`)
data = {
from: entity1,
to: entity2,
auth: {
subject: {
type: "user",
id: "tester",
},
action: {
name: "write",
},
resource: {
type: "data",
id: "1234",
properties: {
ownerID: "tester@test.com",
}
}
},
payload: {
data: "testing",
},
}
r = await jlincProduceEvent(data)
if (r) {
if (printResults) {
console.log(`Result:`)
console.log(`---------------------------------------------`)
console.log(JSON.stringify(r, null, 2))
console.log(`---------------------------------------------`)
}
if (r.decision != undefined && r.decision == false) {
console.log('PASS')
} else {
throw new Error('FAIL')
}
}
} catch (err) {
console.error("[*] ERROR:", err);
}
}
main()
API Reference
jlincInit(data: JLINCConfig)
Call jlincInit before using any other method. The configuration object supports the following properties:
| Key | Type | Default | Description |
|---|---|---|---|
dataStoreApiUrl |
string |
http://localhost:9090 |
Base URL for the data store API |
dataStoreApiKey |
string |
Bearer token for authenticating API requests | |
archiveApiUrl |
string |
http://localhost:9090 |
URL for the archive service |
archiveApiKey |
string |
API key for the archive service | |
systemPrefix |
string |
my-system |
(Optional) Prefix applied to all entity short names |
domain |
string |
Server Specified | (Optional) Default domain for entities. If not specified, it is auto-resolved on first call |
defaultAgreementId |
string |
00000000-0000-0000-0000-000000000000 |
(Optional) Default agreement ID for events |
debug |
boolean |
false |
(Optional) Enables verbose console logging for requests/responses |
jlincProduceAgreement(data: JLINCProduceAgreementData)
Creates and publishes a new agreement.
Parameters:
| Key | Type | Description |
|---|---|---|
requiredSigners |
Array<string> |
List of entities required to sign |
signer |
string |
The entity producing/signing this request |
uri |
string |
Resource URI the agreement applies to |
purposes |
Array<string> |
Allowed purposes under the agreement |
caveats |
Array<string> |
Prohibitions under the agreement |
validRoles |
Array<string> |
Allowed roles for the agreement |
role |
string |
The role being signing the agreement |
auth |
object |
(Optional) AuthZEN authentication data |
jlincProcessAgreement(data: JLINCProcessAgreementData)
Signs an existing agreement.
Parameters:
| Key | Type | Description |
|---|---|---|
agreementId |
string |
The ID of the agreement to process |
signer |
string |
The entity signing the agreement |
role |
string |
The role being signed on behalf of |
auth |
object |
(Optional) AuthZEN authentication data |
jlincProduceEvent(data: JLINCProduceEventData)
Creates and publishes a new event.
Parameters:
| Key | Type | Description |
|---|---|---|
from |
string |
The entity sending and signing the data |
to |
string |
The entity to receive the data |
agreementId |
string |
(Optional) Agreement ID. Falls back to defaultAgreementId if omitted |
payload |
any |
The data payload to send |
auth |
object |
(Optional) AuthZEN authentication data forwarded to the API |
jlincProcessEvent(data: JLINCProcessEventData)
Signs an existing agreement.
Parameters:
| Key | Type | Description |
|---|---|---|
to |
string |
The entity receiving and signing the data |
eventId |
string |
The ID of the event to process |
auth |
object |
(Optional) AuthZEN authentication data |