#1406 improve CSRF and CORS errors reporting (#1488)

This commit is contained in:
Mario Romano
2017-01-17 13:44:39 +00:00
committed by Vito
parent 10a76cc0f6
commit 14d399968c
7 changed files with 181 additions and 95 deletions

View File

@@ -1,26 +1,28 @@
{ {
"LOGIN": { "LOGIN": {
"LOGO": "Alfresco", "LOGO": "Alfresco",
"LABEL": { "LABEL": {
"LOGIN": "Login", "LOGIN": "Login",
"USERNAME": "Username", "USERNAME": "Username",
"PASSWORD": "Password", "PASSWORD": "Password",
"REMEMBER": "Remember" "REMEMBER": "Remember"
}, },
"MESSAGES": { "MESSAGES": {
"USERNAME-REQUIRED": "Required", "USERNAME-REQUIRED": "Required",
"USERNAME-MIN": "Your username needs to be at least 4 characters.", "USERNAME-MIN": "Your username needs to be at least 4 characters.",
"PASSWORD-REQUIRED": "Enter your password to sign in", "PASSWORD-REQUIRED": "Enter your password to sign in",
"LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password", "LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password",
"LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined", "LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined",
"LOGIN-SUCCESS": "Login successful" "LOGIN-SUCCESS": "Login successful",
}, "LOGIN-ERROR-CORS": "CORS exception, check your server configuration",
"BUTTON": { "LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component"
"LOGIN": "SIGN IN" },
}, "BUTTON": {
"ACTION": { "LOGIN": "SIGN IN"
"HELP": "NEED HELP?", },
"REGISTER": "REGISTER" "ACTION": {
"HELP": "NEED HELP?",
"REGISTER": "REGISTER"
}
} }
}
} }

View File

@@ -1,25 +1,27 @@
{ {
"LOGIN": { "LOGIN": {
"LABEL": { "LABEL": {
"LOGIN": "Autenticazione", "LOGIN": "Autenticazione",
"USERNAME": "Nome utente", "USERNAME": "Nome utente",
"PASSWORD": "Password", "PASSWORD": "Password",
"REMEMBER": "Ricordami" "REMEMBER": "Ricordami"
}, },
"MESSAGES": { "MESSAGES": {
"USERNAME-REQUIRED": "Campo obbligatorio", "USERNAME-REQUIRED": "Campo obbligatorio",
"USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.", "USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.",
"PASSWORD-REQUIRED": "Campo obbligatorio", "PASSWORD-REQUIRED": "Campo obbligatorio",
"LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi", "LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi",
"LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo", "LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo",
"LOGIN-SUCCESS": "Login effettuata con successo" "LOGIN-SUCCESS": "Login effettuata con successo",
}, "LOGIN-ERROR-CORS": "CORS exception, controlla le configurazioni del tuo server",
"BUTTON": { "LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component"
"LOGIN": "Accedi" },
}, "BUTTON": {
"ACTION": { "LOGIN": "Accedi"
"HELP": "BISOGNO DI AIUTO?", },
"REGISTER": "REGISTRATI" "ACTION": {
"HELP": "BISOGNO DI AIUTO?",
"REGISTER": "REGISTRATI"
}
} }
} }
}

View File

@@ -24,8 +24,22 @@ export class AuthenticationMock /*extends AlfrescoAuthenticationService*/ {
login(username: string, password: string): Observable<boolean> { login(username: string, password: string): Observable<boolean> {
if (username === 'fake-username' && password === 'fake-password') { if (username === 'fake-username' && password === 'fake-password') {
return Observable.of(true); return Observable.of(true);
} else {
return Observable.throw('Fake server error');
} }
if (username === 'fake-username-CORS-error' && password === 'fake-password') {
return Observable.throw({
error: {
crossDomain: true,
message: 'ERROR: the network is offline, Origin is not allowed by Access-Control-Allow-Origin'
}
});
}
if (username === 'fake-username-CSRF-error' && password === 'fake-password') {
return Observable.throw({message: 'ERROR: Invalid CSRF-token', status: 403});
}
return Observable.throw('Fake server error');
} }
} }

View File

@@ -264,6 +264,52 @@ describe('AlfrescoLogin', () => {
expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS'); expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS');
}); });
it('should return CORS error when server CORS error occurs', () => {
component.providers = 'ECM';
expect(component.success).toBe(false);
expect(component.error).toBe(false);
usernameInput.value = 'fake-username-CORS-error';
passwordInput.value = 'fake-password';
usernameInput.dispatchEvent(new Event('input'));
passwordInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(component.error).toBe(true);
expect(component.success).toBe(false);
expect(element.querySelector('#login-error')).toBeDefined();
expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CORS');
});
it('should return CSRF error when server CSRF error occurs', () => {
component.providers = 'ECM';
expect(component.success).toBe(false);
expect(component.error).toBe(false);
usernameInput.value = 'fake-username-CSRF-error';
passwordInput.value = 'fake-password';
usernameInput.dispatchEvent(new Event('input'));
passwordInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(component.error).toBe(true);
expect(component.success).toBe(false);
expect(element.querySelector('#login-error')).toBeDefined();
expect(element.querySelector('#login-error').innerText).toEqual('LOGIN.MESSAGES.LOGIN-ERROR-CSRF');
});
it('should emit onSuccess event after the login has succeeded', () => { it('should emit onSuccess event after the login has succeeded', () => {
spyOn(component.onSuccess, 'emit'); spyOn(component.onSuccess, 'emit');
component.providers = 'ECM'; component.providers = 'ECM';

View File

@@ -157,8 +157,8 @@ export class AlfrescoLoginComponent implements OnInit {
this.onSuccess.emit({token: token, username: values.username, password: values.password}); this.onSuccess.emit({token: token, username: values.username, password: values.password});
}, },
(err: any) => { (err: any) => {
this.displayErrorMessage(err);
this.enableError(); this.enableError();
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS';
this.onError.emit(err); this.onError.emit(err);
this.logService.error(err); this.logService.error(err);
}, },
@@ -166,6 +166,24 @@ export class AlfrescoLoginComponent implements OnInit {
); );
} }
/**
* Check and display the right error message in the UI
*/
private displayErrorMessage(err: any): void {
if (err.error && err.error.crossDomain && err.error.message.indexOf('the network is offline, Origin is not allowed by' +
' Access-Control-Allow-Origin') > 0) {
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CORS';
return;
}
if (err.status === 403 && err.message.indexOf('Invalid CSRF-token') > 0) {
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CSRF';
return;
}
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS';
}
/** /**
* Check the require parameter * Check the require parameter
* @returns {boolean} * @returns {boolean}

View File

@@ -1,26 +1,28 @@
{ {
"LOGIN": { "LOGIN": {
"LOGO": "Alfresco", "LOGO": "Alfresco",
"LABEL": { "LABEL": {
"LOGIN": "Login", "LOGIN": "Login",
"USERNAME": "Username", "USERNAME": "Username",
"PASSWORD": "Password", "PASSWORD": "Password",
"REMEMBER": "Remember" "REMEMBER": "Remember"
}, },
"MESSAGES": { "MESSAGES": {
"USERNAME-REQUIRED": "Required", "USERNAME-REQUIRED": "Required",
"USERNAME-MIN": "Your username needs to be at least 4 characters.", "USERNAME-MIN": "Your username needs to be at least 4 characters.",
"PASSWORD-REQUIRED": "Enter your password to sign in", "PASSWORD-REQUIRED": "Enter your password to sign in",
"LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password", "LOGIN-ERROR-CREDENTIALS": "You have entered an invalid username or password",
"LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined", "LOGIN-ERROR-PROVIDERS": "Providers cannot be undefined",
"LOGIN-SUCCESS": "Login successful" "LOGIN-SUCCESS": "Login successful",
}, "LOGIN-ERROR-CORS": "CORS exception, check your server configuration",
"BUTTON": { "LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component"
"LOGIN": "SIGN IN" },
}, "BUTTON": {
"ACTION": { "LOGIN": "SIGN IN"
"HELP": "NEED HELP?", },
"REGISTER": "REGISTER" "ACTION": {
"HELP": "NEED HELP?",
"REGISTER": "REGISTER"
}
} }
}
} }

View File

@@ -1,25 +1,27 @@
{ {
"LOGIN": { "LOGIN": {
"LABEL": { "LABEL": {
"LOGIN": "Autenticazione", "LOGIN": "Autenticazione",
"USERNAME": "Nome utente", "USERNAME": "Nome utente",
"PASSWORD": "Password", "PASSWORD": "Password",
"REMEMBER": "Ricordami" "REMEMBER": "Ricordami"
}, },
"MESSAGES": { "MESSAGES": {
"USERNAME-REQUIRED": "Campo obbligatorio", "USERNAME-REQUIRED": "Campo obbligatorio",
"USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.", "USERNAME-MIN": "Inserire un nome utente di minimo 4 caratteri.",
"PASSWORD-REQUIRED": "Campo obbligatorio", "PASSWORD-REQUIRED": "Campo obbligatorio",
"LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi", "LOGIN-ERROR-CREDENTIALS": "Nome utente o password non validi",
"LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo", "LOGIN-ERROR-PROVIDERS": "Providers non può essere nullo",
"LOGIN-SUCCESS": "Login effettuata con successo" "LOGIN-SUCCESS": "Login effettuata con successo",
}, "LOGIN-ERROR-CORS": "CORS exception, controlla le configurazioni del tuo server",
"BUTTON": { "LOGIN-ERROR-CSRF": "CSRF exception, set [disableCsrf]=\"true\" in alfresco-login component"
"LOGIN": "Accedi" },
}, "BUTTON": {
"ACTION": { "LOGIN": "Accedi"
"HELP": "BISOGNO DI AIUTO?", },
"REGISTER": "REGISTRATI" "ACTION": {
"HELP": "BISOGNO DI AIUTO?",
"REGISTER": "REGISTRATI"
}
} }
} }
}