fix(core): Require current password on password change (#285)
Increase security by requiring the current password when changing the password. This increases the security for cases such as XSS, or just a forgotten browser window left open. Fixes #4140pull/287/head
parent
03d8ed5e92
commit
2300fe8aab
|
@ -133,7 +133,7 @@
|
|||
}
|
||||
|
||||
[loginCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
|
||||
|
||||
|
||||
return loginCookie;
|
||||
}
|
||||
|
||||
|
@ -188,14 +188,14 @@
|
|||
NSDictionary *params;
|
||||
NSString *username, *password, *language, *domain, *remoteHost, *verificationCode;
|
||||
NSArray *supportedLanguages, *creds;
|
||||
|
||||
|
||||
SOGoPasswordPolicyError err;
|
||||
int expire, grace;
|
||||
BOOL rememberLogin, b;
|
||||
|
||||
|
||||
err = PolicyNoError;
|
||||
expire = grace = -1;
|
||||
|
||||
|
||||
auth = [[WOApplication application] authenticatorInContext: context];
|
||||
request = [context request];
|
||||
params = [[request contentAsString] objectFromJSONString];
|
||||
|
@ -209,10 +209,10 @@
|
|||
/* this will always be set to something more or less useful by
|
||||
* [WOHttpTransaction applyAdaptorHeadersWithHttpRequest] */
|
||||
remoteHost = [request headerForKey:@"x-webobjects-remote-host"];
|
||||
|
||||
|
||||
if ((b = [auth checkLogin: username password: password domain: &domain
|
||||
perr: &err expire: &expire grace: &grace useCache: NO])
|
||||
&& (err == PolicyNoError)
|
||||
&& (err == PolicyNoError)
|
||||
// no password policy
|
||||
&& ((expire < 0 && grace < 0) // no password policy or everything is alright
|
||||
|| (expire < 0 && grace > 0) // password expired, grace still permits login
|
||||
|
@ -221,7 +221,7 @@
|
|||
NSDictionary *json;
|
||||
|
||||
[self logWithFormat: @"successful login from '%@' for user '%@' - expire = %d grace = %d", remoteHost, username, expire, grace];
|
||||
|
||||
|
||||
// We get the proper username for cookie creation. If we are using a multidomain
|
||||
// environment with SOGoEnableDomainBasedUID, we could have to append the domain
|
||||
// to the username. Also when SOGoEnableDomainBasedUID is enabled, we could be in
|
||||
|
@ -648,7 +648,7 @@
|
|||
|
||||
request = [context request];
|
||||
message = [[request contentAsString] objectFromJSONString];
|
||||
|
||||
|
||||
auth = [[WOApplication application]
|
||||
authenticatorInContext: context];
|
||||
value = [[context request]
|
||||
|
@ -662,6 +662,8 @@
|
|||
password: &password];
|
||||
|
||||
newPassword = [message objectForKey: @"newPassword"];
|
||||
// overwrite the value from the session to compare the actual input
|
||||
password = [message objectForKey: @"oldPassword"];
|
||||
|
||||
um = [SOGoUserManager sharedUserManager];
|
||||
|
||||
|
@ -673,7 +675,7 @@
|
|||
perr: &error])
|
||||
{
|
||||
// We delete the previous session
|
||||
[SOGoSession deleteValueForSessionKey: [creds objectAtIndex: 1]];
|
||||
[SOGoSession deleteValueForSessionKey: [creds objectAtIndex: 1]];
|
||||
|
||||
if ([domain isNotNull])
|
||||
{
|
||||
|
@ -682,7 +684,7 @@
|
|||
[username rangeOfString: @"@"].location == NSNotFound)
|
||||
username = [NSString stringWithFormat: @"%@@%@", username, domain];
|
||||
}
|
||||
|
||||
|
||||
response = [self responseWith204];
|
||||
authCookie = [auth cookieWithUsername: username
|
||||
andPassword: newPassword
|
||||
|
|
|
@ -238,6 +238,7 @@
|
|||
"Additional Parameters" = "Additional Parameters";
|
||||
|
||||
/* password */
|
||||
"Current password" = "Current password";
|
||||
"New password" = "New password";
|
||||
"Confirmation" = "Confirmation";
|
||||
"Change" = "Change";
|
||||
|
|
|
@ -233,6 +233,7 @@
|
|||
"Additional Parameters" = "Zusätzliche Einstellungen";
|
||||
|
||||
/* password */
|
||||
"Current password" = "Aktuelles Passwort";
|
||||
"New password" = "Neues Passwort";
|
||||
"Confirmation" = "Bestätigung";
|
||||
"Change" = "Ändern";
|
||||
|
|
|
@ -262,16 +262,21 @@
|
|||
label:label="Password">
|
||||
<md-content id="passwordView" class="md-padding">
|
||||
<div layout="row">
|
||||
<md-input-container class="md-block" flex="50">
|
||||
<label><var:string label:value="Current password"/>
|
||||
</label>
|
||||
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.oldPassword"/>
|
||||
</md-input-container>
|
||||
<md-input-container class="md-block" flex="50">
|
||||
<label><var:string label:value="New password"/>
|
||||
</label>
|
||||
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPassword"/>
|
||||
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPassword"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container class="md-block" flex="50">
|
||||
<label><var:string label:value="Confirmation"/>
|
||||
</label>
|
||||
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPasswordConfirmation"/>
|
||||
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPasswordConfirmation"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<div layout="row" layout-align="end center">
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
return d.promise;
|
||||
}, // login: function(data) { ...
|
||||
|
||||
changePassword: function(newPassword) {
|
||||
changePassword: function(newPassword, oldPassword) {
|
||||
var d = $q.defer(),
|
||||
xsrfCookie = $cookies.get('XSRF-TOKEN');
|
||||
|
||||
|
@ -151,7 +151,7 @@
|
|||
headers: {
|
||||
'X-XSRF-TOKEN' : xsrfCookie
|
||||
},
|
||||
data: { newPassword: newPassword }
|
||||
data: { newPassword: newPassword, oldPassword: oldPassword }
|
||||
}).then(d.resolve, function(response) {
|
||||
var error,
|
||||
data = response.data,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
this.$onInit = function() {
|
||||
this.preferences = Preferences;
|
||||
this.passwords = { newPassword: null, newPasswordConfirmation: null };
|
||||
this.passwords = { newPassword: null, newPasswordConfirmation: null, oldPassword: null };
|
||||
this.timeZonesList = $window.timeZonesList;
|
||||
this.timeZonesSearchText = '';
|
||||
this.sieveVariablesCapability = ($window.sieveCapabilities.indexOf('variables') >= 0);
|
||||
|
@ -465,14 +465,15 @@
|
|||
this.canChangePassword = function() {
|
||||
if (this.passwords.newPassword && this.passwords.newPassword.length > 0 &&
|
||||
this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length &&
|
||||
this.passwords.newPassword == this.passwords.newPasswordConfirmation)
|
||||
this.passwords.newPassword == this.passwords.newPasswordConfirmation &&
|
||||
this.passwords.oldPassword && this.passwords.oldPassword.length > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
this.changePassword = function() {
|
||||
Authentication.changePassword(this.passwords.newPassword).then(function() {
|
||||
Authentication.changePassword(this.passwords.newPassword, this.passwords.oldPassword).then(function() {
|
||||
var alert = $mdDialog.alert({
|
||||
title: l('Password'),
|
||||
content: l('The password was changed successfully.'),
|
||||
|
|
Loading…
Reference in New Issue