diff --git a/app/Model/AuthKey.php b/app/Model/AuthKey.php
index e1caa4e10..0cc354ec5 100644
--- a/app/Model/AuthKey.php
+++ b/app/Model/AuthKey.php
@@ -104,6 +104,12 @@ class AuthKey extends AppModel
if (isset($val['AuthKey']['allowed_ips'])) {
$results[$key]['AuthKey']['allowed_ips'] = JsonTool::decode($val['AuthKey']['allowed_ips']);
}
+ if (isset($val['AuthKey']['unique_ips'])) {
+ $results[$key]['AuthKey']['unique_ips'] = JsonTool::decode($val['AuthKey']['unique_ips']);
+ } else {
+ $results[$key]['AuthKey']['unique_ips'] = [];
+ }
+
}
return $results;
}
@@ -117,6 +123,13 @@ class AuthKey extends AppModel
$this->data['AuthKey']['allowed_ips'] = JsonTool::encode($this->data['AuthKey']['allowed_ips']);
}
}
+ if (isset($this->data['AuthKey']['unique_ips'])) {
+ if (empty($this->data['AuthKey']['unique_ips'])) {
+ $this->data['AuthKey']['unique_ips'] = null;
+ } else {
+ $this->data['AuthKey']['unique_ips'] = JsonTool::encode($this->data['AuthKey']['unique_ips']);
+ }
+ }
return true;
}
@@ -162,12 +175,24 @@ class AuthKey extends AppModel
$possibleAuthkeys = $this->find('all', [
'recursive' => -1,
- 'fields' => ['id', 'authkey', 'user_id', 'expiration', 'allowed_ips', 'read_only'],
+ 'fields' => ['id', 'authkey', 'user_id', 'expiration', 'allowed_ips', 'read_only', 'unique_ips'],
'conditions' => $conditions,
]);
$passwordHasher = $this->getHasher();
foreach ($possibleAuthkeys as $possibleAuthkey) {
- if ($passwordHasher->check($authkey, $possibleAuthkey['AuthKey']['authkey'])) {
+ if ($passwordHasher->check($authkey, $possibleAuthkey['AuthKey']['authkey'])) { // valid authkey
+ // store IP in db if not there yet
+ $remote_ip = $this->_remoteIp();
+ $update_db_ip = true;
+ if (is_array($possibleAuthkey['AuthKey']['unique_ips']) && in_array($remote_ip, $possibleAuthkey['AuthKey']['unique_ips'])) {
+ $update_db_ip = false; // IP already seen, skip saving in DB
+ } else { // first time an IP is seen for this API key
+ $possibleAuthkey['AuthKey']['unique_ips'][] = $remote_ip;
+ }
+ if ($update_db_ip) {
+ $this->save($possibleAuthkey);
+ }
+ // fetch user
$user = $this->User->getAuthUser($possibleAuthkey['AuthKey']['user_id']);
if ($user) {
$user = $this->setUserData($user, $possibleAuthkey);
diff --git a/app/View/AuthKeys/index.ctp b/app/View/AuthKeys/index.ctp
index 0fc6e0dd8..358434eeb 100644
--- a/app/View/AuthKeys/index.ctp
+++ b/app/View/AuthKeys/index.ctp
@@ -73,6 +73,10 @@
'name' => __('Allowed IPs'),
'data_path' => 'AuthKey.allowed_ips',
],
+ [
+ 'name' => __('Seen IPs'),
+ 'data_path' => 'AuthKey.unique_ips'
+ ]
],
'title' => empty($ajax) ? __('Authentication key Index') : false,
'description' => empty($ajax) ? __('A list of API keys bound to a user.') : false,
diff --git a/app/View/AuthKeys/view.ctp b/app/View/AuthKeys/view.ctp
index ff9c8262d..47ef91b17 100644
--- a/app/View/AuthKeys/view.ctp
+++ b/app/View/AuthKeys/view.ctp
@@ -48,7 +48,7 @@ echo $this->element('genericElements/SingleViews/single_view', [
'type' => 'custom',
'function' => function (array $data) {
if (is_array($data['AuthKey']['allowed_ips'])) {
- return implode("
", array_map('h', $data['AuthKey']['allowed_ips']));
+ return implode("
", array_map('h', $data['AuthKey']['allowed_ips']));
}
return __('All');
}
@@ -83,9 +83,14 @@ echo $this->element('genericElements/SingleViews/single_view', [
'requirement' => isset($keyUsage),
],
[
- 'key' => __('Unique IPs'),
- 'raw' => $uniqueIps,
- 'requirement' => isset($keyUsage),
+ 'key' => __('Seen IPs'),
+ 'type' => 'custom',
+ 'function' => function (array $data) {
+ if (is_array($data['AuthKey']['unique_ips'])) {
+ return implode("
", array_map('h', $data['AuthKey']['unique_ips']));
+ }
+ return '';
+ }
]
],
]);