Skip to content

Commit

Permalink
feat(xapi): add support for Basic auth via meta_secret-lrs-payload
Browse files Browse the repository at this point in the history
Add support for Basic auth via meta_secret-lrs-payload.
The new supported payload format is:
  ```json
    {
      "lrs_endpoint": "https://lrs1.example.com",
      "lrs_username": "user",
      "lrs_password": "pass"
    }
  ```
Check the xAPI module's README for more information.
  • Loading branch information
prlanzarin committed Jun 6, 2024
1 parent 10a14c8 commit 148b6c4
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.

### UNRELEASED

* feat(xapi): add support for Basic auth via meta_secret-lrs-payload
* build: [email protected]

### v3.1.0
Expand Down
30 changes: 22 additions & 8 deletions src/out/xapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,28 @@ If you set `meta_xapi-enabled` to false, no xAPI events will be generated or sen

### meta_secret-lrs-payload
- **Description**: This parameter allows you to specify the credentials and endpoint of the Learning Record Store (LRS) where the xAPI events will be sent. The payload is a Base64-encoded string representing a JSON object encrypted (AES 256/PBKDF2) using the **server secret** as the **passphrase**.
- **Value Format**: Base64-encoded JSON object encrypted with AES 256/PBKDF2 encryption
- **JSON Payload Structure**:
```json
{
"lrs_endpoint": "https://lrs1.example.com",
"lrs_token": "AAF32423SDF5345"
}
```
There are two supported formats for the payload:

- **LRS Token (Bearer authentication)**
- **Value Format**: Base64-encoded JSON object encrypted with AES 256/PBKDF2 encryption
- **JSON Payload Structure**:
```json
{
"lrs_endpoint": "https://lrs1.example.com",
"lrs_token": "AAF32423SDF5345"
}
```
- **LRS Username/Password (Basic authentication)**
- **Value Format**: Base64-encoded JSON object encrypted with AES 256/PBKDF2 encryption
- **JSON Payload Structure**:
```json
{
"lrs_endpoint": "https://lrs1.example.com",
"lrs_username": "user",
"lrs_password": "pass"
}
```

- **Encrypting the Payload**: The Payload should be encrypted with the server secret using the following bash command (provided the lrs credential are in the `lrs.conf` file and server secret is `bab3fd92bcd7d464`):
```bash
cat ./lrs.conf | openssl aes-256-cbc -pass "pass:bab3fd92bcd7d464" -pbkdf2 -a -A
Expand Down
32 changes: 23 additions & 9 deletions src/out/xapi/xapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ export default class XAPI {
}

async postToLRS(statement, meeting_data) {
let { lrs_endpoint, lrs_username, lrs_password } = this.config.lrs;
if (meeting_data.lrs_endpoint !== ''){
lrs_endpoint = meeting_data.lrs_endpoint;
}
const lrs_username = meeting_data.lrs_username || this.config.lrs?.lrs_username;
const lrs_password = meeting_data.lrs_password || this.config.lrs?.lrs_password;
const lrs_endpoint = meeting_data.lrs_endpoint || this.config.lrs?.lrs_endpoint;
const lrs_token = meeting_data.lrs_token;
const headers = {
Authorization: `Basic ${Buffer.from(
Expand All @@ -52,9 +51,7 @@ export default class XAPI {
"X-Experience-API-Version": "1.0.0",
};

if (lrs_token !== ''){
headers.Authorization = `Bearer ${lrs_token}`
}
if (lrs_token) headers.Authorization = `Bearer ${lrs_token}`

const requestOptions = {
method: "POST",
Expand Down Expand Up @@ -107,15 +104,32 @@ export default class XAPI {
const lrs_payload = event.data.attributes.meeting.metadata?.["secret-lrs-payload"];
let lrs_endpoint = '';
let lrs_token = '';
let lrs_username = '';
let lrs_password = '';

// if lrs_payload exists, decrypts with the server secret and extracts lrs_endpoint and lrs_token from it
if (lrs_payload !== undefined){
const payload_text = decryptStr(lrs_payload, this.config.server.secret);
({lrs_endpoint, lrs_token} = JSON.parse(payload_text));
try {
const payload_text = decryptStr(lrs_payload, this.config.server.secret);
({
lrs_endpoint,
lrs_token,
lrs_username,
lrs_password,
} = JSON.parse(payload_text));
} catch (error) {
this.logger.error("OutXAPI.onEvent: invalid lrs_payload", {
error: error.stack,
lrs_payload
});
return reject(error);
}
}

meeting_data.lrs_endpoint = lrs_endpoint;
meeting_data.lrs_token = lrs_token;
meeting_data.lrs_username = lrs_username;
meeting_data.lrs_password = lrs_password;

const meeting_create_day = DateTime.fromMillis(
meeting_data.create_time
Expand Down

0 comments on commit 148b6c4

Please sign in to comment.