The Elearning Community • API - Authentication API
Page 1 of 2

API - Authentication API

Posted: Sun Jun 15, 2025 8:19 am
by zaff
Hi,

I have been following the API documentation. Now there are two sections for authentication. The first talks about
1. Authentication API - For Restful API, use key and secret, and develop X-authorization. I changed API settings to choose the secret and key auth method in the admin section for this.
2. The second section (in documentation) talks of /api/auth/authenticate using username and password.
My focus is in using the key and secret (key and secret). However, when I use the code below, it keeps telling me that "token could not be established" [not the exact phrase]. However, when I removed X-authorization (meaning the $codice and X-authorization from the code) and in the formalms admin setting chose token-based auth method. It worked, returning me a "success" and also a token.
But I don't intend to use token-based authorization.

And later, as I tinkered with the code, I realized that in the code (API folder), the code doesn't tell what needs to be done if the auth method is secret & Key, but does tell what should be done if the auth method is token type (i.e. generate token). [Not sure if I missed anything in the code that actually directs what needs to be done for key & secret based auth code]

What I want to do is I want to authenticate using key and secret using the X-authorizatoin as discussed in the documentation. Please help.

The code I used is below, which does not give me success for key and secret based authorization (but provides me token and success if removed the section on "Generating auth code" and X-authorizatoin .

<?php
// Only handle POST if form is submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username'], $_POST['password'])) {
// Basic input sanitization
$user = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$pass = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

// Replace with your actual API credentials
$key = 'key';
$secret = 'key_secret';
$api_url = 'https://mydomain.com/api/rest.php?q=/ap ... thenticate';

// Generate auth code
$params = [$user, $pass];
$sha1_hash = strtolower(sha1(implode(',', $params) . ',' . $secret));
$auth_code = base64_encode($key . ':' . $sha1_hash);

// Build POST request with cURL
$post_fields = http_build_query([
'username' => $user,
'password' => $pass
]);

$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Accept: application/xml",
"Content-Type: application/x-www-form-urlencoded",
"X-Authorization: FormaLMS $auth_code"
]);

$response = curl_exec($ch);

if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}

curl_close($ch);

// Display results

Re: API - Authentication API

Posted: Sun Jun 15, 2025 9:43 am
by alfa24
Forma version?

Re: API - Authentication API

Posted: Sun Jun 15, 2025 2:30 pm
by alfa24
Regardless of your forma version, I think your answer is in the auth calc when _AUTH_SECRET_KEY is set in /api/lib/lib.api.php checkAuthentication function.
In checkKeys function you'll find how params are expected to be passed:

$auth = base64_decode(str_replace('FormaLMS ', '', $_SERVER['HTTP_X_AUTHORIZATION']));
$params_to_check = $this->getValuesFromParams($params);

$hash_sha1 = sha1(implode(',', $params_to_check) . ',' . FormaLms\lib\Get::sett('rest_auth_api_secret', ''));

// check if the two hashes match each other
if (strtolower($auth) != strtolower(FormaLms\lib\Get::sett('rest_auth_api_key', '') . ':' . $hash_sha1)) {
$result['success'] = false;
$result['message'] = 'Api Key or Secret not valid';
}

So you should first of all ensure passing a base64_encoded $_SERVER['HTTP_X_AUTHORIZATION'].
This code should be equals to strtolower(FormaLms\lib\Get::sett('rest_auth_api_key', '') . ':' . $hash_sha1), where $hash_sha1 = sha1(implode(',', $params_to_check) . ',' . FormaLms\lib\Get::sett('rest_auth_api_secret', ''))

Re: API - Authentication API

Posted: Sun Jun 15, 2025 5:24 pm
by zaff
I have seen the code earlier too in code base i.e. -
$auth = base64_decode(str_replace('FormaLMS ', '', $_SERVER['HTTP_X_AUTHORIZATION']));
$params_to_check = $this->getValuesFromParams($params);
$hash_sha1 = sha1(implode(',', $params_to_check) . ',' . FormaLms\lib\Get::sett('rest_auth_api_secret', ''));
// check if the two hashes match each other
if (strtolower($auth) != strtolower(FormaLms\lib\Get::sett('rest_auth_api_key', '') . ':' . $hash_sha1)) {
$result['success'] = false;
$result['message'] = 'Api Key or Secret not valid';
}

I have used it my code too. My question is why isn't it hitting the endpoint that leads to the above code. It is going to the code that provides tokens. I am not sure if my code standards are as per Formalms requirements is right , is it I am missing some basics of documentation or is the API end point (Below) correct? Sharing my code below

<?php
// Only handle POST if form is submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username'], $_POST['password'])) {
// Basic input sanitization
$user = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$pass = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

// Replace with your actual API credentials
$key = 'key';
$secret = 'key_secret';
$api_url = 'https://mydomain.com/api/rest.php?q=/ap ... thenticate';

// Generate auth code
$params = [$user, $pass];
$sha1_hash = strtolower(sha1(implode(',', $params) . ',' . $secret));
$auth_code = base64_encode($key . ':' . $sha1_hash);

// Build POST request with cURL
$post_fields = http_build_query([
'username' => $user,
'password' => $pass
]);

$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Accept: application/xml",
"Content-Type: application/x-www-form-urlencoded",
"X-Authorization: FormaLMS $auth_code"
]);

$response = curl_exec($ch);

if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}

curl_close($ch);

// Display results

Re: API - Authentication API

Posted: Sun Jun 15, 2025 5:24 pm
by zaff
Forma version is above 3.0

Re: API - Authentication API

Posted: Sun Jun 15, 2025 7:30 pm
by zaff
My end point is
https://mydomain.com/api/rest.php?q=/api/auth/authenticate

This end point takes me to the server code that produces tokens. I am wondering am I missing the right endpoint that should take me to the code (you shared from api/lib/lib.api.php). The documentation doesn't mention the end point. Or am I missing a important structural code requirement. Please help

Re: API - Authentication API

Posted: Sun Jun 15, 2025 7:41 pm
by alfa24
The endpoint is correct.
I don't understand exactly what is not working.
I use a layer (class) I constructed myself, and I suggest you to do the same.
Then you should provide the code in a readable format and the response as well, so I can help to figure out what you're missing.

Re: API - Authentication API

Posted: Mon Jun 16, 2025 4:24 am
by zaff
Thanks Alfa24. The entire code with response is provided below -

As I said earlier if I remove ""X-Authorization: FormaLMS $auth_code"" section (From header) and the section of "// Replace with your actual API credentials" from the code below- it automatically releases tokens with success, but thats not what I am looking for.


<?php
// Only handle POST if form is submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username'], $_POST['password'])) {
// Basic input sanitization
$user = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$pass = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

// Replace with your actual API credentials
$key = 'key';
$secret = 'key_secret';
$api_url = 'https://mydomain.com/api/rest.php?q=/api/auth/authenticate';

// Generate auth code
$params = [$user, $pass];
$sha1_hash = strtolower(sha1(implode(',', $params) . ',' . $secret));
$auth_code = base64_encode($key . ':' . $sha1_hash);

// Build POST request with cURL
$post_fields = http_build_query([
'username' => $user,
'password' => $pass
]);

$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Accept: application/xml",
"Content-Type: application/x-www-form-urlencoded",
"X-Authorization: FormaLMS $auth_code"
]);

$response = curl_exec($ch);

if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}

curl_close($ch);

// Display results
echo '<div style="margin-top:20px;">';
if (isset($error_msg)) {
echo '<p style="color:red;">API request failed: ' . htmlspecialchars($error_msg) . '</p>';
} elseif ($response) {
$xml = simplexml_load_string($response);
if ($xml && $xml->success == 'true') {
echo '<p style="color:green;">Login successful!</p>';
echo '<p><strong>Token:</strong> ' . htmlspecialchars($xml->token) . '</p>';
echo '<p><strong>Expires At:</strong> ' . htmlspecialchars($xml->expire_at) . '</p>';
// You can store token in session or redirect here
} else {
echo '<p style="color:red;">Login failed: ' . htmlspecialchars($xml->message ?? 'Invalid response.') . '</p>';
}
} else {
echo '<p style="color:red;">Empty response from API.</p>';
}
echo '</div>';
}
?>

<!DOCTYPE html>
<html>
<head>
<title>FormaLMS Login</title>
</head>
<body>
<h2>Login to FormaLMS</h2>
<form method="post">
<label for="username">User ID:</label>
<input type="text" name="username" id="username" required />
<br><br>
<label for="password">Password:</label>
<input type="password" name="password" id="password" required />
<br><br>
<button type="submit">Login</button>
</form>
</body>
</html>

Re: API - Authentication API

Posted: Mon Jun 16, 2025 4:37 am
by alfa24
You MUST provide the x-Authorization header.
You can't remove it.

Re: API - Authentication API

Posted: Mon Jun 16, 2025 4:53 pm
by zaff
What should be the api end point ?