Merge branch 'feature/accept-web-server-authentication-5405'
This commit is contained in:
commit
bcfebcd937
|
@ -85,10 +85,16 @@ class AuthenticationController extends ActionController
|
|||
*/
|
||||
public function logoutAction()
|
||||
{
|
||||
$this->_helper->layout->setLayout('inline');
|
||||
$auth = AuthManager::getInstance();
|
||||
$auth->removeAuthorization();
|
||||
$this->redirectToLogin();
|
||||
|
||||
if ($auth->isAuthenticatedFromRemoteUser()) {
|
||||
$this->_helper->layout->setLayout('login');
|
||||
$this->_response->setHttpResponseCode(401);
|
||||
} else {
|
||||
$this->_helper->layout->setLayout('inline');
|
||||
$this->redirectToLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
* is useful for preserving the detail view and the selection in that case.
|
||||
*
|
||||
* refs #4833
|
||||
*
|
||||
* TODO: Copy this snipped into the new login.phtml
|
||||
*/
|
||||
var url = document.URL.match(/(^[^#]*)/)[0] + encodeURIComponent(window.location.hash);
|
||||
document.getElementById('form_login').action = url;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<!--
|
||||
This view provides a workaround to logout from an external authentication provider, in case external
|
||||
authentication was configured (the default is to handle authentications internally in Icingaweb2).
|
||||
|
||||
The <a href="http://tools.ietf.org/html/rfc2617">Http Basic and Digest Authentication</a> is not
|
||||
designed to handle logout. When the user has provided valid credentials, the client is adviced to include these
|
||||
in every further request until the browser was closed. To allow logout and to allow the user to change the
|
||||
logged-in user this JavaScript provides a workaround to force a new authentication prompt in most browsers.
|
||||
-->
|
||||
|
||||
<div class="row">
|
||||
<br/>
|
||||
<div class="md-offset-3 col-md-6 col-sm-6 col-sm-offset-3">
|
||||
<div class="alert alert-warning" id="logout-status">
|
||||
<b> <?= t('Logging out...'); ?> </b> <br />
|
||||
<?= t(
|
||||
'If this message does not disappear, it might be necessary to quit the ' .
|
||||
'current session manually by clearing the cache, or by closing the current ' .
|
||||
'browser session.'
|
||||
); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3">
|
||||
<div class="container" >
|
||||
<a class="button btn btn-cta form-control input-sm" href="<?= $this->href('dashboard/index'); ?>"> <?= t('Login'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
/**
|
||||
* When JavaScript is available, trigger an XmlHTTPRequest with the non-existing user 'logout' and abort it
|
||||
* before it is able to finish. This will cause the browser to show a new authentication prompt in the next
|
||||
* request.
|
||||
*/
|
||||
window.onload = function () {
|
||||
function getXMLHttpRequest() {
|
||||
var xmlhttp = null;
|
||||
try {
|
||||
if (window.XMLHttpRequest) {
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
} else if (window.ActiveXObject) {
|
||||
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
} catch (e) {}
|
||||
return xmlhttp;
|
||||
}
|
||||
var msg = document.getElementById('logout-status');
|
||||
try {
|
||||
if (navigator.userAgent.toLowerCase().indexOf('msie') !== -1) {
|
||||
document.execCommand('ClearAuthenticationCache');
|
||||
} else {
|
||||
var xhttp = getXMLHttpRequest();
|
||||
xhttp.open('GET', 'arbitrary url', true, 'logout', 'logout');
|
||||
xhttp.send('');
|
||||
xhttp.abort();
|
||||
}
|
||||
} catch (e) {
|
||||
msg.innerHTML = '<?= t(
|
||||
'Logout not possible, it may be necessary to quit the session manually ' .
|
||||
'by clearing the cache, or closing the current browser session. Error: '
|
||||
);?>' + ': ' + e.getMessage() ;
|
||||
msg.setAttribute('class', 'alert alert-danger');
|
||||
}
|
||||
msg.innerHTML = '<?= t('Logout successful!'); ?>';
|
||||
msg.setAttribute('class', 'alert alert-success');
|
||||
};
|
||||
</script>
|
|
@ -14,6 +14,10 @@ moduleFolder = "@icingaweb_config_path@/enabledModules"
|
|||
; won't show up in the list of disabled modules.
|
||||
; modulePath = "/vagrant/modules:/usr/share/icingaweb/modules"
|
||||
|
||||
; The used authentication-mode can be either "internal" to handle the authentication in IcingaWeb
|
||||
; or "external" to delegate the authentication to the used WebServer
|
||||
authenticationMode = "internal"
|
||||
|
||||
[logging]
|
||||
enable = true
|
||||
; Writing to a Stream
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# Externel Authentication
|
||||
|
||||
It is possible to use the authentication mechanism of the webserver,
|
||||
instead of using the internal authentication-manager to
|
||||
authenticate users. This might be useful if you only have very few users, and
|
||||
user management over *.htaccess* is sufficient, or if you must use some other
|
||||
authentication mechanism that is only available through your webserver.
|
||||
|
||||
When external authentication is used, Icingaweb will entrust the
|
||||
complete authentication process to the external authentication provider (the webserver):
|
||||
The provider should take care of authenticating the user and declining
|
||||
all requests with invalid or missing credentials. When the authentication
|
||||
was succesful, it should provide the authenticated users name to its php-module
|
||||
and Icingaweb will assume that the user is authorized to access the page.
|
||||
Because of this it is very important that the webservers authentication is
|
||||
configured correctly, as wrong configuration could lead to unauthorized
|
||||
access to the site, or a broken login-process.
|
||||
|
||||
|
||||
## Use External Authentication
|
||||
|
||||
Using external authentication in Icingaweb requires two steps to work:
|
||||
|
||||
1. The external authentication must be set up correctly to always
|
||||
authenticate the users.
|
||||
2. Icingaweb must be configured to use the external authentication.
|
||||
|
||||
|
||||
### Prepare the External Authentication Provider
|
||||
|
||||
This step depends heavily on the used webserver and authentication
|
||||
mechanism you want to use. It is not possible to cover all possibillities
|
||||
and you should probably read the documentation for your webserver for
|
||||
detailed instructions on how to set up authentication properly.
|
||||
|
||||
In general, you need to make sure that:
|
||||
|
||||
- All routes require authentication
|
||||
- Only permitted users are allowed to authenticate
|
||||
|
||||
|
||||
#### Example Configuration for Apache and HTTPDigestAuthentication
|
||||
|
||||
The following example will show how to enable external authentication in Apache using
|
||||
*HTTP Digest Authentication*.
|
||||
|
||||
##### Create users
|
||||
|
||||
To create users for a digest authentication we can use the tool *htdigest*.
|
||||
We choose *.icingawebdigest* as a name for the created file, containing
|
||||
the user credentials.
|
||||
|
||||
This command will create a new file with the user *jdoe*. *htdigest*
|
||||
will prompt you for your password, after it has been executed. If you
|
||||
want to add more users to the file you need to ommit the *-c* parameter
|
||||
in all further commands to avoInid the file to be overwritten.
|
||||
|
||||
|
||||
sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe
|
||||
|
||||
|
||||
##### Set up authentication
|
||||
|
||||
The webserver should require authentication for all public icingaweb files.
|
||||
|
||||
|
||||
<Directory "/var/www/html/icingaweb">
|
||||
AuthType digest
|
||||
AuthName "Icingaweb 2"
|
||||
AuthDigestProvider file
|
||||
AuthUserFile /etc/httpd/conf.d/.icingawebdigest
|
||||
Require valid-user
|
||||
</Directory>
|
||||
|
||||
|
||||
### Prepare Icingaweb
|
||||
|
||||
When the external authentication is set up correctly, we need
|
||||
to configure IcingaWeb to use it as an authentication source. The
|
||||
configuration key *authenticationMode* in the section *global* defines
|
||||
if the authentication should be handled internally or externally. Since
|
||||
we want to delegate the authentication to the Webserver we choose
|
||||
"external" as the new value:
|
||||
|
||||
|
||||
[global]
|
||||
; ...
|
||||
authenticationMode = "external"
|
||||
; ...
|
||||
|
|
@ -230,6 +230,11 @@ class Web extends ApplicationBootstrap
|
|||
{
|
||||
$authenticationManager = AuthenticationManager::getInstance();
|
||||
|
||||
|
||||
if ($this->getConfig()->get('global')->get('authenticationMode', 'internal') === 'external') {
|
||||
$authenticationManager->authenticateFromRemoteUser();
|
||||
}
|
||||
|
||||
if ($authenticationManager->isAuthenticated() === true) {
|
||||
$user = $authenticationManager->getUser();
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ use Icinga\Authentication\Backend\LdapUserBackend;
|
|||
**/
|
||||
class Manager
|
||||
{
|
||||
|
||||
/**
|
||||
* Singleton instance
|
||||
*
|
||||
|
@ -59,6 +60,13 @@ class Manager
|
|||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* If the user was authenticated from the REMOTE_USER server variable
|
||||
*
|
||||
* @var Boolean
|
||||
*/
|
||||
private $fromRemoteUser = false;
|
||||
|
||||
/**
|
||||
* Instance of authenticated user
|
||||
*
|
||||
|
@ -387,6 +395,27 @@ class Manager
|
|||
$this->user = Session::getSession()->get('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to authenticate the user from the session, and then from the REMOTE_USER superglobal, that can be set by
|
||||
* an external authentication provider.
|
||||
*/
|
||||
public function authenticateFromRemoteUser()
|
||||
{
|
||||
$this->fromRemoteUser = true;
|
||||
$this->authenticateFromSession();
|
||||
if ($this->user !== null) {
|
||||
if (array_key_exists('REMOTE_USER', $_SERVER) && $this->user->getUsername() !== $_SERVER["REMOTE_USER"]) {
|
||||
// Remote user has changed, clear all sessions
|
||||
$this->removeAuthorization();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (array_key_exists('REMOTE_USER', $_SERVER) && $_SERVER["REMOTE_USER"]) {
|
||||
$this->user = new User($_SERVER["REMOTE_USER"]);
|
||||
$this->persistCurrentUser();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user is currently authenticated
|
||||
*
|
||||
|
@ -472,4 +501,12 @@ class Manager
|
|||
{
|
||||
return $this->user->getGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the session was established from the REMOTE_USER server variable.
|
||||
*/
|
||||
public function isAuthenticatedFromRemoteUser()
|
||||
{
|
||||
return $this->fromRemoteUser;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ class PieChart implements Widget
|
|||
*/
|
||||
private $template =<<<'EOD'
|
||||
|
||||
<div data-icinga-component="app/piechart">
|
||||
<div>
|
||||
<img class='inlinepie' src="{url}" width={width} height={height}> </img>
|
||||
</div>
|
||||
EOD;
|
||||
|
|
Loading…
Reference in New Issue