Skip to content
Snippets Groups Projects
Commit 36a346a8 authored by Pavel Břoušek's avatar Pavel Břoušek
Browse files

REFEDS (replacing mfa_performed)

parent e60fb751
No related branches found
No related tags found
No related merge requests found
README.md 100644 → 100755
...@@ -27,7 +27,7 @@ The modules that are going to be controlled by authswitcher need to be installed ...@@ -27,7 +27,7 @@ The modules that are going to be controlled by authswitcher need to be installed
Add (for example) the following as the first [auth proc filter](https://simplesamlphp.org/docs/stable/simplesamlphp-authproc#section_1): Add (for example) the following as the first [auth proc filter](https://simplesamlphp.org/docs/stable/simplesamlphp-authproc#section_1):
```php ```php
'1' => array( 1 => array(
'class' => 'authswitcher:SwitchAuth', 'class' => 'authswitcher:SwitchAuth',
'dataAdapterClassName' => 'sspmod_authapi_DbDataAdapter', 'dataAdapterClassName' => 'sspmod_authapi_DbDataAdapter',
'configs' => array( 'configs' => array(
...@@ -36,6 +36,7 @@ Add (for example) the following as the first [auth proc filter](https://simplesa ...@@ -36,6 +36,7 @@ Add (for example) the following as the first [auth proc filter](https://simplesa
'api_key' => 'abcdefghchijklmnopqrstuvwxyz', // change to your API key 'api_key' => 'abcdefghchijklmnopqrstuvwxyz', // change to your API key
'key_id_attribute' => 'yubikey', 'key_id_attribute' => 'yubikey',
'abort_if_missing' => true, 'abort_if_missing' => true,
'assurance_attribute' => 'yubikeyAssurance',
), ),
'simpletotp:2fa' => array( 'simpletotp:2fa' => array(
'secret_attr' => 'totp_secret', 'secret_attr' => 'totp_secret',
...@@ -43,19 +44,37 @@ Add (for example) the following as the first [auth proc filter](https://simplesa ...@@ -43,19 +44,37 @@ Add (for example) the following as the first [auth proc filter](https://simplesa
), ),
), ),
), ),
// and as a safety precausion, remove the "secret" attributes // as a safety precausion, remove the "secret" attributes
98 => array( 2 => array(
'class' => 'core:AttributeAlter', 'class' => 'core:AttributeAlter',
'subject' => 'yubikey', 'subject' => 'yubikey',
'pattern' => '/.*/', 'pattern' => '/.*/',
'%remove', '%remove',
), ),
99 => array( 3 => array(
'class' => 'core:AttributeAlter', 'class' => 'core:AttributeAlter',
'subject' => 'totp_secret', 'subject' => 'totp_secret',
'pattern' => '/.*/', 'pattern' => '/.*/',
'%remove', '%remove',
), ),
// REFEDS
10 => array(
'class' => 'core:AttributeAdd',
'eduPersonAssurance' => array(
'https://refeds.org/assurance',
'https://refeds.org/assurance/ID/unique',
'https://refeds.org/assurance/ID/no-eppn-reassign',
'https://refeds.org/assurance/IAP/local-enterprise',
'https://refeds.org/assurance/ATP/ePA-1m',
'https://refeds.org/assurance/ATP/ePA-1d',
'https://refeds.org/assurance/IAP/low',
'https://refeds.org/assurance/IAP/medium',
),
),
15 => array(
'class' => 'authswitcher:Refeds',
),
``` ```
All MFA modules should enforce 2FA etc. as they are only run for users that have turned them on. All MFA modules should enforce 2FA etc. as they are only run for users that have turned them on.
...@@ -100,4 +119,4 @@ class aswAuthFilterMethod_foo_bar extends sspmod_authswitcher_AuthFilterMethod { ...@@ -100,4 +119,4 @@ class aswAuthFilterMethod_foo_bar extends sspmod_authswitcher_AuthFilterMethod {
Then configure authswitcher to use filter `foo:bar` and this class will be used. Then configure authswitcher to use filter `foo:bar` and this class will be used.
© 2017 CSIRT-MU © 2017-2018 CSIRT-MU
default-enable 100644 → 100755
File mode changed from 100644 to 100755
<?php
require_once __DIR__ . '/../../defaultAuthFilterMethods.php';
class sspmod_authswitcher_Auth_Process_Refeds extends SimpleSAML_Auth_ProcessingFilter {
/* constants */
const DEBUG_PREFIX = 'authswitcher:Refeds: ';
/** @override */
public function process(&$state) {
$mfaPerformed = $this->wasMFAPerformed($state);
$this->addRefedsAttributes($mfaPerformed, $state);
}
/** Check if the MFA auth proc filters (which were run) finished successfully.
* If everything is configured correctly, this should not throw an exception. */
private function wasMFAPerformed(&$state) {
$mfaPerformed = false;
if (isset($state[sspmod_authswitcher_AuthSwitcher::MFA_BEING_PERFORMED])) {
foreach($state[sspmod_authswitcher_AuthSwitcher::MFA_BEING_PERFORMED] as $method) {
if ($this->wasAuthProcFilterRun($method, $state)) {
$mfaPerformed = true;
} else {
throw new SimpleSAML_Error_Exception(self::DEBUG_PREFIX . 'The auth proc filter ' . $method->method . ' did not run. This probably means invalid configuration.');
}
}
}
return $mfaPerformed;
}
/** Check if an auth proc filter was actually run */
private function wasAuthProcFilterRun(sspmod_authswitcher_MethodParams $method, &$state) {
list($module, $simpleClass) = explode(":", $method->method);
$filterMethodClassName = "aswAuthFilterMethod_" . $module . "_" . $simpleClass;
$filterMethod = new $filterMethodClassName($method);
return $filterMethod->wasPerformed($state);
}
/** Add attributes to eduPersonAssurance considering SFA/MFA.
* It is assumed that SFA and MFA are exclusive (users with MFA enabled must use it every time). */
private function addRefedsAttributes($mfaPerformed, &$state) {
if ($mfaPerformed) {
$state['saml:AuthnContextClassRef'] = "https://refeds.org/profile/mfa";
$state['Attributes']['eduPersonAssurance'][] = 'https://refeds.org/assurance/IAP/high';
$state['Attributes']['eduPersonAssurance'][] = 'https://refeds.org/assurance/profile/espresso';
$state['Attributes']['eduPersonAssurance'][] = 'https://refeds.org/profile/mfa';
} else {
$state['saml:AuthnContextClassRef'] = "https://refeds.org/profile/sfa";
$state['Attributes']['eduPersonAssurance'][] = 'https://refeds.org/assurance/profile/cappuccino';
$state['Attributes']['eduPersonAssurance'][] = 'https://refeds.org/profile/sfa';
}
}
}
...@@ -82,17 +82,16 @@ class sspmod_authswitcher_Auth_Process_SwitchAuth extends SimpleSAML_Auth_Proces ...@@ -82,17 +82,16 @@ class sspmod_authswitcher_Auth_Process_SwitchAuth extends SimpleSAML_Auth_Proces
} }
/** Prepare before running auth proc filter (e.g. add atributes with secret keys) */ /** Prepare before running auth proc filter (e.g. add atributes with secret keys) */
private function prepareBeforeAuthProcFilter(sspmod_authswitcher_MethodParams $method, &$request) { private function prepareBeforeAuthProcFilter(sspmod_authswitcher_MethodParams $method, &$state) {
list($module, $simpleClass) = explode(":", $method->method); list($module, $simpleClass) = explode(":", $method->method);
$filterMethodClassName = "aswAuthFilterMethod_" . $module . "_" . $simpleClass; $filterMethodClassName = "aswAuthFilterMethod_" . $module . "_" . $simpleClass;
$filterMethod = new $filterMethodClassName($method); $filterMethod = new $filterMethodClassName($method);
$filterMethod->process($request); $filterMethod->process($state);
} }
/** @override */ /** @override */
public function process(&$request) { public function process(&$state) {
$uid = $request['Attributes'][sspmod_authswitcher_AuthSwitcher::UID_ATTR][0]; $uid = $state['Attributes'][sspmod_authswitcher_AuthSwitcher::UID_ATTR][0];
$request['Attributes'][sspmod_authswitcher_AuthSwitcher::MFA_PERFORMED_ATTR] = array();
for ($factor = sspmod_authswitcher_AuthSwitcher::FACTOR_MIN; $factor <= $this->supportedFactorMax; $factor++) { for ($factor = sspmod_authswitcher_AuthSwitcher::FACTOR_MIN; $factor <= $this->supportedFactorMax; $factor++) {
$methods = $this->getData()->getMethodsActiveForUidAndFactor($uid, $factor); $methods = $this->getData()->getMethodsActiveForUidAndFactor($uid, $factor);
...@@ -110,10 +109,13 @@ class sspmod_authswitcher_Auth_Process_SwitchAuth extends SimpleSAML_Auth_Proces ...@@ -110,10 +109,13 @@ class sspmod_authswitcher_Auth_Process_SwitchAuth extends SimpleSAML_Auth_Proces
throw new SimpleSAML_Error_Exception(self::DEBUG_PREFIX . 'Configuration for ' . $methodClass . ' is missing.'); throw new SimpleSAML_Error_Exception(self::DEBUG_PREFIX . 'Configuration for ' . $methodClass . ' is missing.');
} }
$this->prepareBeforeAuthProcFilter($method, $request); $this->prepareBeforeAuthProcFilter($method, $state);
$request['Attributes'][sspmod_authswitcher_AuthSwitcher::MFA_PERFORMED_ATTR][] = $methodClass; if (!isset($state[sspmod_authswitcher_AuthSwitcher::MFA_BEING_PERFORMED])) {
sspmod_authswitcher_Utils::runAuthProcFilter($methodClass, $this->configs[$methodClass], $request, $this->reserved); $state[sspmod_authswitcher_AuthSwitcher::MFA_BEING_PERFORMED] = array();
}
$state[sspmod_authswitcher_AuthSwitcher::MFA_BEING_PERFORMED][] = $method;
sspmod_authswitcher_Utils::runAuthProcFilter($methodClass, $this->configs[$methodClass], $state, $this->reserved);
} }
} }
......
<?php <?php
/** Concrete subclasses will be named aswAuthFilterMethod_modulename_filtername */ /** Concrete subclasses will be named aswAuthFilterMethod_modulename_filtername */
abstract class sspmod_authswitcher_AuthFilterMethod { abstract class sspmod_authswitcher_AuthFilterMethod {
abstract public function process(&$request); abstract public function process(&$state);
abstract public function __construct(sspmod_authswitcher_MethodParams $methodParams); abstract public function __construct(sspmod_authswitcher_MethodParams $methodParams);
abstract public function wasPerformed(&$state);
} }
...@@ -10,8 +10,8 @@ abstract class sspmod_authswitcher_AuthFilterMethodWithSimpleSecret extends sspm ...@@ -10,8 +10,8 @@ abstract class sspmod_authswitcher_AuthFilterMethodWithSimpleSecret extends sspm
} }
/** @override */ /** @override */
public function process(&$request) { public function process(&$state) {
$request['Attributes'][$this->getTargetFieldName()] = $this->parameter; $state['Attributes'][$this->getTargetFieldName()] = $this->parameter;
} }
/** @return string */ /** @return string */
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
class sspmod_authswitcher_AuthSwitcher { class sspmod_authswitcher_AuthSwitcher {
/** Name of the uid attribute. */ /** Name of the uid attribute. */
const UID_ATTR = 'uid'; const UID_ATTR = 'uid';
/** Name of the MFA performed attribute. */ /** Name of the MFA being performed attribute. */
const MFA_PERFORMED_ATTR = 'mfa_performed'; const MFA_BEING_PERFORMED = 'mfa_being_performed';
/** Minimal factor. */ /** Minimal factor. */
const FACTOR_MIN = sspmod_authswitcher_AuthSwitcherFactor::SECOND; const FACTOR_MIN = sspmod_authswitcher_AuthSwitcherFactor::SECOND;
} }
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
lib/Utils.php 100644 → 100755
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
class sspmod_authswitcher_Utils { class sspmod_authswitcher_Utils {
/** Execute an auth proc filter. /** Execute an auth proc filter.
* @see https://github.com/CESNET/perun-simplesamlphp-module/blob/master/lib/Auth/Process/ProxyFilter.php */ * @see https://github.com/CESNET/perun-simplesamlphp-module/blob/master/lib/Auth/Process/ProxyFilter.php */
public static function runAuthProcFilter(/*string*/ $nestedClass, array $config, &$request, $reserved) { public static function runAuthProcFilter(/*string*/ $nestedClass, array $config, &$state, $reserved) {
list($module, $simpleClass) = explode(":", $nestedClass); list($module, $simpleClass) = explode(":", $nestedClass);
$className = 'sspmod_'.$module.'_Auth_Process_'.$simpleClass; $className = 'sspmod_'.$module.'_Auth_Process_'.$simpleClass;
$authFilter = new $className($config, $reserved); $authFilter = new $className($config, $reserved);
$authFilter->process($request); $authFilter->process($state);
} }
/** Check if all modules for the specified filters are installed and enabled. */ /** Check if all modules for the specified filters are installed and enabled. */
......
...@@ -2,10 +2,19 @@ ...@@ -2,10 +2,19 @@
/** Definition for filter yubikey:OTP /** Definition for filter yubikey:OTP
* @see https://github.com/simplesamlphp/simplesamlphp-module-yubikey */ * @see https://github.com/simplesamlphp/simplesamlphp-module-yubikey */
class aswAuthFilterMethod_yubikey_OTP extends sspmod_authswitcher_AuthFilterMethodWithSimpleSecret { class aswAuthFilterMethod_yubikey_OTP extends sspmod_authswitcher_AuthFilterMethodWithSimpleSecret {
/* constants */
const ASSURANCE_ATTR_NAME = 'yubikeyAssurance';
const ASSURANCE_ATTR_VALUE = 'OTP';
/** @override */ /** @override */
public function getTargetFieldName() { public function getTargetFieldName() {
return 'yubikey'; return 'yubikey';
} }
/** @override */
public function wasPerformed(&$state) {
return isset($state['Attributes'][self::ASSURANCE_ATTR_NAME]) && $state['Attributes'][self::ASSURANCE_ATTR_NAME][0] === self::ASSURANCE_ATTR_VALUE;
}
} }
/** Definition for filter simpletotp:2fa /** Definition for filter simpletotp:2fa
...@@ -15,12 +24,17 @@ class aswAuthFilterMethod_simpletotp_2fa extends sspmod_authswitcher_AuthFilterM ...@@ -15,12 +24,17 @@ class aswAuthFilterMethod_simpletotp_2fa extends sspmod_authswitcher_AuthFilterM
public function getTargetFieldName() { public function getTargetFieldName() {
return 'totp_secret'; return 'totp_secret';
} }
/** @override */
public function wasPerformed(&$state) {
return isset($state['2fa_secret']);
}
} }
/** Definition for filter authTiqr:Tiqr */ /** Definition for filter authTiqr:Tiqr */
class aswAuthFilterMethod_authTiqr_Tiqr extends sspmod_authswitcher_AuthFilterMethod { class aswAuthFilterMethod_authTiqr_Tiqr extends sspmod_authswitcher_AuthFilterMethod {
/** @override */ /** @override */
public function process(&$request) { public function process(&$state) {
// TODO // TODO
} }
...@@ -28,4 +42,9 @@ class aswAuthFilterMethod_authTiqr_Tiqr extends sspmod_authswitcher_AuthFilterMe ...@@ -28,4 +42,9 @@ class aswAuthFilterMethod_authTiqr_Tiqr extends sspmod_authswitcher_AuthFilterMe
public function __construct(sspmod_authswitcher_MethodParams $methodParams) { public function __construct(sspmod_authswitcher_MethodParams $methodParams) {
// TODO // TODO
} }
/** @override */
public function wasPerformed(&$state) {
// TODO
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment