Skip to content
Snippets Groups Projects
Unverified Commit 16a14224 authored by Thijs Kinkhorst's avatar Thijs Kinkhorst Committed by GitHub
Browse files

Merge pull request #997 from dnmvisser/dv_authorize_add_reject_msg

Show custom rejection message to unauthorised users
parents 4e239ac7 3cf4ff01
No related branches found
No related tags found
No related merge requests found
......@@ -20,20 +20,26 @@ This module provides a user authorization filter based on attribute matching for
`authorize:Authorize`
---------------------
There are two configuration options that can be defined; deny and regex. All other filter configuration options are considered attribute matching rules.
There are three configuration options that can be defined: `deny`, `regex`, and `reject_msg`. All other filter configuration options are considered attribute matching rules.
The users not authorized will be shown a 403 Forbidden page.
Unauthorized users will be shown a 403 Forbidden page.
### Deny ###
### `deny` ###
The default action of the filter is to authorize only if an attribute match is found (default allow). When set to TRUE, this option reverses that rule and authorizes the user unless an attribute match is found (default deny), causing an unauthorized action.
Note: This option needs to be boolean (TRUE/FALSE) else it will be considered an attribute matching rule.
### Regex ###
### `regex` ###
Turn regex pattern matching on or off for the attribute values defined. For backwards compatibility, this option defaults to TRUE, but can be turned off by setting it to FALSE.
Note: This option needs to be boolean (TRUE/FALSE) else it will be considered an attribute matching rule.
### `reject_msg` ###
This option can be used to provide a localised, custom message to an unauthorised user. For example: tailored instructions on how to fix the authorisation issue, specific contact details, etc.
It should be an array of key/value pairs, with the keys as the language code. You can use HTML in the message. See below for an example.
### Attribute Rules ###
Each additional filter configuration option is considered an attribute matching rule. For each attribute, you can specify a string or array of strings to match. If one of those attributes match one of the rules (OR operator), the user is authorized/unauthorized (depending on the deny config option).
......@@ -45,39 +51,55 @@ Note: If regex is enabled, you must use the preg_match format, i.e. you have to
### Examples ###
To use this filter configure it in `config/config.php`:
'authproc.sp' => array(
60 => array(
'class' => 'authorize:Authorize',
'uid' => array(
'/.*@example.com/',
'/(user1|user2|user3)@example.edu/',
),
'schacUserStatus' => '@urn:mace:terena.org:userStatus:' .
'example.org:service:active.*@',
)
```php
'authproc.sp' => [
60 => [
'class' => 'authorize:Authorize',
'uid' => [
'/.*@example.com/',
'/(user1|user2|user3)@example.edu/',
],
'schacUserStatus' => '@urn:mace:terena.org:userStatus:' .
'example.org:service:active.*@',
]
]
```
An alternate way of using this filter is to deny certain users. Or even use multiple filters to create a simple ACL, by first allowing a group of users but then denying a "black list" of users.
'authproc.sp' => array(
60 => array(
'class' => 'authorize:Authorize',
'deny' => TRUE,
'uid' => array(
'/.*@students.example.edu/',
'/(stu1|stu2|stu3)@example.edu/',
)
)
```php
'authproc.sp' => [
60 => array[
'class' => 'authorize:Authorize',
'deny' => TRUE,
'uid' => [
'/.*@students.example.edu/',
'/(stu1|stu2|stu3)@example.edu/',
]
]
]
```
The regex pattern matching can be turned off, allowing for exact attribute matching rules. This can be helpful in cases where you know what the value should be. An example of this is with the memberOf attribute or using the ldap:AttributeAddUsersGroups filter with the group attribute.
'authproc.sp' => array(
60 => array(
'class' => 'authorize:Authorize',
'regex' => FALSE,
'group' => array(
'CN=SimpleSAML Students,CN=Users,DC=example,DC=edu',
'CN=All Teachers,OU=Staff,DC=example,DC=edu',
)
)
Additionally, some helpful instructions are shown.
```php
'authproc.sp' => [
60 => [
'class' => 'authorize:Authorize',
'regex' => FALSE,
'group' => [
'CN=SimpleSAML Students,CN=Users,DC=example,DC=edu',
'CN=All Teachers,OU=Staff,DC=example,DC=edu',
],
'reject_msg' => [
'en' => 'This service is only available to students and teachers.' .
'Please contact <a href="mailto:support@example.edu">support</a>.',
'nl' => 'Deze dienst is alleen beschikbaar voor studenten en docenten.' .
'Neem contact op met <a href="mailto:support@example.edu">support</a>.',
]
]
]
```
......@@ -26,6 +26,13 @@ class Authorize extends \SimpleSAML\Auth\ProcessingFilter
*/
protected $regex = true;
/**
* Array of localised rejection messages
*
* @var array
*/
protected $reject_msg = [];
/**
* Array of valid users. Each element is a regular expression. You should
* user \ to escape special chars, like '.' etc.
......@@ -60,6 +67,13 @@ class Authorize extends \SimpleSAML\Auth\ProcessingFilter
unset($config['regex']);
}
// Check for the reject_msg option, get it and remove it
// Must be array of languages
if (isset($config['reject_msg']) && is_array($config['reject_msg'])) {
$this->reject_msg = $config['reject_msg'];
unset($config['reject_msg']);
}
foreach ($config as $attribute => $values) {
if (is_string($values)) {
$values = [$values];
......@@ -93,6 +107,10 @@ class Authorize extends \SimpleSAML\Auth\ProcessingFilter
assert(array_key_exists('Attributes', $request));
$attributes = &$request['Attributes'];
// Store the rejection message array in the $request
if(!empty($this->reject_msg)) {
$request['authprocAuthorize_reject_msg'] = $this->reject_msg;
}
foreach ($this->valid_attribute_values as $name => $patterns) {
if (array_key_exists($name, $attributes)) {
......
......@@ -13,6 +13,11 @@
$this->data['403_header'] = $this->t('{authorize:Authorize:403_header}');
$this->data['403_text'] = $this->t('{authorize:Authorize:403_text}');
if (array_key_exists('reject_msg', $this->data)) {
if(isset($this->data['reject_msg'][$this->getLanguage()])) {
$this->data['403_text'] = $this->data['reject_msg'][$this->getLanguage()];
}
}
$this->includeAtTemplateBase('includes/header.php');
echo '<h1>'.$this->data['403_header'].'</h1>';
......
......@@ -2,7 +2,11 @@
{% block content %}
<h1>{{ '{authorize:Authorize:403_header}'|trans }}</h1>
{% if reject_msg[currentLanguage] is defined %}
<p>{{ reject_msg[currentLanguage]|raw }}</p>
{% else %}
<p>{{ '{authorize:Authorize:403_text}'|trans }}</p>
{% endif %}
{% if logoutURL is defined %}
<p>
<a href="{{ logoutURL|escape('html') }}">{{ '{status:logout}'|trans }}</a>
......
......@@ -18,5 +18,8 @@ if (isset($state['Source']['auth'])) {
['as' => $state['Source']['auth']]
)."&logout";
}
if (isset($state['authprocAuthorize_reject_msg'])) {
$t->data['reject_msg'] = $state['authprocAuthorize_reject_msg'];
}
header('HTTP/1.0 403 Forbidden');
$t->show();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment