diff --git a/lib/Authentication/AuthTokens/OIDCAuthToken.php b/lib/Authentication/AuthTokens/OIDCAuthToken.php index a7f84ed24..80555e2ba 100644 --- a/lib/Authentication/AuthTokens/OIDCAuthToken.php +++ b/lib/Authentication/AuthTokens/OIDCAuthToken.php @@ -9,6 +9,11 @@ abstract class OIDCAuthToken implements IAuthentication private $principal; protected $acceptedIssuers; protected $authRealm; + protected $groupHeader; + protected $groupSplitChar; + protected $bannedGroups; + protected $requiredGroups; + protected $helpString; /** * {@see IAuthentication::eraseCredentials()} @@ -99,7 +104,7 @@ public static function isStateless() } /** - * Set principal/User details from the session. + * Set principal/User details from the session and check group membership. */ protected function setTokenFromSession() { @@ -108,6 +113,82 @@ protected function setTokenFromSession() $this->userDetails = array( 'AuthenticationRealm' => array($this->authRealm) ); + + // Check group membership is acceptable. + $this->checkBannedGroups(); + $this->checkRequiredGroups(); + } + } + + /** + * Check the token lists all the required groups. + */ + protected function checkRequiredGroups() + { + $groupArray = explode( + $this->groupSplitChar, + $_SERVER[$this->groupHeader] + ); + + // Build up a list of missing groups. + $missingGoodGroups = []; + foreach ($this->requiredGroups as $group) { + if (!in_array($group, $groupArray)) { + $missingGoodGroups[] = $group; + } + } + + // If the list of missing groups is not empty, reject the user. + if (!empty($missingGoodGroups)) { + $this->rejectUser( + 'You are missing the following group(s):', + $missingGoodGroups + ); + } + } + + /** + * Check the token lists non of the banned groups. + */ + protected function checkBannedGroups() + { + $groupArray = explode($this->groupSplitChar, $_SERVER[$this->groupHeader]); + + $presentBadGroups = []; + foreach ($this->bannedGroups as $group) { + if (in_array($group, $groupArray)) { + $presentBadGroups[] = $group; + } + } + + // If the list of present bad groups is not empty, reject the user. + if (!empty($presentBadGroups)) { + $this->rejectUser( + 'We do not grant access to GOCDB to members of the following group(s):', + $presentBadGroups + ); } } + + /** + * Craft a BadCredentialsException exception. + * + * Uses the given error message to provide the end user more context. + * + * @param string $errorContext Context for the error. + * @param string[] $groupArray An array of group memberships + */ + protected function rejectUser($errorContext, $groupArray) + { + // For readability, when listing groups to the user, + // start each one on a new line with a '-' character. + $prependString = '
- '; + $groupString = implode($prependString, $groupArray); + throw new BadCredentialsException( + null, + 'You do not belong to the correct group(s) ' . + 'to gain access to this site.

' . $errorContext . + $prependString . $groupString . '

' . $this->helpString + ); + } }