import { AfterViewInit, Component, Input, OnInit } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { AuthProvider } from '@app/core/common/enum/auth-provider'; import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider'; import { AuthService } from '@app/core/services/auth/auth.service'; import { ConfigurableProvidersService } from '@app/ui/auth/login/utilities/configurableProviders.service'; import { LoginService } from '@app/ui/auth/login/utilities/login.service'; import { BaseComponent } from '@common/base/base.component'; import { environment } from 'environments/environment'; import { takeUntil } from 'rxjs/operators'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { MergeLoginService } from './utilities/merge-login.service'; import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { BehaviorSubject } from 'rxjs'; import { FormControl } from '@angular/forms'; import { OrcidUser } from '@app/core/model/orcid/orcidUser'; import { ZenodoToken } from '@app/core/model/zenodo/zenodo-token.model'; import { LoginInfo } from '@app/core/model/auth/login-info'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; /// /// declare const gapi: any; declare const FB: any; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent extends BaseComponent implements OnInit, AfterViewInit { @Input() redirect: boolean = true; @Input() mergeUsers: boolean; public auth2: any; private returnUrl: string; private twitterUrl = new BehaviorSubject(undefined); private emailFormControl = new FormControl(''); private orcidUser: OrcidUser; private zenodoToken: ZenodoToken; private accessToken: string; private oauthLock: boolean; //public cofigurableProviders: ConfigurableProvider[]; constructor( private router: Router, private route: ActivatedRoute, private loginService: LoginService, private authService: AuthService, public configurableProviderService: ConfigurableProvidersService, private configurationService: ConfigurationService, private mergeLoginService: MergeLoginService, private oauth2DialogService: Oauth2DialogService, private httpClient: HttpClient, private matomoService: MatomoService, ) { super(); } ngOnInit(): void { if(this.authService.current() && (this.redirect == true)){ this.router.navigate(['home']); } this.matomoService.trackPageView('loginPage'); this.route.queryParams .pipe(takeUntil(this._destroyed)) .subscribe((params: Params) => { const returnUrl = params['returnUrl']; if (returnUrl) { this.returnUrl = returnUrl; } }); this.authService.getConfigurableProviders() .pipe(takeUntil(this._destroyed)) .subscribe((data: any) => { this.configurableProviderService.providers = data; }) } ngAfterViewInit() { this.initProviders(); } public linkedInLogin() { //this.router.navigate(['/login/linkedin']); this.oauth2DialogService.login(this.getLinkedInUrl()).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.linkedInLoginUser(result.oauthCode, result.oauthState); this.oauthLock = true; } } else { this.oauthLock = false; } }); } public twitterLogin() { // this.router.navigate(['/login/twitter']); this.twitterUrl.asObservable().pipe(takeUntil(this._destroyed)).subscribe(url => { if (url !== undefined) { this.oauth2DialogService.login(url).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.twitterLoginUser(result.oauthToken, result.oauthVerifier); this.oauthLock = true; } } else { this.oauthLock = false; } }); } }); this.twitterAuthorize(); } public b2AccessLogin() { //this.router.navigate(['/login/external/b2access'], {queryParams: {returnUrl: this.returnUrl, mergeUsers: this.mergeUsers}}); this.oauth2DialogService.login(this.getB2AccessUrl()).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.b2AccessLoginUser(result.oauthCode); this.oauthLock = true; } } else { this.oauthLock = false; } }); } public orcidLogin() { //this.router.navigate(['/login/external/orcid']); this.oauth2DialogService.login(this.getORCIDUrl()).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.orcidLoginUser(result.oauthCode); this.oauthLock = true; } } else { this.oauthLock = false; } }); } public openaireLogin() { //this.router.navigate(['/login/openaire']); this.oauth2DialogService.login(this.getOpenAireUrl()).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.openaireLoginUser(result.oauthCode, result.oauthState); this.oauthLock = true; } } else { this.oauthLock = false; } }); } public configurableLogin(provider: ConfigurableProvider) { this.router.navigate(['/login/configurable/' + provider.configurableLoginId]) } public zenodoLogin() { //this.router.navigate(['/login/external/zenodo']); this.oauth2DialogService.login(this.getZenodoUrl()).pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { if (!this.oauthLock) { this.zenodoLoginUser(result.oauthCode); this.oauthLock = true; } } else { this.oauthLock = false; } }); } public hasFacebookOauth(): boolean { return this.hasProvider(AuthProvider.Facebook); } public hasLinkedInOauth(): boolean { return this.hasProvider(AuthProvider.LinkedIn); } public hasTwitterOauth(): boolean { return this.hasProvider(AuthProvider.Twitter); } public hasGoogleOauth(): boolean { return this.hasProvider(AuthProvider.Google); } public hasB2AccessOauth(): boolean { return this.hasProvider(AuthProvider.B2Access); } public hasOrcidOauth(): boolean { return this.hasProvider(AuthProvider.ORCID); } public hasOpenAireOauth(): boolean { return this.hasProvider(AuthProvider.OpenAire); } public hasZenodoOauth(): boolean { return this.hasProvider(AuthProvider.Zenodo); } public initProviders() { if (this.hasProvider(AuthProvider.Google)) { this.initializeGoogleOauth(); } if (this.hasProvider(AuthProvider.Facebook)) { this.initializeFacebookOauth(); } } public hasProvider(provider: AuthProvider) { for (let i = 0; i < this.configurationService.loginProviders.enabled.length; i++) { if (provider === this.configurationService.loginProviders.enabled[i]) { return this.isProviderProperlyConfigured(provider); } } return false; } private isProviderProperlyConfigured(provider: AuthProvider) { switch (provider) { case AuthProvider.Facebook: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.facebookConfiguration); case AuthProvider.Google: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.googleConfiguration); case AuthProvider.LinkedIn: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.linkedInConfiguration); case AuthProvider.Twitter: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.twitterConfiguration); case AuthProvider.B2Access: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.b2accessConfiguration); case AuthProvider.ORCID: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.orcidConfiguration); case AuthProvider.OpenAire: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.openAireConfiguration); case AuthProvider.Zenodo: return this.hasAllRequiredFieldsConfigured(this.configurationService.loginProviders.zenodoConfiguration); default: throw new Error('Unsupported Provider Type'); } } private hasAllRequiredFieldsConfigured(configuration: any) { if (configuration != null && configuration.clientId != null) { return true; } return false; } /* * GOOGLE SIGN IN */ private initializeGoogleOauth(): void { gapi.load('auth2', () => { this.auth2 = gapi.auth2.init({ client_id: this.configurationService.loginProviders.googleConfiguration.clientId, scope: 'profile email' }); this.attachGoogleSignΙn(document.getElementById('googleSignInButton')); }); } public attachGoogleSignΙn(element) { if (!element) { return; } this.auth2.attachClickHandler(element, {}, (googleUser) => { const id_token = googleUser.getAuthResponse().id_token; if (id_token) { this.authLogin({ ticket: id_token, provider: AuthProvider.Google }); } }, (error) => { }); } /* * FACEBOOK SIGN IN */ private initializeFacebookOauth(): void { FB.init({ appId: this.configurationService.loginProviders.facebookConfiguration.clientId, cookie: false, xfbml: true, version: 'v2.8' }); } public facebookLogin() { FB.login((response: any) => { if (response.status === 'connected' || 'not_authorized') { this.authLogin({ ticket: response.authResponse.accessToken, provider: AuthProvider.Facebook }); } }, { scope: 'email' }); } public hasConfigurableProviders(): boolean { return !(this.configurableProviderService.providers == undefined) && this.configurableProviderService.providers.length > 0 } private getLinkedInUrl() { return this.configurationService.loginProviders.linkedInConfiguration.oauthUrl + '?response_type=code&client_id=' + this.configurationService.loginProviders.linkedInConfiguration.clientId + '&redirect_uri=' + this.configurationService.loginProviders.linkedInConfiguration.redirectUri + '&state=' + this.configurationService.loginProviders.linkedInConfiguration.state + '&scope=r_emailaddress'; } public linkedInLoginUser(code: string, state: string) { if (state !== this.configurationService.loginProviders.linkedInConfiguration.state) { this.router.navigate(['/login']); } this.httpClient.post(this.configurationService.server + 'auth/linkedInRequestToken', { code: code, provider: AuthProvider.LinkedIn }) .pipe(takeUntil(this._destroyed)) .subscribe((data: any) => { this.authLogin({ ticket: data.payload.accessToken, provider: AuthProvider.LinkedIn, data: null }); }); } public twitterAuthorize() { let headers = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); headers = headers.set('Accept', 'application/json'); this.httpClient.get(this.configurationService.server + 'auth/twitterRequestToken', { headers: headers }) .pipe(takeUntil(this._destroyed)) .subscribe((data: any) => { this.twitterUrl.next(this.configurationService.loginProviders.twitterConfiguration.oauthUrl + '?oauth_token=' + data.payload.value); }); } public twitterLoginUser(token: string, verifier: string) { const data = { email: this.emailFormControl.value, verifier: verifier }; this.authLogin({ ticket: token, provider: AuthProvider.Twitter, data: data }); } private getB2AccessUrl() { return this.configurationService.loginProviders.b2accessConfiguration.oauthUrl + '?response_type=code&client_id=' + this.configurationService.loginProviders.b2accessConfiguration.clientId + '&redirect_uri=' + this.configurationService.loginProviders.b2accessConfiguration.redirectUri + '&state=' + this.configurationService.loginProviders.b2accessConfiguration.state + '&scope=USER_PROFILE'; } public b2AccessLoginUser(code: String) { let headers = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); headers = headers.set('Accept', 'application/json'); this.httpClient.post(this.configurationService.server + 'auth/b2AccessRequestToken', { code: code }, { headers: headers }) .pipe(takeUntil(this._destroyed)) .subscribe((data: any) => { this.authLogin({ ticket: data.payload.accessToken, provider: AuthProvider.B2Access, data: null }); }); } private getORCIDUrl() { return this.configurationService.loginProviders.orcidConfiguration.oauthUrl + '?client_id=' + this.configurationService.loginProviders.orcidConfiguration.clientId + '&response_type=code&scope=/authenticate&redirect_uri=' + this.configurationService.loginProviders.orcidConfiguration.redirectUri; } public orcidLoginUser(code: string) { let headers = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); headers = headers.set('Accept', 'application/json'); this.httpClient.post(this.configurationService.server + 'auth/orcidRequestToken', { code: code }, { headers: headers }) .pipe(takeUntil(this._destroyed)) .subscribe((responseData: any) => { this.orcidUser = new OrcidUser(); this.orcidUser.orcidId = responseData.payload.orcidId this.orcidUser.name = responseData.payload.name this.accessToken = responseData.payload.accessToken; this.authLogin({ ticket: this.accessToken, provider: AuthProvider.ORCID, data: this.orcidUser }); }); } private getOpenAireUrl() { return this.configurationService.loginProviders.openAireConfiguration.oauthUrl + '?response_type=code&client_id=' + this.configurationService.loginProviders.openAireConfiguration.clientId + '&redirect_uri=' + this.configurationService.loginProviders.openAireConfiguration.redirectUri + '&state=' + this.configurationService.loginProviders.openAireConfiguration.state + '&scope=openid profile email'; } public openaireLoginUser(code: string, state: string) { if (state !== this.configurationService.loginProviders.openAireConfiguration.state) { this.router.navigate(['/login']) } this.httpClient.post(this.configurationService.server + 'auth/openAireRequestToken', { code: code, provider: AuthProvider.OpenAire }) .pipe(takeUntil(this._destroyed)) .subscribe((data: any) => { this.authLogin({ ticket: data.payload.accessToken, provider: AuthProvider.OpenAire, data: null }); }); } private getZenodoUrl() { return this.configurationService.loginProviders.zenodoConfiguration.oauthUrl + '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' + this.configurationService.loginProviders.zenodoConfiguration.redirectUri; } public zenodoLoginUser(code: string) { let headers = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); headers = headers.set('Accept', 'application/json'); this.httpClient.post(this.configurationService.server + 'auth/zenodoRequestToken', { code: code }, { headers: headers }) .pipe(takeUntil(this._destroyed)) .subscribe((responseData: any) => { this.zenodoToken = new ZenodoToken(); this.zenodoToken.userId = responseData.payload.userId; this.zenodoToken.expiresIn = responseData.payload.expiresIn; this.accessToken = this.zenodoToken.accessToken = responseData.payload.accessToken; this.zenodoToken.email = responseData.payload.email; this.zenodoToken.refreshToken = responseData.payload.refreshToken; this.authLogin({ ticket: this.accessToken, provider: AuthProvider.Zenodo, data: this.zenodoToken }); }); } private authLogin(loginInfo: LoginInfo) { if (this.mergeUsers) { this.authService.mergeLogin(loginInfo) .pipe(takeUntil(this._destroyed)) .subscribe( res => this.mergeLoginService.setRequest({email: res.payload.email, userId: res.payload.id, provider: loginInfo.provider}) ); } else { this.authService.login(loginInfo) .pipe(takeUntil(this._destroyed)) .subscribe( res => this.loginService.onLogInSuccess(res, this.returnUrl), error => this.loginService.onLogInError(error) ); } } }