In the context of a server automatically renewing a token, I'm struggling with the basics: Obtaining header data from a response.
It does not seem to be CORS related as my Node/express allwos the Authorization/x-access-token and reponds accordingly (see network tab screeencap below).
The first step I want to see working is simply reading the header from the response. See my code, it's boilerplate as found in the docs. Event getting "Content-Length" returns null.
auth-service.ts
login(username:string, password:string):Observable<boolean>{
this.loggedIn = false;
return new Observable( (observer:Observer<boolean>) => {
const body = {user: username, pwd: password};
const url = this.config.API_ENDPOINT_PUBLIC_AUTH;
this.httpClient.post(url, body, {
responseType: 'text',
observe: "response"
}).first().subscribe(
(response:HttpResponse<string>) => {
// DEBUG
console.log(response.headers.get('Authorization'));
console.log(response.headers.get('X-Test-Header'));
console.log(response.headers.get('Content-length'));
this.token = response.headers.get('Authorization');
this.storeToken(this.token);
this.currentUser = username;
this.loggedIn = true;
this.authChanged$.next('auth');
observer.next(true);
},
(err) => observer.next(false),
() => {},
);
});
}
Console output:
null
null
null
Compare this to the contents of my network tab for this request:
Needless to say my HttpInterceptor doesn't work either - upon being provided "Authorization" header in a response, it uses the value as new token. This to implement auto-renewal of tokens:
token.interceptor.ts
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService);
const token = authService.getToken();
if(token){
request = request.clone({
setHeaders: { 'x-access-token' : token }
});
}
return next.handle(request).do(
(event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
const response:HttpResponse<any> = (<HttpResponse<any>> event);
const authorizationHeader = response.headers.get('Authorization');
console.log('Authorization header value: ' + authorizationHeader);
if(authorizationHeader){
authService.setToken(authorizationHeader);
}
}
},
(err: any) => {
if (err instanceof HttpErrorResponse){
if (err.status === 401) {
this.router.navigate(['/']);
}
}
});
}
Ok, here is the answer: I'm using Node.js/Express as backend and even though headers are visible in the network tab of Chrome, it doesn't make them available for processing by Angular.
"How comes they're visible yet cannot be used?" is still not clear to me.
Configure your Node/Express app (look for the comment "SOLUTION HERE"):
function configureExpress(expressApp){
expressApp.use(bodyparser.urlencoded({ extended: true }));
expressApp.use(bodyparser.json());
// Middleware: Use CORS, add headers and allow methods
expressApp.use(expressMiddleware);
}
function expressMiddleware(req, res, next) {
// Request origin: Allow ALL
res.header("Access-Control-Allow-Origin", "*");
// Allowed headers
res.header("Access-Control-Allow-Headers",
"Origin"
+",X-Requested-With" // Dont allow AJAX CORS without server consent - see http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header
+",x-access-token"
+",Content-Type"
+",Authorization"
+",Accept"
);
// SOLUTION HERE
// Allow headers access
res.header("access-control-expose-headers",
",Authorization"
+",Content-Length"
);
// Allowed methods
res.header('Access-Control-Allow-Methods',
'GET,'
+',POST'
+',OPTIONS'
+',PUT,'
+',DELETE'
);
// Handle CORS requests: cross-domain/origin requests will begin with an OPTION request to the same endpoint.
if('OPTIONS' === req.method){
res.sendStatus(200);
}
else{
// Request validations complete
next();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With