SSO: Display (localized) error message on failed SSO login.

This commit is contained in:
Aleksander Machniak 2018-11-27 13:17:26 +01:00
parent cf50715f4f
commit 2eea216d36
3 changed files with 61 additions and 19 deletions

View file

@ -69,14 +69,13 @@ class kolab_sso_openidc
{
$this->plugin->debug("[{$this->id}][authorize] Response: " . $_SERVER['REQUEST_URI']);
$error = $this->response_error(
$this->error = $this->error_message(
rcube_utils::get_input_value('error', rcube_utils::INPUT_GET),
rcube_utils::get_input_value('error_description', rcube_utils::INPUT_GET),
rcube_utils::get_input_value('error_uri', rcube_utils::INPUT_GET)
);
if ($error) {
// TODO: display error in UI
if ($this->error) {
return;
}
@ -85,25 +84,35 @@ class kolab_sso_openidc
if (!$state) {
$this->plugin->debug("[{$this->id}][response] State missing");
$error = $this->plugin->gettext('errorinvalidresponse');
$this->error = $this->plugin->gettext('errorinvalidresponse');
return;
}
if ($state != $this->plugin->rc->get_request_token()) {
$this->plugin->debug("[{$this->id}][response] Invalid response state");
$error = $this->plugin->gettext('errorinvalidresponse');
$this->error = $this->plugin->gettext('errorinvalidresponse');
return;
}
if (!$code) {
$this->plugin->debug("[{$this->id}][response] Code missing");
$error = $this->plugin->gettext('errorinvalidresponse');
$this->error = $this->plugin->gettext('errorinvalidresponse');
return;
}
return $this->request_token($code);
}
/**
* Error message for the response handler
*/
public function response_error()
{
if ($this->error) {
return $this->plugin->rc->gettext('loginfailed') . ' ' . $this->error;
}
}
/**
* Existing session validation
*/
@ -194,11 +203,12 @@ class kolab_sso_openidc
$response = @json_decode($response, true);
if ($status != 200 || !is_array($response) || !empty($response['error'])) {
$err = $this->error_message(is_array($response) ? $response['error'] : null);
$err = $this->error_text(is_array($response) ? $response['error'] : null);
throw new Exception("OpenIDC request failed with error: $err");
}
}
catch (Exception $e) {
$this->error = $this->plugin->gettext('errorunknown');
rcube::raise_error(array(
'line' => __LINE__, 'file' => __FILE__, 'message' => $e->getMessage()),
true, false);
@ -218,6 +228,7 @@ class kolab_sso_openidc
if (empty($response['access_token']) || empty($response['token_type'])
|| strtolower($response['token_type']) != 'bearer'
) {
$this->error = $this->plugin->gettext('errorinvalidresponse');
$this->plugin->debug("[{$this->id}][$mode] Error: Invalid or unsupported response");
return;
}
@ -276,6 +287,7 @@ class kolab_sso_openidc
$result['email'] = $email;
}
catch (Exception $e) {
$this->error = $this->plugin->gettext('errorinvalidtoken');
rcube::raise_error(array(
'line' => __LINE__, 'file' => __FILE__, 'message' => $e->getMessage()),
true, false);
@ -328,30 +340,30 @@ class kolab_sso_openidc
/**
* Returns (localized) user-friendly error message
*/
protected function response_error($error, $description, $uri)
protected function error_message($error, $description, $uri)
{
if (empty($error)) {
return;
}
$msg = $this->error_message($error);
$msg = $this->error_text($error);
$this->plugin->debug("[{$this->id}] Error: $msg");
// TODO: Add URI to the message
rcube::raise_error(array(
'message' => "[SSO] $msg." . ($description ? " $description" : '') . ($uri ? " ($uri)" : '')
), true, false);
$label = 'error' . str_replace('_', '', $error);
if ($this->plugin->rc->text_exists($label, 'kolab_sso')) {
return $this->plugin->gettext($label);
if (!$this->plugin->rc->text_exists($label, 'kolab_sso')) {
$label = 'errorunknown';
}
return $this->plugin->gettext('responseerrorunknown');
return $this->plugin->gettext($label);
}
/**
* Returns error message for specified OpenIDC error code
* Returns error text for specified OpenIDC error code
*/
protected function error_message($error)
protected function error_text($error)
{
switch ($error) {
// OAuth2 codes
@ -389,11 +401,11 @@ class kolab_sso_openidc
case 'invalid_request_object':
return "Invalid Request Object";
case 'request_not_supported':
return "Request param not supported";
return "Request not supported";
case 'request_uri_not_supported':
return "request_uri param not supported";
case 'registration_not_supported':
return "Registration parameter not supported";
return "Registration not supported";
}
return "Unknown error";

View file

@ -27,6 +27,7 @@ class kolab_sso extends rcube_plugin
private $data;
private $old_data;
private $driver;
private $logon_error;
private $debug = false;
@ -68,6 +69,9 @@ class kolab_sso extends rcube_plugin
$this->data['url'] = $_SESSION['sso_url'];
$this->data['mode'] = $mode;
}
else {
$this->logon_error = $driver->response_error();
}
}
// This is where we handle clicking one of "Login by SSO" buttons
else if ($_SESSION['temp'] && $this->rc->check_request()) {
@ -168,6 +172,10 @@ class kolab_sso extends rcube_plugin
$this->add_hook('ldap_connected', array($this, 'ldap_connected'));
$this->add_hook('chwala_authenticate', array($this, 'chwala_authenticate'));
}
else if ($this->logon_error) {
$args['valid'] = false;
$args['error'] = $this->logon_error;
}
return $args;
}

View file

@ -2,3 +2,25 @@
$labels['loginby'] = 'Login by $provider';
$labels['sso'] = 'Single Sign On';
$labels['errorunknown'] = 'Unknown SSO error.';
$labels['errorinvalidresponse'] = 'Invalid SSO response.';
$labels['errortokenfailed'] = 'Failed to get SSO token.';
$labels['errorivalidtoken'] = 'Invalid SSO token.';
$labels['errorinvalidrequest'] = 'Malformed SSO request.';
$labels['errorunauthorizedclient'] = 'Unauthorized SSO client.';
$labels['errorinvalidclient'] = 'SSO client authentication failed.';
$labels['erroraccessdienied'] = 'SSO request denied.';
$labels['errorunsupportedresponsetype'] = 'Unsupported SSO response type.';
$labels['errorinvalidgrant'] = 'Invalid authorization grant.';
$labels['errorinvalidscope'] = 'Invalid SSO scope.';
$labels['errorservererror'] = 'SSO server error.';
$labels['errortemporarilyunavailable'] = 'SSO service temporarily unavailable.';
$labels['errorinteractionrequired'] = 'User interaction required.';
$labels['errorloginrequired'] = 'User authentication required.';
$labels['erroraccountselectionrequired'] = 'User account selection required.';
$labels['errorconsentrequired'] = 'User consent required.';
$labels['errorinvalidrequesturi'] = 'Invalid request_uri.';
$labels['errorinvalidrequestobject'] = 'Invalid request object';
$labels['errorrequestnotsupported'] = 'Request not supported.';
$labels['errorrequesturinotsupported'] = 'Request_uri parameter not supported.';
$labels['errorregistrationnotsupported'] = 'Registration not supported';