diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index 0c0d3309b1..0aed7bca36 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -75,11 +75,12 @@ export class AuthenticatedSuccessAction implements Action { public type: string = AuthActionTypes.AUTHENTICATED_SUCCESS; payload: { authenticated: boolean; + authToken: AuthTokenInfo; user: Eperson }; - constructor(authenticated: boolean, user: Eperson) { - this.payload = { authenticated, user }; + constructor(authenticated: boolean, authToken: AuthTokenInfo, user: Eperson) { + this.payload = { authenticated, authToken, user }; } } diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 64bf311ff3..122975bd96 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -57,7 +57,7 @@ export class AuthEffects { .ofType(AuthActionTypes.AUTHENTICATED) .switchMap((action: AuthenticatedAction) => { return this.authService.authenticatedUser(action.payload) - .map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), user)) + .map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) .catch((error) => Observable.of(new AuthenticatedErrorAction(error))); }); diff --git a/src/app/core/auth/auth.reducers.ts b/src/app/core/auth/auth.reducers.ts index d45b637f07..9664773ac5 100644 --- a/src/app/core/auth/auth.reducers.ts +++ b/src/app/core/auth/auth.reducers.ts @@ -3,11 +3,12 @@ import { AddAuthenticationMessageAction, AuthActions, AuthActionTypes, AuthenticatedSuccessAction, AuthenticationErrorAction, AuthenticationSuccessAction, LogOutErrorAction, RedirectWhenAuthenticationIsRequiredAction, - RedirectWhenTokenExpiredAction, SetRedirectUrlAction + RedirectWhenTokenExpiredAction, RefreshTokenSuccessAction, SetRedirectUrlAction } from './auth.actions'; // import models import { Eperson } from '../eperson/models/eperson.model'; +import { AuthTokenInfo } from './models/auth-token-info.model'; /** * The auth state. @@ -18,6 +19,9 @@ export interface AuthState { // boolean if user is authenticated authenticated: boolean; + // the authentication token + authToken?: AuthTokenInfo; + // error message error?: string; @@ -68,6 +72,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.AUTHENTICATED_ERROR: return Object.assign({}, state, { authenticated: false, + authToken: undefined, error: (action as AuthenticationErrorAction).payload.message, loaded: true, loading: false @@ -76,6 +81,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.AUTHENTICATED_SUCCESS: return Object.assign({}, state, { authenticated: true, + authToken: (action as AuthenticatedSuccessAction).payload.authToken, loaded: true, error: undefined, loading: false, @@ -87,6 +93,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.REGISTRATION_ERROR: return Object.assign({}, state, { authenticated: false, + authToken: undefined, error: (action as AuthenticationErrorAction).payload.message, loading: false }); @@ -115,6 +122,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.REFRESH_TOKEN_ERROR: return Object.assign({}, state, { authenticated: false, + authToken: undefined, error: undefined, loaded: false, loading: false, @@ -127,6 +135,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.REDIRECT_TOKEN_EXPIRED: return Object.assign({}, state, { authenticated: false, + authToken: undefined, loaded: false, loading: false, info: (action as RedirectWhenTokenExpiredAction as RedirectWhenAuthenticationIsRequiredAction).payload, @@ -136,6 +145,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.REGISTRATION: return Object.assign({}, state, { authenticated: false, + authToken: undefined, error: undefined, loading: true, info: undefined @@ -151,6 +161,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.REFRESH_TOKEN_SUCCESS: return Object.assign({}, state, { + authToken: (action as RefreshTokenSuccessAction).payload, refreshing: false, }); @@ -161,10 +172,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.RESET_MESSAGES: return Object.assign({}, state, { - authenticated: state.authenticated, error: undefined, - loaded: state.loaded, - loading: state.loading, info: undefined, }); @@ -234,6 +242,14 @@ export const _isLoading = (state: AuthState) => state.loading; */ export const _isRefreshing = (state: AuthState) => state.refreshing; +/** + * Returns the authentication token. + * @function _getAuthenticationToken + * @param {State} state + * @returns {AuthToken} + */ +export const _getAuthenticationToken = (state: AuthState) => state.authToken; + /** * Returns the sign out error. * @function _getLogOutError diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 4539aa3532..68bb3f2843 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@angular/core'; -import { NavigationExtras, PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; +import { PRIMARY_OUTLET, Router, UrlSegmentGroup, UrlTree } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { map, withLatestFrom } from 'rxjs/operators'; @@ -12,7 +12,7 @@ import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model'; import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util'; import { CookieService } from '../../shared/services/cookie.service'; -import { getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; +import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; import { AppState, routerStateSelector } from '../../app.reducer'; import { Store } from '@ngrx/store'; import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth.actions'; @@ -212,13 +212,16 @@ export class AuthService { * @returns {AuthTokenInfo} */ public getToken(): AuthTokenInfo { - // Retrieve authentication token info and check if is valid - const token = this.storage.get(TOKENITEM); - if (isNotEmpty(token) && token.hasOwnProperty('accessToken') && isNotEmpty(token.accessToken)) { - return token; - } else { - return null; - } + let token: AuthTokenInfo; + this.store.select(getAuthenticationToken) + .subscribe((authTokenInfo: AuthTokenInfo) => { + // Retrieve authentication token info and check if is valid + token = isNotEmpty(authTokenInfo) ? authTokenInfo : this.storage.get(TOKENITEM); + if (isEmpty(token) || !token.hasOwnProperty('accessToken') || isEmpty(token.accessToken)) { + token = null; + } + }); + return token; } /** diff --git a/src/app/core/auth/selectors.ts b/src/app/core/auth/selectors.ts index a37f128c88..9d592eba0c 100644 --- a/src/app/core/auth/selectors.ts +++ b/src/app/core/auth/selectors.ts @@ -83,6 +83,14 @@ export const isAuthenticationLoading = createSelector(getAuthState, auth._isLoad */ export const isTokenRefreshing = createSelector(getAuthState, auth._isRefreshing); +/** + * Returns the authentication token. + * @function getAuthenticationToken + * @param {State} state + * @returns {AuthToken} + */ +export const getAuthenticationToken = createSelector(getAuthState, auth._getAuthenticationToken); + /** * Returns the log out error. * @function getLogOutError