[CST-5668] Create and abstract component for authentication with external providers

This commit is contained in:
Giuseppe Digilio
2022-06-10 19:27:40 +02:00
parent 03369b8e10
commit 10f4f80f0d
4 changed files with 125 additions and 285 deletions

View File

@@ -0,0 +1,110 @@
import { Component, Inject, OnInit, } from '@angular/core';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { select, Store } from '@ngrx/store';
import { AuthMethod } from '../../../core/auth/models/auth.method';
import { isAuthenticated, isAuthenticationLoading } from '../../../core/auth/selectors';
import { NativeWindowRef, NativeWindowService } from '../../../core/services/window.service';
import { isEmpty, isNotNull } from '../../empty.util';
import { AuthService } from '../../../core/auth/auth.service';
import { HardRedirectService } from '../../../core/services/hard-redirect.service';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { CoreState } from '../../../core/core-state.model';
@Component({
selector: 'ds-log-in-external-provider',
template: ''
})
export abstract class LogInExternalProviderComponent implements OnInit {
/**
* The authentication method data.
* @type {AuthMethod}
*/
public authMethod: AuthMethod;
/**
* True if the authentication is loading.
* @type {boolean}
*/
public loading: Observable<boolean>;
/**
* The shibboleth authentication location url.
* @type {string}
*/
public location: string;
/**
* Whether user is authenticated.
* @type {Observable<string>}
*/
public isAuthenticated: Observable<boolean>;
/**
* @constructor
* @param {AuthMethod} injectedAuthMethodModel
* @param {boolean} isStandalonePage
* @param {NativeWindowRef} _window
* @param {AuthService} authService
* @param {HardRedirectService} hardRedirectService
* @param {Store<State>} store
*/
constructor(
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
@Inject('isStandalonePage') public isStandalonePage: boolean,
@Inject(NativeWindowService) protected _window: NativeWindowRef,
private authService: AuthService,
private hardRedirectService: HardRedirectService,
private store: Store<CoreState>
) {
this.authMethod = injectedAuthMethodModel;
}
ngOnInit(): void {
// set isAuthenticated
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
// set loading
this.loading = this.store.pipe(select(isAuthenticationLoading));
// set location
this.location = decodeURIComponent(this.injectedAuthMethodModel.location);
}
/**
* Redirect to the external provider url for login
*/
redirectToExternalProvider() {
this.authService.getRedirectUrl().pipe(take(1)).subscribe((redirectRoute) => {
if (!this.isStandalonePage) {
redirectRoute = this.hardRedirectService.getCurrentRoute();
} else if (isEmpty(redirectRoute)) {
redirectRoute = '/';
}
const correctRedirectUrl = new URLCombiner(this._window.nativeWindow.origin, redirectRoute).toString();
let externalServerUrl = this.location;
const myRegexp = /\?redirectUrl=(.*)/g;
const match = myRegexp.exec(this.location);
const redirectUrlFromServer = (match && match[1]) ? match[1] : null;
// Check whether the current page is different from the redirect url received from rest
if (isNotNull(redirectUrlFromServer) && redirectUrlFromServer !== correctRedirectUrl) {
// change the redirect url with the current page url
const newRedirectUrl = `?redirectUrl=${correctRedirectUrl}`;
externalServerUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl);
}
// redirect to shibboleth authentication url
this.hardRedirectService.redirect(externalServerUrl);
});
}
}

View File

@@ -1,110 +1,21 @@
import { Component, Inject, OnInit, } from '@angular/core'; import { Component, } from '@angular/core';
import { Observable } from 'rxjs';
import { select, Store } from '@ngrx/store';
import { renderAuthMethodFor } from '../log-in.methods-decorator'; import { renderAuthMethodFor } from '../log-in.methods-decorator';
import { AuthMethodType } from '../../../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../../../core/auth/models/auth.method-type';
import { AuthMethod } from '../../../../core/auth/models/auth.method'; import { LogInExternalProviderComponent } from '../log-in-external-provider.component';
import { isAuthenticated, isAuthenticationLoading } from '../../../../core/auth/selectors';
import { NativeWindowRef, NativeWindowService } from '../../../../core/services/window.service';
import { isNotNull, isEmpty } from '../../../empty.util';
import { AuthService } from '../../../../core/auth/auth.service';
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
import { take } from 'rxjs/operators';
import { URLCombiner } from '../../../../core/url-combiner/url-combiner';
import { CoreState } from '../../../../core/core-state.model';
@Component({ @Component({
selector: 'ds-log-in-oidc', selector: 'ds-log-in-oidc',
templateUrl: './log-in-oidc.component.html', templateUrl: './log-in-oidc.component.html',
}) })
@renderAuthMethodFor(AuthMethodType.Oidc) @renderAuthMethodFor(AuthMethodType.Oidc)
export class LogInOidcComponent implements OnInit { export class LogInOidcComponent extends LogInExternalProviderComponent {
/** /**
* The authentication method data. * Redirect to orcid authentication url
* @type {AuthMethod}
*/ */
public authMethod: AuthMethod;
/**
* True if the authentication is loading.
* @type {boolean}
*/
public loading: Observable<boolean>;
/**
* The oidc authentication location url.
* @type {string}
*/
public location: string;
/**
* Whether user is authenticated.
* @type {Observable<string>}
*/
public isAuthenticated: Observable<boolean>;
/**
* @constructor
* @param {AuthMethod} injectedAuthMethodModel
* @param {boolean} isStandalonePage
* @param {NativeWindowRef} _window
* @param {AuthService} authService
* @param {HardRedirectService} hardRedirectService
* @param {Store<State>} store
*/
constructor(
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
@Inject('isStandalonePage') public isStandalonePage: boolean,
@Inject(NativeWindowService) protected _window: NativeWindowRef,
private authService: AuthService,
private hardRedirectService: HardRedirectService,
private store: Store<CoreState>
) {
this.authMethod = injectedAuthMethodModel;
}
ngOnInit(): void {
// set isAuthenticated
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
// set loading
this.loading = this.store.pipe(select(isAuthenticationLoading));
// set location
this.location = decodeURIComponent(this.injectedAuthMethodModel.location);
}
redirectToOidc() { redirectToOidc() {
this.redirectToExternalProvider();
this.authService.getRedirectUrl().pipe(take(1)).subscribe((redirectRoute) => {
if (!this.isStandalonePage) {
redirectRoute = this.hardRedirectService.getCurrentRoute();
} else if (isEmpty(redirectRoute)) {
redirectRoute = '/';
}
const correctRedirectUrl = new URLCombiner(this._window.nativeWindow.origin, redirectRoute).toString();
let oidcServerUrl = this.location;
const myRegexp = /\?redirectUrl=(.*)/g;
const match = myRegexp.exec(this.location);
const redirectUrlFromServer = (match && match[1]) ? match[1] : null;
// Check whether the current page is different from the redirect url received from rest
if (isNotNull(redirectUrlFromServer) && redirectUrlFromServer !== correctRedirectUrl) {
// change the redirect url with the current page url
const newRedirectUrl = `?redirectUrl=${correctRedirectUrl}`;
oidcServerUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl);
}
// redirect to oidc authentication url
this.hardRedirectService.redirect(oidcServerUrl);
});
} }
} }

View File

@@ -1,110 +1,21 @@
import { Component, Inject, OnInit, } from '@angular/core'; import { Component, } from '@angular/core';
import { Observable } from 'rxjs';
import { select, Store } from '@ngrx/store';
import { renderAuthMethodFor } from '../log-in.methods-decorator'; import { renderAuthMethodFor } from '../log-in.methods-decorator';
import { AuthMethodType } from '../../../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../../../core/auth/models/auth.method-type';
import { AuthMethod } from '../../../../core/auth/models/auth.method'; import { LogInExternalProviderComponent } from '../log-in-external-provider.component';
import { isAuthenticated, isAuthenticationLoading } from '../../../../core/auth/selectors';
import { NativeWindowRef, NativeWindowService } from '../../../../core/services/window.service';
import { isNotNull, isEmpty } from '../../../empty.util';
import { AuthService } from '../../../../core/auth/auth.service';
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
import { take } from 'rxjs/operators';
import { URLCombiner } from '../../../../core/url-combiner/url-combiner';
import {CoreState} from '../../../../core/core-state.model';
@Component({ @Component({
selector: 'ds-log-in-orcid', selector: 'ds-log-in-orcid',
templateUrl: './log-in-orcid.component.html', templateUrl: './log-in-orcid.component.html',
}) })
@renderAuthMethodFor(AuthMethodType.Orcid) @renderAuthMethodFor(AuthMethodType.Orcid)
export class LogInOrcidComponent implements OnInit { export class LogInOrcidComponent extends LogInExternalProviderComponent {
/** /**
* The authentication method data. * Redirect to orcid authentication url
* @type {AuthMethod}
*/ */
public authMethod: AuthMethod;
/**
* True if the authentication is loading.
* @type {boolean}
*/
public loading: Observable<boolean>;
/**
* The orcid authentication location url.
* @type {string}
*/
public location: string;
/**
* Whether user is authenticated.
* @type {Observable<string>}
*/
public isAuthenticated: Observable<boolean>;
/**
* @constructor
* @param {AuthMethod} injectedAuthMethodModel
* @param {boolean} isStandalonePage
* @param {NativeWindowRef} _window
* @param {AuthService} authService
* @param {HardRedirectService} hardRedirectService
* @param {Store<State>} store
*/
constructor(
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
@Inject('isStandalonePage') public isStandalonePage: boolean,
@Inject(NativeWindowService) protected _window: NativeWindowRef,
private authService: AuthService,
private hardRedirectService: HardRedirectService,
private store: Store<CoreState>
) {
this.authMethod = injectedAuthMethodModel;
}
ngOnInit(): void {
// set isAuthenticated
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
// set loading
this.loading = this.store.pipe(select(isAuthenticationLoading));
// set location
this.location = decodeURIComponent(this.injectedAuthMethodModel.location);
}
redirectToOrcid() { redirectToOrcid() {
this.redirectToExternalProvider();
this.authService.getRedirectUrl().pipe(take(1)).subscribe((redirectRoute) => {
if (!this.isStandalonePage) {
redirectRoute = this.hardRedirectService.getCurrentRoute();
} else if (isEmpty(redirectRoute)) {
redirectRoute = '/';
}
const correctRedirectUrl = new URLCombiner(this._window.nativeWindow.origin, redirectRoute).toString();
let orcidServerUrl = this.location;
const myRegexp = /\?redirectUrl=(.*)/g;
const match = myRegexp.exec(this.location);
const redirectUrlFromServer = (match && match[1]) ? match[1] : null;
// Check whether the current page is different from the redirect url received from rest
if (isNotNull(redirectUrlFromServer) && redirectUrlFromServer !== correctRedirectUrl) {
// change the redirect url with the current page url
const newRedirectUrl = `?redirectUrl=${correctRedirectUrl}`;
orcidServerUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl);
}
// redirect to orcid authentication url
this.hardRedirectService.redirect(orcidServerUrl);
});
} }
} }

View File

@@ -1,21 +1,8 @@
import { Component, Inject, OnInit, } from '@angular/core'; import { Component, } from '@angular/core';
import { Observable } from 'rxjs';
import { select, Store } from '@ngrx/store';
import { renderAuthMethodFor } from '../log-in.methods-decorator'; import { renderAuthMethodFor } from '../log-in.methods-decorator';
import { AuthMethodType } from '../../../../core/auth/models/auth.method-type'; import { AuthMethodType } from '../../../../core/auth/models/auth.method-type';
import { AuthMethod } from '../../../../core/auth/models/auth.method'; import { LogInExternalProviderComponent } from '../log-in-external-provider.component';
import { isAuthenticated, isAuthenticationLoading } from '../../../../core/auth/selectors';
import { RouteService } from '../../../../core/services/route.service';
import { NativeWindowRef, NativeWindowService } from '../../../../core/services/window.service';
import { isNotNull, isEmpty } from '../../../empty.util';
import { AuthService } from '../../../../core/auth/auth.service';
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
import { take } from 'rxjs/operators';
import { URLCombiner } from '../../../../core/url-combiner/url-combiner';
import { CoreState } from '../../../../core/core-state.model';
@Component({ @Component({
selector: 'ds-log-in-shibboleth', selector: 'ds-log-in-shibboleth',
@@ -24,92 +11,13 @@ import { CoreState } from '../../../../core/core-state.model';
}) })
@renderAuthMethodFor(AuthMethodType.Shibboleth) @renderAuthMethodFor(AuthMethodType.Shibboleth)
export class LogInShibbolethComponent implements OnInit { export class LogInShibbolethComponent extends LogInExternalProviderComponent {
/** /**
* The authentication method data. * Redirect to shibboleth authentication url
* @type {AuthMethod}
*/ */
public authMethod: AuthMethod;
/**
* True if the authentication is loading.
* @type {boolean}
*/
public loading: Observable<boolean>;
/**
* The shibboleth authentication location url.
* @type {string}
*/
public location: string;
/**
* Whether user is authenticated.
* @type {Observable<string>}
*/
public isAuthenticated: Observable<boolean>;
/**
* @constructor
* @param {AuthMethod} injectedAuthMethodModel
* @param {boolean} isStandalonePage
* @param {NativeWindowRef} _window
* @param {RouteService} route
* @param {AuthService} authService
* @param {HardRedirectService} hardRedirectService
* @param {Store<State>} store
*/
constructor(
@Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod,
@Inject('isStandalonePage') public isStandalonePage: boolean,
@Inject(NativeWindowService) protected _window: NativeWindowRef,
private route: RouteService,
private authService: AuthService,
private hardRedirectService: HardRedirectService,
private store: Store<CoreState>
) {
this.authMethod = injectedAuthMethodModel;
}
ngOnInit(): void {
// set isAuthenticated
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
// set loading
this.loading = this.store.pipe(select(isAuthenticationLoading));
// set location
this.location = decodeURIComponent(this.injectedAuthMethodModel.location);
}
redirectToShibboleth() { redirectToShibboleth() {
this.redirectToExternalProvider();
this.authService.getRedirectUrl().pipe(take(1)).subscribe((redirectRoute) => {
if (!this.isStandalonePage) {
redirectRoute = this.hardRedirectService.getCurrentRoute();
} else if (isEmpty(redirectRoute)) {
redirectRoute = '/';
}
const correctRedirectUrl = new URLCombiner(this._window.nativeWindow.origin, redirectRoute).toString();
let shibbolethServerUrl = this.location;
const myRegexp = /\?redirectUrl=(.*)/g;
const match = myRegexp.exec(this.location);
const redirectUrlFromServer = (match && match[1]) ? match[1] : null;
// Check whether the current page is different from the redirect url received from rest
if (isNotNull(redirectUrlFromServer) && redirectUrlFromServer !== correctRedirectUrl) {
// change the redirect url with the current page url
const newRedirectUrl = `?redirectUrl=${correctRedirectUrl}`;
shibbolethServerUrl = this.location.replace(/\?redirectUrl=(.*)/g, newRedirectUrl);
}
// redirect to shibboleth authentication url
this.hardRedirectService.redirect(shibbolethServerUrl);
});
} }
} }