Added further dynamic authentication methods

This commit is contained in:
Julius Gruber
2019-08-08 11:05:12 +02:00
parent bcc6daa39f
commit 3b6a20bf67
11 changed files with 12 additions and 70 deletions

View File

@@ -399,7 +399,6 @@
"volume-title": "Volume Title", "volume-title": "Volume Title",
"publisher": "Publisher", "publisher": "Publisher",
"description": "Description" "description": "Description"
}, },
"listelement": { "listelement": {
"badge": "Publication" "badge": "Publication"
@@ -924,14 +923,14 @@
}, },
"login": { "login": {
"title": "Login", "title": "Login",
"shibboleth": "Shibboleth",
"form": { "form": {
"header": "Please log in to DSpace", "header": "Please log in to DSpace",
"email": "Email address", "email": "Email address",
"forgot-password": "Have you forgotten your password?", "forgot-password": "Have you forgotten your password?",
"new-user": "New user? Click here to register.", "new-user": "New user? Click here to register.",
"password": "Password", "password": "Password",
"submit": "Log in", "submit": "Log in"
"ssoLogin": "Shibboleth"
} }
}, },
"logout": { "logout": {

View File

@@ -2,13 +2,11 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { LoginPageComponent } from './login-page.component'; import { LoginPageComponent } from './login-page.component';
import {ShibbolethComponent} from './shibboleth/shibboleth.component';
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule.forChild([ RouterModule.forChild([
{ path: '', pathMatch: 'full', component: LoginPageComponent, data: { title: 'login.title' } } { path: '', pathMatch: 'full', component: LoginPageComponent, data: { title: 'login.title' } }
/* { path: 'shibboleth', component: ShibbolethComponent }*/
]) ])
] ]
}) })

View File

@@ -4,7 +4,6 @@ import { SharedModule } from '../shared/shared.module';
import { LoginPageComponent } from './login-page.component'; import { LoginPageComponent } from './login-page.component';
import { LoginPageRoutingModule } from './login-page-routing.module'; import { LoginPageRoutingModule } from './login-page-routing.module';
@NgModule({ @NgModule({
imports: [ imports: [
LoginPageRoutingModule, LoginPageRoutingModule,

View File

@@ -3,7 +3,7 @@ import {RouterModule} from '@angular/router';
import {PageNotFoundComponent} from './pagenotfound/pagenotfound.component'; import {PageNotFoundComponent} from './pagenotfound/pagenotfound.component';
import {AuthenticatedGuard} from './core/auth/authenticated.guard'; import {AuthenticatedGuard} from './core/auth/authenticated.guard';
import {ShibbolethComponent} from './+login-page/shibboleth/shibboleth.component'; import {ShibbolethComponent} from './+login-page/shibbolethTargetPage/shibboleth.component';
const ITEM_MODULE_PATH = 'items'; const ITEM_MODULE_PATH = 'items';

View File

@@ -39,7 +39,7 @@ import { ExpandableAdminSidebarSectionComponent } from './+admin/admin-sidebar/e
import { NavbarModule } from './navbar/navbar.module'; import { NavbarModule } from './navbar/navbar.module';
import { JournalEntitiesModule } from './entity-groups/journal-entities/journal-entities.module'; import { JournalEntitiesModule } from './entity-groups/journal-entities/journal-entities.module';
import { ResearchEntitiesModule } from './entity-groups/research-entities/research-entities.module'; import { ResearchEntitiesModule } from './entity-groups/research-entities/research-entities.module';
import { ShibbolethComponent } from './+login-page/shibboleth/shibboleth.component'; import { ShibbolethComponent } from './+login-page/shibbolethTargetPage/shibboleth.component';
export function getConfig() { export function getConfig() {
return ENV_CONFIG; return ENV_CONFIG;

View File

@@ -43,9 +43,7 @@ export class AuthRequestService {
public postToEndpoint(method: string, body?: any, options?: HttpOptions): Observable<any> { public postToEndpoint(method: string, body?: any, options?: HttpOptions): Observable<any> {
return this.halService.getEndpoint(this.linkName).pipe( return this.halService.getEndpoint(this.linkName).pipe(
filter((href: string) => isNotEmpty(href)), filter((href: string) => isNotEmpty(href)),
tap((href: string) => console.log('This is href in postToEndpoint(): ' , href)),
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
tap((href2) => {console.log('href2', href2)}),
distinctUntilChanged(), distinctUntilChanged(),
map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)), map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)),
tap((request: PostRequest) => this.requestService.configure(request, true)), tap((request: PostRequest) => this.requestService.configure(request, true)),
@@ -57,9 +55,7 @@ export class AuthRequestService {
console.log('auth.request getRequest() was called'); console.log('auth.request getRequest() was called');
return this.halService.getEndpoint(this.linkName).pipe( return this.halService.getEndpoint(this.linkName).pipe(
filter((href: string) => isNotEmpty(href)), filter((href: string) => isNotEmpty(href)),
tap((href) => console.log('auth-request.service getRequest()', href)),
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
tap((whatsThis) => console.log('whatsThis: ', whatsThis)),
distinctUntilChanged(), distinctUntilChanged(),
map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)), map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)),
tap((request: GetRequest) => this.requestService.configure(request, true)), tap((request: GetRequest) => this.requestService.configure(request, true)),

View File

@@ -74,10 +74,8 @@ export class AuthInterceptor implements HttpInterceptor {
} }
private parseAuthMethodsfromHeaders(headers: HttpHeaders): AuthMethodModel[] { private parseAuthMethodsfromHeaders(headers: HttpHeaders): AuthMethodModel[] {
// console.log('parseAuthMethodsfromHeaders(): ', headers);
const authMethodModels: AuthMethodModel[] = []; const authMethodModels: AuthMethodModel[] = [];
const parts: string[] = headers.get('www-authenticate').split(','); const parts: string[] = headers.get('www-authenticate').split(',');
console.log('parts: ', parts);
// get the login methods names // get the login methods names
// tslint:disable-next-line:forin // tslint:disable-next-line:forin
for (const i in parts) { for (const i in parts) {
@@ -89,14 +87,15 @@ export class AuthInterceptor implements HttpInterceptor {
// if so the next part is the shibboleth location // if so the next part is the shibboleth location
// e.g part i: shibboleth realm="DSpace REST API", part i+1: location="/Shibboleth.sso/Login?target=https://serverUrl" // e.g part i: shibboleth realm="DSpace REST API", part i+1: location="/Shibboleth.sso/Login?target=https://serverUrl"
if (methodName.includes('shibboleth')) { if (methodName.includes('shibboleth')) {
const location: string = this.parseShibbolethLocation(parts[+i + 1]); // +1: unaray + operator is necessaray because i is a string, the operator works like parseInt() // +1: unaray + operator in the next line is necessaray because i is a string, the operator works like parseInt()
// console.log('shib location: ', location); const location: string = this.parseShibbolethLocation(parts[+i + 1]);
authMethod.location = location; authMethod.location = location;
} }
// if other authentication methods deliver data needed for the method to work
// it would be checked here e.g. if (methodName.includes('ldap')) { }
authMethodModels.push(authMethod); authMethodModels.push(authMethod);
} }
} }
// console.log('Array of AuthMethodModels: ', authMethodModels);
return authMethodModels; return authMethodModels;
} }
@@ -183,13 +182,11 @@ export class AuthInterceptor implements HttpInterceptor {
} }
}), }),
catchError((error, caught) => { catchError((error, caught) => {
console.log('catchError operator in auth.interceptor was triggered');
// Intercept an error response // Intercept an error response
if (error instanceof HttpErrorResponse) { if (error instanceof HttpErrorResponse) {
// Checks if is a response from a request to an authentication endpoint // Checks if is a response from a request to an authentication endpoint
if (this.isAuthRequest(error)) { if (this.isAuthRequest(error)) {
console.log('catchError isAuthRequest=true');
// clean eventually refresh Requests list // clean eventually refresh Requests list
this.refreshTokenRequestUrls = []; this.refreshTokenRequestUrls = [];

View File

@@ -12,8 +12,8 @@ import {
SetRedirectUrlAction SetRedirectUrlAction
} from './auth.actions'; } from './auth.actions';
// import models // import models
import { EPerson } from '../eperson/models/eperson.model'; import {EPerson} from '../eperson/models/eperson.model';
import { AuthTokenInfo } from './models/auth-token-info.model'; import {AuthTokenInfo} from './models/auth-token-info.model';
import {AuthMethodModel} from './models/auth-method.model'; import {AuthMethodModel} from './models/auth-method.model';
/** /**
@@ -200,15 +200,13 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
info: undefined, info: undefined,
}); });
// next three cases are used by shibboleth login // next three cases are used by dynamic rendering of login methods
case AuthActionTypes.RETRIEVE_AUTH_METHODS: case AuthActionTypes.RETRIEVE_AUTH_METHODS:
console.log('case AuthActionTypes.RETRIEVE_AUTH_METHODS');
return Object.assign({}, state, { return Object.assign({}, state, {
loading: true loading: true
}); });
case AuthActionTypes.RETRIEVE_AUTH_METHODS_SUCCESS: case AuthActionTypes.RETRIEVE_AUTH_METHODS_SUCCESS:
console.log('case RETRIEVE_AUTH_METHODS_SUCCESS');
return Object.assign({}, state, { return Object.assign({}, state, {
loading: false, loading: false,
authMethods: (action as RetrieveAuthMethodsSuccessAction).payload authMethods: (action as RetrieveAuthMethodsSuccessAction).payload

View File

@@ -224,8 +224,6 @@ export class AuthService {
* @returns {User} * @returns {User}
*/ */
public retrieveAuthMethods(): Observable<AuthMethodModel[]> { public retrieveAuthMethods(): Observable<AuthMethodModel[]> {
console.log('auth.service retrieveAuthMethods() was called');
// return this.authRequestService.getRequest('login').pipe(
return this.authRequestService.postToEndpoint('login', {}).pipe( return this.authRequestService.postToEndpoint('login', {}).pipe(
map((status: AuthStatus) => { map((status: AuthStatus) => {
let authMethods: AuthMethodModel[]; let authMethods: AuthMethodModel[];
@@ -237,8 +235,6 @@ export class AuthService {
) )
} }
/** /**
* Create a new user * Create a new user
* @returns {User} * @returns {User}

View File

@@ -26,33 +26,6 @@
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit" <button class="btn btn-lg btn-primary btn-block mt-3" type="submit"
[disabled]="!form.valid">{{"login.form.submit" | translate}}</button> [disabled]="!form.valid">{{"login.form.submit" | translate}}</button>
<br>
<!--
<div *ngIf="(hasSsoLoginUrl | async)">
&lt;!&ndash;<div class="text-center mt-2"><span class="align-middle">{{"login.form.or-divider" | translate}}</span></div>&ndash;&gt;
<a class="btn btn-lg btn-primary btn-block mt-2" [href]="(ssoLoginUrl | async)"
role="button">{{"login.form.ssoLogin" | translate}}</a>
</div>-->
<!--Change href to "https://dspace.hostname/Shibboleth.sso/Login?target=https://dspace.hostname/shibboleth"
to make this work with your Shibboleth IdentityProvider and Service Provider. dspace.hostname = as in the
backend config file "dspace.cfg". Do not change the following parts of href:
"/Shibboleth.sso/Login?target=" and "/shibboleth" at the end of href -->
<!-- <br>
<div>
<a class="btn btn-lg btn-primary btn-block mt-2"
href="https://fis.tiss.tuwien.ac.at/Shibboleth.sso/Login?target=https://fis.tiss.tuwien.ac.at/shibboleth"
role="button"
>HardCoded Shibb</a>
</div>-->
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">{{"login.form.new-user" | translate}}</a> <a class="dropdown-item" href="#">{{"login.form.new-user" | translate}}</a>

View File

@@ -1,22 +1,8 @@
<!--Change href to "https://dspace.hostname/Shibboleth.sso/Login?target=https://dspace.hostname/shibboleth"
to make this work with your Shibboleth IdentityProvider and Service Provider. dspace.hostname = as in the
backend config file "dspace.cfg". Do not change the following parts of href:
"/Shibboleth.sso/Login?target=" and "/shibboleth" at the end of href -->
<!--<br>
<div>
<a class="btn btn-lg btn-primary btn-block mt-3" type="submit"
href="https://fis.tiss.tuwien.ac.at/Shibboleth.sso/Login?target=https://fis.tiss.tuwien.ac.at/shibboleth"
role="button"
>HardCoded Shibb</a>
</div>-->
<br>
<div> <div>
<a class="btn btn-lg btn-primary btn-block mt-3" type="submit" <a class="btn btn-lg btn-primary btn-block mt-3" type="submit"
[href]="injectedShibbolethUrl" [href]="injectedShibbolethUrl"
role="button" role="button"
>Shibboleth</a> >{{"login.shibboleth" | translate}}</a>
</div> </div>