fix login oauth cookie problem (#3508)

* fix login don't check the cookie in oauth2

* fix test

* check boolean storage
This commit is contained in:
Eugenio Romano
2018-06-20 12:08:35 +01:00
committed by GitHub
parent 061a2e5567
commit ebbf4c30a0
6 changed files with 46 additions and 19 deletions

View File

@@ -27,6 +27,8 @@ Authenticates to Alfresco Content Services and Alfresco Process Services.
- [Customizing validation rules](#customizing-validation-rules) - [Customizing validation rules](#customizing-validation-rules)
- [Call an external identity provider to fetch the auth token](#call-an-external-identity-provider-to-fetch-the-auth-token) - [Call an external identity provider to fetch the auth token](#call-an-external-identity-provider-to-fetch-the-auth-token)
- [Controlling form submit execution behaviour](#controlling-form-submit-execution-behaviour) - [Controlling form submit execution behaviour](#controlling-form-submit-execution-behaviour)
- [SSO login](#sso-login)
- [Implicit Flow](#implicit-flow)
- [See Also](#see-also) - [See Also](#see-also)
@@ -50,7 +52,7 @@ Authenticates to Alfresco Content Services and Alfresco Process Services.
| fieldsValidation | `any` | | Custom validation rules for the login form. | | fieldsValidation | `any` | | Custom validation rules for the login form. |
| logoImageUrl | `string` | "./assets/images/alfresco-logo.svg" | Path to a custom logo image. | | logoImageUrl | `string` | "./assets/images/alfresco-logo.svg" | Path to a custom logo image. |
| needHelpLink | `string` | "" | Sets the URL of the NEED HELP link in the footer. | | needHelpLink | `string` | "" | Sets the URL of the NEED HELP link in the footer. |
| providers | `string` | | Possible valid values are ECM, BPM or ALL. By default, this component will log in only to ECM. If you want to log in in both systems then use ALL. | | providers | `string` | | **Deprecated:** 3.0.0 |
| registerLink | `string` | "" | Sets the URL of the REGISTER link in the footer. | | registerLink | `string` | "" | Sets the URL of the REGISTER link in the footer. |
| showLoginActions | `boolean` | true | Should the extra actions (`Need Help`, `Register`, etc) be shown? | | showLoginActions | `boolean` | true | Should the extra actions (`Need Help`, `Register`, etc) be shown? |
| showRememberMe | `boolean` | true | Should the `Remember me` checkbox be shown? When selected, this option will remember the logged-in user after the browser is closed to avoid logging in repeatedly. | | showRememberMe | `boolean` | true | Should the `Remember me` checkbox be shown? When selected, this option will remember the logged-in user after the browser is closed to avoid logging in repeatedly. |
@@ -275,7 +277,7 @@ export class MyCustomLogin {
### Implicit Flow ### Implicit Flow
If the 'app.config.json' or you used the host-setting component to use the SSO Oauth the login component will show only a button to login: If the 'app.config.json' or you used the host-setting component to use the SSO Oauth the [login component](../core/login.component.md) will show only a button to login:
```JSON ```JSON
"authType" :"OAUTH", "authType" :"OAUTH",
@@ -289,8 +291,8 @@ If the 'app.config.json' or you used the host-setting component to use the SSO O
"redirectUri": "/", "redirectUri": "/",
"redirectUriLogout": "/logout" "redirectUriLogout": "/logout"
}, },
``` ```
![Login component](../docassets/images/sso-login.png) ![Login component](../docassets/images/sso-login.png)
Note if the silentLogin property in the oauth2 configuration is true will not be possible to show the login page. with silentLogin true the application is automatically redirect to the Note if the silentLogin property in the oauth2 configuration is true will not be possible to show the login page. with silentLogin true the application is automatically redirect to the

View File

@@ -25,6 +25,7 @@ import { AuthenticationService } from '../../services/authentication.service';
import { LogService } from '../../services/log.service'; import { LogService } from '../../services/log.service';
import { TranslationService } from '../../services/translation.service'; import { TranslationService } from '../../services/translation.service';
import { UserPreferencesService } from '../../services/user-preferences.service'; import { UserPreferencesService } from '../../services/user-preferences.service';
import { SettingsService } from '../../services/settings.service';
import { LoginErrorEvent } from '../models/login-error.event'; import { LoginErrorEvent } from '../models/login-error.event';
import { LoginSubmitEvent } from '../models/login-submit.event'; import { LoginSubmitEvent } from '../models/login-submit.event';
@@ -86,9 +87,8 @@ export class LoginComponent implements OnInit {
@Input() @Input()
copyrightText: string = '\u00A9 2016 Alfresco Software, Inc. All Rights Reserved.'; copyrightText: string = '\u00A9 2016 Alfresco Software, Inc. All Rights Reserved.';
/** Possible valid values are ECM, BPM or ALL. /** @deprecated 3.0.0 Possible valid values are ECM, BPM or ALL.
* deprecated in 2.4.0 use the providers property in the the app.config.json * deprecated in 3.0.0 use the providers property in the the app.config.json
* @deprecated 2.4.0
*/ */
@Input() @Input()
providers: string; providers: string;
@@ -97,7 +97,7 @@ export class LoginComponent implements OnInit {
@Input() @Input()
fieldsValidation: any; fieldsValidation: any;
/** Prevents the CSRF Token from being submitted. Only valid for Alfresco Process Services. */ /** @depreated 3.0.0 Prevents the CSRF Token from being submitted. Only valid for Alfresco Process Services. */
@Input() @Input()
disableCsrf: boolean; disableCsrf: boolean;
@@ -147,7 +147,8 @@ export class LoginComponent implements OnInit {
private elementRef: ElementRef, private elementRef: ElementRef,
private router: Router, private router: Router,
private appConfig: AppConfigService, private appConfig: AppConfigService,
private userPreferences: UserPreferencesService private userPreferences: UserPreferencesService,
private settingsService: SettingsService
) { ) {
this.initFormError(); this.initFormError();
this.initFormFieldsMessages(); this.initFormFieldsMessages();
@@ -176,9 +177,8 @@ export class LoginComponent implements OnInit {
* @param event * @param event
*/ */
onSubmit(values: any) { onSubmit(values: any) {
if (this.disableCsrf !== null && this.disableCsrf !== undefined) { this.settingsService.setProviders(this.providers);
this.appConfig.get<boolean>(AppConfigValues.DISABLECSRF); this.settingsService.csrfDisabled = this.disableCsrf;
}
this.disableError(); this.disableError();
const args = new LoginSubmitEvent({ const args = new LoginSubmitEvent({

View File

@@ -104,7 +104,9 @@ export class AlfrescoApiService {
return this.getInstance().core.groupsApi; return this.getInstance().core.groupsApi;
} }
constructor(protected appConfig: AppConfigService, protected storage: StorageService) {} constructor(protected appConfig: AppConfigService,
protected storage: StorageService) {
}
async load() { async load() {
await this.appConfig.load().then(() => { await this.appConfig.load().then(() => {
@@ -124,13 +126,13 @@ export class AlfrescoApiService {
} }
const config = { const config = {
provider: this.appConfig.get<string>(AppConfigValues.PROVIDERS), provider: this.getProvider(),
hostEcm: this.appConfig.get<string>(AppConfigValues.ECMHOST), hostEcm: this.appConfig.get<string>(AppConfigValues.ECMHOST),
hostBpm: this.appConfig.get<string>(AppConfigValues.BPMHOST), hostBpm: this.appConfig.get<string>(AppConfigValues.BPMHOST),
authType: this.appConfig.get<string>(AppConfigValues.AUTHTYPE, 'BASIC'), authType: this.appConfig.get<string>(AppConfigValues.AUTHTYPE, 'BASIC'),
contextRootBpm: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTBPM), contextRootBpm: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTBPM),
contextRoot: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTECM), contextRoot: this.appConfig.get<string>(AppConfigValues.CONTEXTROOTECM),
disableCsrf: this.storage.getItem('DISABLE_CSRF') === 'true', disableCsrf: this.getDisableCSRF(),
oauth2: oauth oauth2: oauth
}; };
@@ -140,4 +142,18 @@ export class AlfrescoApiService {
this.alfrescoApi = <AlfrescoApi> new alfrescoApi(config); this.alfrescoApi = <AlfrescoApi> new alfrescoApi(config);
} }
} }
// @deprecated 3.0.0 get only from app config
private getDisableCSRF(): boolean {
if (this.storage.getItem(AppConfigValues.DISABLECSRF) === 'true') {
return true;
} else {
return this.appConfig.get<boolean>(AppConfigValues.DISABLECSRF);
}
}
// @deprecated 3.0.0 get only from app config
private getProvider() {
return this.storage.getItem(AppConfigValues.PROVIDERS) || this.appConfig.get<string>(AppConfigValues.PROVIDERS);
}
} }

View File

@@ -128,6 +128,7 @@ describe('AuthenticationService', () => {
it('should require remember me set for ECM check', () => { it('should require remember me set for ECM check', () => {
spyOn(cookie, 'isEnabled').and.returnValue(true); spyOn(cookie, 'isEnabled').and.returnValue(true);
spyOn(authService, 'isRememberMeSet').and.returnValue(false); spyOn(authService, 'isRememberMeSet').and.returnValue(false);
spyOn(authService, 'isOauth').and.returnValue(false);
spyOn(apiService, 'getInstance').and.callThrough(); spyOn(apiService, 'getInstance').and.callThrough();
expect(authService.isEcmLoggedIn()).toBeFalsy(); expect(authService.isEcmLoggedIn()).toBeFalsy();
@@ -137,6 +138,7 @@ describe('AuthenticationService', () => {
it('should not require cookie service enabled for ECM check', () => { it('should not require cookie service enabled for ECM check', () => {
spyOn(cookie, 'isEnabled').and.returnValue(false); spyOn(cookie, 'isEnabled').and.returnValue(false);
spyOn(authService, 'isRememberMeSet').and.returnValue(false); spyOn(authService, 'isRememberMeSet').and.returnValue(false);
spyOn(authService, 'isOauth').and.returnValue(false);
spyOn(apiService, 'getInstance').and.callThrough(); spyOn(apiService, 'getInstance').and.callThrough();
expect(authService.isEcmLoggedIn()).toBeFalsy(); expect(authService.isEcmLoggedIn()).toBeFalsy();
@@ -230,6 +232,7 @@ describe('AuthenticationService', () => {
it('should require remember me set for BPM check', () => { it('should require remember me set for BPM check', () => {
spyOn(cookie, 'isEnabled').and.returnValue(true); spyOn(cookie, 'isEnabled').and.returnValue(true);
spyOn(authService, 'isRememberMeSet').and.returnValue(false); spyOn(authService, 'isRememberMeSet').and.returnValue(false);
spyOn(authService, 'isOauth').and.returnValue(false);
spyOn(apiService, 'getInstance').and.callThrough(); spyOn(apiService, 'getInstance').and.callThrough();
expect(authService.isBpmLoggedIn()).toBeFalsy(); expect(authService.isBpmLoggedIn()).toBeFalsy();

View File

@@ -164,7 +164,7 @@ export class AuthenticationService {
* @returns True if logged in, false otherwise * @returns True if logged in, false otherwise
*/ */
isEcmLoggedIn(): boolean { isEcmLoggedIn(): boolean {
if (this.cookie.isEnabled() && !this.isRememberMeSet()) { if (!this.isOauth() && this.cookie.isEnabled() && !this.isRememberMeSet()) {
return false; return false;
} }
return this.alfrescoApi.getInstance().isEcmLoggedIn(); return this.alfrescoApi.getInstance().isEcmLoggedIn();
@@ -175,7 +175,7 @@ export class AuthenticationService {
* @returns True if logged in, false otherwise * @returns True if logged in, false otherwise
*/ */
isBpmLoggedIn(): boolean { isBpmLoggedIn(): boolean {
if (this.cookie.isEnabled() && !this.isRememberMeSet()) { if (!this.isOauth() && this.cookie.isEnabled() && !this.isRememberMeSet()) {
return false; return false;
} }
return this.alfrescoApi.getInstance().isBpmLoggedIn(); return this.alfrescoApi.getInstance().isBpmLoggedIn();

View File

@@ -18,12 +18,14 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { LogService } from './log.service'; import { LogService } from './log.service';
import { StorageService } from './storage.service';
@Injectable() @Injectable()
export class SettingsService { export class SettingsService {
constructor(private appConfig: AppConfigService, constructor(private appConfig: AppConfigService,
private logService: LogService) { private logService: LogService,
private storage: StorageService) {
} }
/** @deprecated in 1.6.0 */ /** @deprecated in 1.6.0 */
@@ -35,6 +37,9 @@ export class SettingsService {
/** @deprecated in 1.7.0 */ /** @deprecated in 1.7.0 */
public set csrfDisabled(csrfDisabled: boolean) { public set csrfDisabled(csrfDisabled: boolean) {
this.logService.log(`SettingsService.csrfDisabled is deprecated. Use UserPreferencesService.disableCSRF instead.`); this.logService.log(`SettingsService.csrfDisabled is deprecated. Use UserPreferencesService.disableCSRF instead.`);
if (csrfDisabled !== null && csrfDisabled !== undefined) {
this.storage.setItem(AppConfigValues.DISABLECSRF, csrfDisabled.toString());
}
} }
/** @deprecated in 1.6.0 */ /** @deprecated in 1.6.0 */
@@ -62,11 +67,12 @@ export class SettingsService {
/** @deprecated in 1.7.0 */ /** @deprecated in 1.7.0 */
public getProviders(): string { public getProviders(): string {
this.logService.log(`SettingsService.getProviders is deprecated. Use UserPreferencesService.authType instead.`); this.logService.log(`SettingsService.getProviders is deprecated. Use UserPreferencesService.authType instead.`);
return this.appConfig.get<string>(AppConfigValues.PROVIDERS); return this.storage.getItem(AppConfigValues.PROVIDERS) || this.appConfig.get<string>(AppConfigValues.PROVIDERS);
} }
/** @deprecated in 1.7.0 */ /** @deprecated in 1.7.0 */
public setProviders(providers: string) { public setProviders(providers: string) {
this.logService.log(`SettingsService.aetProviders is deprecated. Use the app-config.json`); this.logService.log(`SettingsService.aetProviders is deprecated. Use the app-config.json`);
this.storage.setItem(AppConfigValues.PROVIDERS, providers);
} }
} }