mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Use status request to check an existing token and to retrieve auth methods available
This commit is contained in:
@@ -85,6 +85,15 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
return http.url && http.url.endsWith('/authn/logout');
|
return http.url && http.url.endsWith('/authn/logout');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if response is from a status request
|
||||||
|
*
|
||||||
|
* @param http
|
||||||
|
*/
|
||||||
|
private isStatusResponse(http: HttpRequest<any> | HttpResponseBase): boolean {
|
||||||
|
return http.url && http.url.endsWith('/authn/status');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract location url from the WWW-Authenticate header
|
* Extract location url from the WWW-Authenticate header
|
||||||
*
|
*
|
||||||
@@ -202,8 +211,10 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
|
|
||||||
const authService = this.inj.get(AuthService);
|
const authService = this.inj.get(AuthService);
|
||||||
|
|
||||||
const token = authService.getToken();
|
const token: AuthTokenInfo = authService.getToken();
|
||||||
let newReq;
|
let newReq: HttpRequest<any>;
|
||||||
|
let updateReq: any = {};
|
||||||
|
let authorization: string;
|
||||||
|
|
||||||
if (authService.isTokenExpired()) {
|
if (authService.isTokenExpired()) {
|
||||||
authService.setRedirectUrl(this.router.url);
|
authService.setRedirectUrl(this.router.url);
|
||||||
@@ -224,11 +235,13 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Get the auth header from the service.
|
// Get the auth header from the service.
|
||||||
const Authorization = authService.buildAuthHeader(token);
|
authorization = authService.buildAuthHeader(token);
|
||||||
// Clone the request to add the new header.
|
// Clone the request to add the new header.
|
||||||
newReq = req.clone({headers: req.headers.set('authorization', Authorization)});
|
newReq = req.clone({ headers: req.headers.set('authorization', authorization) });
|
||||||
} else {
|
} else {
|
||||||
const updateReq = this.isAuthRequest(req) ? { withCredentials: true } : {};
|
if (this.isAuthRequest(req)) {
|
||||||
|
updateReq = { withCredentials: true };
|
||||||
|
}
|
||||||
newReq = req.clone(updateReq);
|
newReq = req.clone(updateReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,19 +250,29 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
// tap((response) => console.log('next.handle: ', response)),
|
// tap((response) => console.log('next.handle: ', response)),
|
||||||
map((response) => {
|
map((response) => {
|
||||||
// Intercept a Login/Logout response
|
// Intercept a Login/Logout response
|
||||||
if (response instanceof HttpResponse && this.isSuccess(response) && (this.isLoginResponse(response) || this.isLogoutResponse(response))) {
|
if (response instanceof HttpResponse && this.isSuccess(response) && this.isAuthRequest(response)) {
|
||||||
// It's a success Login/Logout response
|
// It's a success Login/Logout response
|
||||||
let authRes: HttpResponse<any>;
|
let authRes: HttpResponse<any>;
|
||||||
if (this.isLoginResponse(response)) {
|
if (this.isLoginResponse(response)) {
|
||||||
// login successfully
|
// login successfully
|
||||||
const newToken = response.headers.get('authorization');
|
const newToken = response.headers.get('authorization');
|
||||||
authRes = response.clone({body: this.makeAuthStatusObject(true, newToken)});
|
authRes = response.clone({
|
||||||
|
body: this.makeAuthStatusObject(true, newToken)
|
||||||
|
});
|
||||||
|
|
||||||
// clean eventually refresh Requests list
|
// clean eventually refresh Requests list
|
||||||
this.refreshTokenRequestUrls = [];
|
this.refreshTokenRequestUrls = [];
|
||||||
|
} else if (this.isStatusResponse(response)) {
|
||||||
|
authRes = response.clone({
|
||||||
|
body: Object.assign(response.body, {
|
||||||
|
authMethods: this.parseAuthMethodsFromHeaders(response.headers)
|
||||||
|
})
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// logout successfully
|
// logout successfully
|
||||||
authRes = response.clone({body: this.makeAuthStatusObject(false)});
|
authRes = response.clone({
|
||||||
|
body: this.makeAuthStatusObject(false)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return authRes;
|
return authRes;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -16,7 +16,13 @@ import { AuthStatus } from './models/auth-status.model';
|
|||||||
import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model';
|
import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model';
|
||||||
import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util';
|
import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util';
|
||||||
import { CookieService } from '../services/cookie.service';
|
import { CookieService } from '../services/cookie.service';
|
||||||
import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors';
|
import {
|
||||||
|
getAuthenticationMethods,
|
||||||
|
getAuthenticationToken,
|
||||||
|
getRedirectUrl,
|
||||||
|
isAuthenticated,
|
||||||
|
isTokenRefreshing
|
||||||
|
} from './selectors';
|
||||||
import { AppState, routerStateSelector } from '../../app.reducer';
|
import { AppState, routerStateSelector } from '../../app.reducer';
|
||||||
import {
|
import {
|
||||||
CheckAuthenticationTokenAction,
|
CheckAuthenticationTokenAction,
|
||||||
@@ -28,6 +34,7 @@ import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util';
|
|||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
import { RouteService } from '../services/route.service';
|
import { RouteService } from '../services/route.service';
|
||||||
import { AuthMethod } from './models/auth.method';
|
import { AuthMethod } from './models/auth.method';
|
||||||
|
import { NormalizedAuthStatus } from './models/normalized-auth-status.model';
|
||||||
|
|
||||||
export const LOGIN_ROUTE = '/login';
|
export const LOGIN_ROUTE = '/login';
|
||||||
export const LOGOUT_ROUTE = '/logout';
|
export const LOGOUT_ROUTE = '/logout';
|
||||||
@@ -121,7 +128,14 @@ export class AuthService {
|
|||||||
* Checks if token is present into the request cookie
|
* Checks if token is present into the request cookie
|
||||||
*/
|
*/
|
||||||
public checkAuthenticationCookie(): Observable<AuthStatus> {
|
public checkAuthenticationCookie(): Observable<AuthStatus> {
|
||||||
return this.authRequestService.postToEndpoint('login');
|
// Determine if the user has an existing auth session on the server
|
||||||
|
const options: HttpOptions = Object.create({});
|
||||||
|
let headers = new HttpHeaders();
|
||||||
|
headers = headers.append('Accept', 'application/json');
|
||||||
|
options.headers = headers;
|
||||||
|
return this.authRequestService.getRequest('status', options).pipe(
|
||||||
|
map((status: NormalizedAuthStatus) => Object.assign(new AuthStatus(), status))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,7 +172,13 @@ export class AuthService {
|
|||||||
* Checks if token is present into browser storage and is valid. (NB Check is done only on SSR)
|
* Checks if token is present into browser storage and is valid. (NB Check is done only on SSR)
|
||||||
*/
|
*/
|
||||||
public checkAuthenticationToken() {
|
public checkAuthenticationToken() {
|
||||||
this.store.dispatch(new CheckAuthenticationTokenAction());
|
this.store.pipe(
|
||||||
|
select(getAuthenticationMethods),
|
||||||
|
filter((authMethods: AuthMethod[]) => isEmpty(authMethods)),
|
||||||
|
take(1)
|
||||||
|
).subscribe(() => {
|
||||||
|
this.store.dispatch(new CheckAuthenticationTokenAction());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -4,6 +4,7 @@ import { mapsTo, relationship } from '../../cache/builders/build-decorators';
|
|||||||
import { NormalizedObject } from '../../cache/models/normalized-object.model';
|
import { NormalizedObject } from '../../cache/models/normalized-object.model';
|
||||||
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
|
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
|
||||||
import { EPerson } from '../../eperson/models/eperson.model';
|
import { EPerson } from '../../eperson/models/eperson.model';
|
||||||
|
import { AuthMethod } from './auth.method';
|
||||||
|
|
||||||
@mapsTo(AuthStatus)
|
@mapsTo(AuthStatus)
|
||||||
@inheritSerialization(NormalizedObject)
|
@inheritSerialization(NormalizedObject)
|
||||||
@@ -39,4 +40,9 @@ export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
|
|||||||
@autoserialize
|
@autoserialize
|
||||||
eperson: string;
|
eperson: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All authentication methods enabled at the backend
|
||||||
|
*/
|
||||||
|
@autoserialize
|
||||||
|
authMethods: AuthMethod[];
|
||||||
}
|
}
|
||||||
|
@@ -225,6 +225,8 @@ export class AuthPostRequest extends PostRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AuthGetRequest extends GetRequest {
|
export class AuthGetRequest extends GetRequest {
|
||||||
|
forceBypassCache = true;
|
||||||
|
|
||||||
constructor(uuid: string, href: string, public options?: HttpOptions) {
|
constructor(uuid: string, href: string, public options?: HttpOptions) {
|
||||||
super(uuid, href, null, options);
|
super(uuid, href, null, options);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user