Skip to content
Snippets Groups Projects
Verified Commit 06305649 authored by Pavel Vyskočil's avatar Pavel Vyskočil
Browse files

feat: allow filter out acrs by prefix

parent b223ef15
No related branches found
No related tags found
1 merge request!61feat: allow filter out acrs by prefix
Pipeline #643592 passed
...@@ -85,6 +85,7 @@ Add an instance of the auth proc filter with example configuration `authswitcher ...@@ -85,6 +85,7 @@ Add an instance of the auth proc filter with example configuration `authswitcher
[2] => 'example_entity_id2', [2] => 'example_entity_id2',
], ],
'setup_mfa_redirect_url' => 'mfa.id.muni.cz', 'setup_mfa_redirect_url' => 'mfa.id.muni.cz',
'prefixes_for_acrs_filtering' => ['prefix1', 'prefix2']
//'password_contexts' => array_merge(AuthSwitcher::PASSWORD_CONTEXTS, [ //'password_contexts' => array_merge(AuthSwitcher::PASSWORD_CONTEXTS, [
// 'my-custom-authn-context-for-password', // 'my-custom-authn-context-for-password',
// '/^my-regex-.*/', // '/^my-regex-.*/',
...@@ -140,6 +141,8 @@ You can override which AuthnContextClassRefs are treated as password authenticat ...@@ -140,6 +141,8 @@ You can override which AuthnContextClassRefs are treated as password authenticat
Use `setup_mfa_redirect_url` for redirecting user without MFA tokens to page, where he can register it. User is redirected when MFA is enforced and service is not excluded from this behaviour by `mfa_excluded_sps` configuration option. Use `setup_mfa_redirect_url` for redirecting user without MFA tokens to page, where he can register it. User is redirected when MFA is enforced and service is not excluded from this behaviour by `mfa_excluded_sps` configuration option.
It's possible to filter out some ACRS by using `prefixes_for_acrs_filtering`. ACRS starting with some of configured prefix will be filtered out and will not be forwarded to IdP.
## MFA tokens ## MFA tokens
This module expects that there will be a user attribute (`$attributes` aka `$state['Attributes']`) with This module expects that there will be a user attribute (`$attributes` aka `$state['Attributes']`) with
......
...@@ -114,14 +114,16 @@ class SwitchAuth extends \SimpleSAML\Auth\ProcessingFilter ...@@ -114,14 +114,16 @@ class SwitchAuth extends \SimpleSAML\Auth\ProcessingFilter
$this->change_weak_password_urls = $config->getArray('change_weak_password_urls', []); $this->change_weak_password_urls = $config->getArray('change_weak_password_urls', []);
list($this->password_contexts, $this->mfa_contexts, $password_contexts_patterns, $mfa_contexts_patterns) [$this->password_contexts, $this->mfa_contexts, $password_contexts_patterns,
$mfa_contexts_patterns, $prefixes_for_acrs_filtering]
= ContextSettings::parseConfig($config); = ContextSettings::parseConfig($config);
$this->authnContextHelper = new AuthnContextHelper( $this->authnContextHelper = new AuthnContextHelper(
$this->password_contexts, $this->password_contexts,
$this->mfa_contexts, $this->mfa_contexts,
$password_contexts_patterns, $password_contexts_patterns,
$mfa_contexts_patterns $mfa_contexts_patterns,
$prefixes_for_acrs_filtering
); );
} }
......
...@@ -24,11 +24,16 @@ class AuthnContextHelper ...@@ -24,11 +24,16 @@ class AuthnContextHelper
public const CHANGE_WEAK_PASSWORD_URL_ENABLED = 'change_weak_password_url_enabled'; public const CHANGE_WEAK_PASSWORD_URL_ENABLED = 'change_weak_password_url_enabled';
public const SAML_REQUESTED_AUTHN_CONTEXT = "saml:RequestedAuthnContext";
public const STATE_AUTHN_CONTEXT_CLASS_REF = "AuthnContextClassRef";
public function __construct( public function __construct(
$password_contexts, $password_contexts,
$mfa_contexts, $mfa_contexts,
$password_contexts_patterns = [], $password_contexts_patterns = [],
$mfa_contexts_patterns = [] $mfa_contexts_patterns = [],
$prefixes_for_acrs_filtering = []
) { ) {
$this->password_contexts = $password_contexts; $this->password_contexts = $password_contexts;
$this->password_contexts_patterns = $password_contexts_patterns; $this->password_contexts_patterns = $password_contexts_patterns;
...@@ -36,6 +41,7 @@ class AuthnContextHelper ...@@ -36,6 +41,7 @@ class AuthnContextHelper
$this->mfa_contexts_patterns = $mfa_contexts_patterns; $this->mfa_contexts_patterns = $mfa_contexts_patterns;
$this->supported_contexts = array_merge($this->mfa_contexts, $this->password_contexts); $this->supported_contexts = array_merge($this->mfa_contexts, $this->password_contexts);
$this->default_requested_contexts = array_merge($this->password_contexts, $this->mfa_contexts); $this->default_requested_contexts = array_merge($this->password_contexts, $this->mfa_contexts);
$this->$prefixes_for_acrs_filtering = $prefixes_for_acrs_filtering;
} }
public function MFAin($contexts) public function MFAin($contexts)
...@@ -60,7 +66,32 @@ class AuthnContextHelper ...@@ -60,7 +66,32 @@ class AuthnContextHelper
&$mustPerformMfa, &$mustPerformMfa,
$change_weak_password_urls $change_weak_password_urls
) { ) {
$requestedContexts = $state['saml:RequestedAuthnContext']['AuthnContextClassRef'] ?? null; $originalAuthnContextClassRef =
$state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF] ?? [];
$filteredAcrs = [];
if (!empty($this->filter_acrs_prefixes)) {
Logger::debug('authswitcher: ' . json_encode($this->filter_acrs_prefixes) .
' prefixes will be filtered from AuthnContextClassRef');
foreach ($originalAuthnContextClassRef as $acr) {
$acr = trim($acr);
$retain = true;
foreach ($this->filter_acrs_prefixes as $prefix) {
if (substr($acr, 0, strlen($prefix)) === $prefix) {
$retain = false;
break;
}
}
if ($retain) {
array_push($filteredAcrs, $acr);
}
}
$state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF] = $filteredAcrs;
Logger::debug('authswitcher: AuthnContextClassRef was filtered to ' . json_encode($filteredAcrs));
}
$requestedContexts = $state[self::SAML_REQUESTED_AUTHN_CONTEXT][self::STATE_AUTHN_CONTEXT_CLASS_REF] ?? null;
if (empty($requestedContexts)) { if (empty($requestedContexts)) {
Logger::info( Logger::info(
'authswitcher: no AuthnContext requested, using default: ' . json_encode( 'authswitcher: no AuthnContext requested, using default: ' . json_encode(
...@@ -69,6 +100,7 @@ class AuthnContextHelper ...@@ -69,6 +100,7 @@ class AuthnContextHelper
); );
$requestedContexts = $this->default_requested_contexts; $requestedContexts = $this->default_requested_contexts;
} }
$supportedRequestedContexts = array_values(array_intersect($requestedContexts, $this->supported_contexts)); $supportedRequestedContexts = array_values(array_intersect($requestedContexts, $this->supported_contexts));
if (!$sfaEntropy && in_array(AuthSwitcher::REFEDS_SFA, $supportedRequestedContexts)) { if (!$sfaEntropy && in_array(AuthSwitcher::REFEDS_SFA, $supportedRequestedContexts)) {
Logger::info( Logger::info(
...@@ -105,7 +137,7 @@ class AuthnContextHelper ...@@ -105,7 +137,7 @@ class AuthnContextHelper
$requestResult = $this->testComparison( $requestResult = $this->testComparison(
$usersCapabilities, $usersCapabilities,
$supportedRequestedContexts, $supportedRequestedContexts,
$state['saml:RequestedAuthnContext']['Comparison'] ?? Constants::COMPARISON_EXACT, $state[self::SAML_REQUESTED_AUTHN_CONTEXT]['Comparison'] ?? Constants::COMPARISON_EXACT,
$upstreamContext $upstreamContext
); );
if ($requestResult === null) { if ($requestResult === null) {
......
...@@ -11,6 +11,7 @@ class ContextSettings ...@@ -11,6 +11,7 @@ class ContextSettings
$contexts_regex = $config->getBoolean('contexts_regex', false); $contexts_regex = $config->getBoolean('contexts_regex', false);
$password_contexts = $config->getArray('password_contexts', AuthSwitcher::PASSWORD_CONTEXTS); $password_contexts = $config->getArray('password_contexts', AuthSwitcher::PASSWORD_CONTEXTS);
$mfa_contexts = $config->getArray('mfa_contexts', AuthSwitcher::MFA_CONTEXTS); $mfa_contexts = $config->getArray('mfa_contexts', AuthSwitcher::MFA_CONTEXTS);
$prefixes_for_acrs_filtering = $config->getArray('remove_authn_context_class_ref_prefixes', []);
if ($contexts_regex) { if ($contexts_regex) {
$password_contexts_patterns = array_filter($password_contexts, self::isRegex); $password_contexts_patterns = array_filter($password_contexts, self::isRegex);
$password_contexts = array_diff($password_contexts, $password_contexts_patterns); $password_contexts = array_diff($password_contexts, $password_contexts_patterns);
...@@ -21,7 +22,8 @@ class ContextSettings ...@@ -21,7 +22,8 @@ class ContextSettings
$mfa_contexts_patterns = []; $mfa_contexts_patterns = [];
} }
return [$password_contexts, $mfa_contexts, $password_contexts_patterns, $mfa_contexts_patterns]; return [$password_contexts, $mfa_contexts, $password_contexts_patterns,
$mfa_contexts_patterns, $prefixes_for_acrs_filtering];
} }
private static function isRegex($str) private static function isRegex($str)
......
...@@ -28,13 +28,18 @@ class DiscoUtils ...@@ -28,13 +28,18 @@ class DiscoUtils
public static function setUpstreamRequestedAuthnContext(array &$state) public static function setUpstreamRequestedAuthnContext(array &$state)
{ {
$config = Configuration::getOptionalConfig('module_authswitcher.php'); $config = Configuration::getOptionalConfig('module_authswitcher.php');
list($password_contexts, $mfa_contexts, $password_contexts_patterns, $mfa_contexts_patterns) [$password_contexts,
$mfa_contexts,
$password_contexts_patterns,
$mfa_contexts_patterns,
$prefixes_for_acrs_filtering]
= ContextSettings::parseConfig($config); = ContextSettings::parseConfig($config);
$authnContextHelper = new AuthnContextHelper( $authnContextHelper = new AuthnContextHelper(
$password_contexts, $password_contexts,
$mfa_contexts, $mfa_contexts,
$password_contexts_patterns, $password_contexts_patterns,
$mfa_contexts_patterns $mfa_contexts_patterns,
$prefixes_for_acrs_filtering
); );
$spRequestedContexts = $state['saml:RequestedAuthnContext']['AuthnContextClassRef'] ?? []; $spRequestedContexts = $state['saml:RequestedAuthnContext']['AuthnContextClassRef'] ?? [];
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment