Authentication Settings
The seven endpoints behind the second step, location and address checks asked beyond the password.
Overview
These seven endpoints decide what is asked beyond the password at sign-in: a second step, an extra check when someone arrives from an unfamiliar location, and another when they arrive from an unfamiliar address.
All three are set separately for clients and admins. Switching one side on leaves the other alone, so wanting both means sending both blocks.
Reference
Reading Two-Step Verification
Returns which second-step methods are on and who is asked for them.
curl 'https://panel.example.com/api/v1/admin/settings/security/two-factor' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/two-factor', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/two-factor');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The switches only bite while AT LEAST ONE method is on; read them together.
$tfa = Api::Settings()->GetTwoFactor()['data'];
$live = $tfa['admin'] === 1 && $tfa['authentications'] !== [];Writing Two-Step Verification
Writes the methods and who is asked for them.
curl -X PUT 'https://panel.example.com/api/v1/admin/settings/security/two-factor' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"authentications":["GoogleAuthenticator"],"admin":1,"show_popup":1}'const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/two-factor', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
authentications: ['GoogleAuthenticator'],
admin: 1,
show_popup: 1,
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/two-factor');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'authentications' => ['GoogleAuthenticator'],
'admin' => 1,
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The method list is written WHOLE: sending one while meaning to add turns the others off.
$tfa = Api::Settings()->GetTwoFactor()['data'];
$methods = $tfa['authentications'];
$methods[] = 'GoogleAuthenticator';
Api::Settings()->UpdateTwoFactor(['authentications' => array_unique($methods)]);Listing the Methods
Returns the second-step methods installed and which of them are on.
curl 'https://panel.example.com/api/v1/admin/settings/security/two-factor/methods' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/two-factor/methods', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/two-factor/methods');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Take the method keys from HERE: an invented key is ignored without a word.
$keys = array_column(Api::Settings()->GetTwoFactorMethods()['data'], 'key');Reading Location Verification
Returns what happens when someone signs in from an unfamiliar location.
curl 'https://panel.example.com/api/v1/admin/settings/security/location-verification' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/location-verification', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/location-verification');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The client and admin settings are INDEPENDENT: switching one on leaves the other alone.
$loc = Api::Settings()->GetLocationVerification()['data'];Writing Location Verification
Writes location verification, one side at a time.
curl -X PUT 'https://panel.example.com/api/v1/admin/settings/security/location-verification' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"client":{"status":1,"method":"email","type":"soft"}}'const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/location-verification', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
client: { status: 1, method: 'email', type: 'soft' },
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/location-verification');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'client' => ['status' => 1, 'method' => 'email', 'type' => 'soft'],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Resolving a location depends on the LOCATION MODULE: without one the check cannot work as expected.
$loc = Api::Settings()->GetLocalisation()['data'];
if ($loc['ip_module'] !== '') {
Api::Settings()->UpdateLocationVerification([
'client' => ['status' => 1, 'method' => 'email'],
]);
}Reading Address Verification
Returns what happens when someone signs in from an unfamiliar address.
curl 'https://panel.example.com/api/v1/admin/settings/security/ip-verification' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/ip-verification', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/ip-verification');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$ip = Api::Settings()->GetIpVerification()['data'];Writing Address Verification
Writes address verification, one side at a time.
curl -X PUT 'https://panel.example.com/api/v1/admin/settings/security/ip-verification' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"admin":{"status":1,"whitelist":"203.0.113.0/24"}}'const res = await fetch('https://panel.example.com/api/v1/admin/settings/security/ip-verification', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
admin: { status: 1, whitelist: '203.0.113.0/24' },
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/security/ip-verification');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'admin' => ['status' => 1, 'whitelist' => '203.0.113.0/24'],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The exempt list is REPLACED by what you send: read it first and append to it.
$ip = Api::Settings()->GetIpVerification()['data'];
Api::Settings()->UpdateIpVerification([
'admin' => [
'status' => 1,
'whitelist' => $ip['admin']['whitelist'] . "\n" . $myAddress,
],
]);Pitfalls
The client and admin switches only bite while at least one method is on. Turning the admin second step on with an empty method list changes nothing, yet the setting reads as on and you believe you are protected. Read them together.
The method list you send replaces the old one: sending one while meaning to add turns the others off. The second step users set up with those methods stops working at once. Read the current list and append to it.
Working out where a sign-in came from is the location module's job. With no module installed, or with its lookup failing, the check does not behave as you expect. Confirm the location module is chosen in the localisation settings before switching this on.
Switching address verification on for admins covers you as well. On a connection whose address changes, every sign-in asks for the extra check, and forgetting your own address on the exempt list can leave you in an awkward spot. The exempt list is also replaced by what you send, not merged.
The methods to switch on are named by the keys of installed modules, and those keys come from the methods endpoint. An unrecognised key is ignored without a word: the request looks successful while the method stays off. Confirm through the read endpoint afterwards.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.