Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • perun/perun-proxyidp/simplesamlphp-module-campusmultiauth
1 result
Show changes
Commits on Source (5)
# [2.1.0](https://gitlab.ics.muni.cz/perun-proxy-aai/simplesamlphp/simplesamlphp-module-campusmultiauth/compare/v2.0.0...v2.1.0) (2022-12-01)
### Features
* security texts ([f521d10](https://gitlab.ics.muni.cz/perun-proxy-aai/simplesamlphp/simplesamlphp-module-campusmultiauth/commit/f521d103130d9d0e64cd97b18ef7efb5c20f06d7))
# [2.0.0](https://gitlab.ics.muni.cz/perun-proxy-aai/simplesamlphp/simplesamlphp-module-campusmultiauth/compare/v1.5.0...v2.0.0) (2022-11-07)
......
......@@ -173,21 +173,23 @@ In addition to the remember me function, you can turn on security images. Image
`showFreshImage` - if set to true, the security image is fetched everytime user access the login page. Otherwise, it is stored in the cookie. Default `false`.
`storageClass` - an implementation of `SimpleSAML\Module\campusmultiauth\Data\Storage`, default `SimpleSAML\Module\campusmultiauth\Data\DatabaseStorage`.
`pictureStorage` - if some other storage than `SimpleSAML\Module\campusmultiauth\Data\DatabaseStorage` is used (e.g. `SimpleSAML\Module\campusmultiauth\Data\PerunStorage`), this is the place for the configuration of the storage.
`security.cookie.path` - cookie path.
`security.cookie.samesite` - cookie SameSite.
`pictureDir` - if set, the security image is stored in this directory instead of the cookie. The cookie than contains only a link to the picture. Also, if this option is enabled, `securityImageSalt` and `pictureBaseURL` are mandatory. Default `null`.
`securityImageSalt` - a salt which is used in the filename of the picture if the `pictureDir` is on.
`pictureBaseURL` - base URL to the pictures if the `pictureDir` is on.
`storageClass` - an implementation of `SimpleSAML\Module\campusmultiauth\Data\Storage`, default `SimpleSAML\Module\campusmultiauth\Data\DatabaseStorage`.
`pictures_table` - name of the table with security images, default `security_image`.
`pictureStorage` - if some other storage than `SimpleSAML\Module\campusmultiauth\Data\DatabaseStorage` is used (e.g. `SimpleSAML\Module\campusmultiauth\Data\PerunStorage`), this is the place for the configuration of the storage.
`security.cookie.path` - cookie path.
`security.cookie.samesite` - cookie SameSite.
`texts_table` - default `alternative_text`. You can also add an alternative text to images. User can specify his/her own text, so this is an additional antiphishing feature. If user does not have the alternative text set, the alt is an empty string. In case he/she does not have the image set, this text will be displayed instead of it.
## Hinting
......
......@@ -626,25 +626,25 @@
},
{
"name": "nette/schema",
"version": "v1.2.2",
"version": "v1.2.3",
"source": {
"type": "git",
"url": "https://github.com/nette/schema.git",
"reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df"
"reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/schema/zipball/9a39cef03a5b34c7de64f551538cbba05c2be5df",
"reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df",
"url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
"reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
"shasum": ""
},
"require": {
"nette/utils": "^2.5.7 || ^3.1.5 || ^4.0",
"php": ">=7.1 <8.2"
"php": ">=7.1 <8.3"
},
"require-dev": {
"nette/tester": "^2.3 || ^2.4",
"phpstan/phpstan-nette": "^0.12",
"phpstan/phpstan-nette": "^1.0",
"tracy/tracy": "^2.7"
},
"type": "library",
......@@ -682,9 +682,9 @@
],
"support": {
"issues": "https://github.com/nette/schema/issues",
"source": "https://github.com/nette/schema/tree/v1.2.2"
"source": "https://github.com/nette/schema/tree/v1.2.3"
},
"time": "2021-10-15T11:40:02+00:00"
"time": "2022-10-13T01:24:26+00:00"
},
{
"name": "nette/utils",
......@@ -4311,16 +4311,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
......@@ -4335,7 +4335,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4373,7 +4373,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
......@@ -4389,20 +4389,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
......@@ -4414,7 +4414,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4454,7 +4454,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
......@@ -4470,20 +4470,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
......@@ -4495,7 +4495,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4538,7 +4538,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
......@@ -4554,20 +4554,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
......@@ -4582,7 +4582,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4621,7 +4621,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
......@@ -4637,20 +4637,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
......@@ -4659,7 +4659,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4697,7 +4697,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
......@@ -4713,20 +4713,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"shasum": ""
},
"require": {
......@@ -4735,7 +4735,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4776,7 +4776,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
},
"funding": [
{
......@@ -4792,20 +4792,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
......@@ -4814,7 +4814,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4859,7 +4859,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
......@@ -4875,20 +4875,20 @@
"type": "tidelift"
}
],
"time": "2022-05-10T07:21:04+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
"shasum": ""
},
"require": {
......@@ -4897,7 +4897,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
......@@ -4938,7 +4938,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
},
"funding": [
{
......@@ -4954,7 +4954,7 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/routing",
......
......@@ -140,6 +140,7 @@ $config = [
// 'ldap.basedn' => '',
// 'search.filter' => '',
// 'attribute' => '',
// 'alternative_text_attribute' => '',
// ],
],
// 'uidName' => '',
......
......@@ -203,6 +203,7 @@ class RememberMe extends ProcessingFilter
if (!$this->showFreshImage) {
$payload['security_image'] = Utils::getSecurityImageOfUser($username);
$payload['alternative_text'] = Utils::getAlternativeTextOfUser($username);
}
$this->setCookie($payload);
......
......@@ -22,6 +22,11 @@ class DatabaseStorage implements Storage
*/
private $pictures_table;
/**
* DB table name for texts.
*/
private $texts_table;
/**
* DB table name for tokens.
*/
......@@ -48,9 +53,13 @@ class DatabaseStorage implements Storage
$imagesConfiguration = $this->config->getConfigItem('security_images', []);
$this->db = Database::getInstance($this->config->getConfigItem('store', []));
$this->pictures_table = $this->db->applyPrefix(
$imagesConfiguration->getString('pictures_table', 'security_image')
);
$this->texts_table = $this->db->applyPrefix(
$imagesConfiguration->getString('texts_table', 'alternative_text')
);
$this->tokens_table = $this->db->applyPrefix(
$this->config->getString('tokens_table', 'cookie_counter')
);
......@@ -61,17 +70,17 @@ class DatabaseStorage implements Storage
*/
public function getSecurityImageOfUser(string $uid): ?string
{
$query = 'SELECT picture FROM ' . $this->pictures_table
. ' WHERE ' . self::UID_COL . '=:userid';
$statement = $this->db->read($query, [
'userid' => $uid,
]);
$picture = $statement->fetchColumn();
if ($picture === false) {
return null;
}
$query = 'SELECT picture FROM ' . $this->pictures_table . ' WHERE ' . self::UID_COL . '=:userid';
return $this->getSecurityAttributeOfUser($uid, $query);
}
return $picture;
/**
* @override
*/
public function getAlternativeTextOfUser(string $uid): ?string
{
$query = 'SELECT alternative_text FROM ' . $this->texts_table . ' WHERE ' . self::UID_COL . '=:userid';
return $this->getSecurityAttributeOfUser($uid, $query);
}
/**
......@@ -140,4 +149,18 @@ class DatabaseStorage implements Storage
return (bool) $this->db->write($query, $params);
}
private function getSecurityAttributeOfUser(string $uid, string $query)
{
$statement = $this->db->read($query, [
'userid' => $uid,
]);
$attribute = $statement->fetchColumn();
if ($attribute === false) {
return null;
}
return $attribute;
}
}
......@@ -59,11 +59,25 @@ class PerunStorage extends DatabaseStorage
* @override
*/
public function getSecurityImageOfUser(string $uid): ?string
{
$attribute = $this->config->getString('attribute', null);
return $attribute === null ? null : $this->getSecurityAttributeOfUser($uid, $attribute);
}
/**
* @override
*/
public function getAlternativeTextOfUser(string $uid): ?string
{
$attribute = $this->config->getString('alternative_text_attribute', null);
return $attribute === null ? null : $this->getSecurityAttributeOfUser($uid, $attribute);
}
private function getSecurityAttributeOfUser(string $uid, string $attribute)
{
$base = $this->config->getString('ldap.basedn');
$filter = $this->config->getString('search.filter');
$filter = str_replace('%uid%', $uid, $filter);
$attribute = $this->config->getString('attribute');
try {
$entries = $this->ldap->searchformultiple([$base], $filter, [$attribute], [], true, false);
......
......@@ -13,6 +13,11 @@ interface Storage
*/
public function getSecurityImageOfUser(string $uid): ?string;
/**
* Null if user has none, text otherwise.
*/
public function getAlternativeTextOfUser(string $uid): ?string;
/**
* False if not found (should not happen), counter otherwise.
*/
......
......@@ -29,4 +29,15 @@ class Utils
return $storage->getSecurityImageOfUser($username);
}
public static function getAlternativeTextOfUser($username)
{
$storage = self::getInterfaceInstance(
'SimpleSAML\\Module\\campusmultiauth\\Data\\Storage',
'storageClass',
'SimpleSAML\\Module\\campusmultiauth\\Data\\DatabaseStorage'
);
return $storage->getAlternativeTextOfUser($username);
}
}
......@@ -13,7 +13,9 @@
</h4>
{% if securityImage is defined %}
<img src='{{ securityImage|escape }}' class='security-image' alt=''>
<img src='{{ securityImage|escape('html_attr') }}' class='security-image' alt='{{ alternativeText|default('')|escape('html_attr') }}'>
{% elseif alternativeText is defined %}
<p class="security-image-text">{{ alternativeText|escape }}</p>
{% endif %}
{% if wrongUserPass == true %}
......
......@@ -343,14 +343,21 @@ if ($t->data['userInfo']) {
if (empty($t->data['username']) || $t->data['userInfo']['username'] === $t->data['username']) {
$t->data['username'] = $t->data['userInfo']['username'];
$showFreshImage = $imagesConfig->getBoolean('showFreshImage', false);
if ($showFreshImage && (($t->data['userInfo']['security_image'] ?? true) !== false)) {
$t->data['securityImage'] = Utils::getSecurityImageOfUser($t->data['userInfo']['username']);
} elseif (!$showFreshImage && !empty($t->data['userInfo']['security_image'])) {
$t->data['securityImage'] = $t->data['userInfo']['security_image'];
}
if ($showFreshImage && (($t->data['userInfo']['alternative_text'] ?? true) !== false)) {
$t->data['alternativeText'] = Utils::getAlternativeTextOfUser($t->data['userInfo']['username']);
} elseif (!$showFreshImage && !empty($t->data['userInfo']['alternative_text'])) {
$t->data['alternativeText'] = $t->data['userInfo']['alternative_text'];
}
$pictureDir = $imagesConfig->getString('pictureDir', null);
if ($t->data['securityImage'] && $pictureDir !== null) {
if (!empty($t->data['securityImage']) && $pictureDir !== null) {
$pictureDataSrc = $t->data['securityImage'];
if (preg_match('~^data:image/(png|jpeg|gif);base64,(.*)$~', $pictureDataSrc, $matches)) {
list(, $pictureType, $pictureContent) = $matches;
......