1
0

Use status request to check an existing token and to retrieve auth methods available

This commit is contained in:
Giuseppe Digilio
2020-01-16 14:36:20 +01:00
parent 6f8f4b31bf
commit 6560d1d112
4 changed files with 62 additions and 11 deletions

View File

@@ -85,6 +85,15 @@ export class AuthInterceptor implements HttpInterceptor {
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
*
@@ -202,8 +211,10 @@ export class AuthInterceptor implements HttpInterceptor {
const authService = this.inj.get(AuthService);
const token = authService.getToken();
let newReq;
const token: AuthTokenInfo = authService.getToken();
let newReq: HttpRequest<any>;
let updateReq: any = {};
let authorization: string;
if (authService.isTokenExpired()) {
authService.setRedirectUrl(this.router.url);
@@ -224,11 +235,13 @@ export class AuthInterceptor implements HttpInterceptor {
}
});
// Get the auth header from the service.
const Authorization = authService.buildAuthHeader(token);
authorization = authService.buildAuthHeader(token);
// 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 {
const updateReq = this.isAuthRequest(req) ? { withCredentials: true } : {};
if (this.isAuthRequest(req)) {
updateReq = { withCredentials: true };
}
newReq = req.clone(updateReq);
}
@@ -237,19 +250,29 @@ export class AuthInterceptor implements HttpInterceptor {
// tap((response) => console.log('next.handle: ', response)),
map((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
let authRes: HttpResponse<any>;
if (this.isLoginResponse(response)) {
// login successfully
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
this.refreshTokenRequestUrls = [];
} else if (this.isStatusResponse(response)) {
authRes = response.clone({
body: Object.assign(response.body, {
authMethods: this.parseAuthMethodsFromHeaders(response.headers)
})
})
} else {
// logout successfully
authRes = response.clone({body: this.makeAuthStatusObject(false)});
authRes = response.clone({
body: this.makeAuthStatusObject(false)
});
}
return authRes;
} else {

View File

@@ -16,7 +16,13 @@ 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 '../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 {
CheckAuthenticationTokenAction,
@@ -28,6 +34,7 @@ import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { RouteService } from '../services/route.service';
import { AuthMethod } from './models/auth.method';
import { NormalizedAuthStatus } from './models/normalized-auth-status.model';
export const LOGIN_ROUTE = '/login';
export const LOGOUT_ROUTE = '/logout';
@@ -121,7 +128,14 @@ export class AuthService {
* Checks if token is present into the request cookie
*/
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)
*/
public checkAuthenticationToken() {
this.store.pipe(
select(getAuthenticationMethods),
filter((authMethods: AuthMethod[]) => isEmpty(authMethods)),
take(1)
).subscribe(() => {
this.store.dispatch(new CheckAuthenticationTokenAction());
});
}
/**

View File

@@ -4,6 +4,7 @@ import { mapsTo, relationship } from '../../cache/builders/build-decorators';
import { NormalizedObject } from '../../cache/models/normalized-object.model';
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
import { EPerson } from '../../eperson/models/eperson.model';
import { AuthMethod } from './auth.method';
@mapsTo(AuthStatus)
@inheritSerialization(NormalizedObject)
@@ -39,4 +40,9 @@ export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
@autoserialize
eperson: string;
/**
* All authentication methods enabled at the backend
*/
@autoserialize
authMethods: AuthMethod[];
}

View File

@@ -225,6 +225,8 @@ export class AuthPostRequest extends PostRequest {
}
export class AuthGetRequest extends GetRequest {
forceBypassCache = true;
constructor(uuid: string, href: string, public options?: HttpOptions) {
super(uuid, href, null, options);
}