Angular 5 HTTP Client has “Authorization” missing

2020-08-16 03:48发布

问题:

I am working with JWT (JSON Web Tokens) as a part of logging people into the system. The code that does this is as follows:

this.http.post(url, JSON.stringify({ username: username, password: password }), { observe: 'response' })
      .subscribe((response: HttpResponse<any>) => {

When sending the username and password to the server, the Response object contains the encrypted authorization in the Header.

Included as part of the headers is an Authorization entry and also a Pragma entry. The Authorization has the token correctly defined (and it works). Pragma is also defined as no-cache

From Network tab in Chrome:

but when running the code to process the response headers, the Authorization header is not present.

 adminLogin(username, password) {
    let url = `${this._apiRoot}/login`;
    let tokenResp = {};

    this.http.post(url, JSON.stringify({ username: username, password: password }), { observe: 'response' })
      .subscribe((response: HttpResponse<any>) => {

        console.log(" ---- begin response ----");
        console.log( response );
        console.log(" ---- end response ----");

        let token = response.headers.get("Authorization");

        console.log(" ---- begin token ----");
        console.log ( token );
        console.log(" ---- end token ----");

        let pragma = response.headers.get("pragma");

        console.log(" ---- begin pragma ----");
        console.log ( pragma );
        console.log(" ---- end pragma ----");

Results from code executed:

From the code executed, one can see that the trying to find the Authorization returns null while Pragma gets no-cache. What is going on?

UPDATE

Thanks all for the information.

I followed the information here: https://github.com/angular/angular/issues/13554

and made changes to the java code:

@Override
    protected void successfulAuthentication(HttpServletRequest req,
            HttpServletResponse res, FilterChain chain, Authentication auth)
            throws IOException, ServletException {
        String username = ((User) auth.getPrincipal()).getUsername();
        ApplicationUser user = applicationUserRepository
                .findByUsername(username);

        String token = Jwts
                .builder()
                .setSubject(((User) auth.getPrincipal()).getUsername())
                .claim("id", user.getId())

            [... snip ...]

            res.addHeader("Access-Control-Expose-Headers", "Authorization");
            res.addHeader(SecurityConstants.HEADER_STRING,SecurityConstants.TOKEN_PREFIX + token);

    }

Thanks again!

回答1:

To solve this issue we need to expose the desired header from the backend side and use and write a custom HttpInterceptor.

NodeJs API exemple: Expose authorization header from backend

res.setHeader('Access-Control-Expose-Headers', 'authorization'); 
res.setHeader('authorization', 'foo-bar');

Sample angular interceptor

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    return next.handle(request).pipe(
      tap(response => {
        if (response.headers) {
          console.log('Header keys', response.headers.keys());
          console.log('Authorization: ', response.headers.get('authorization'));
        }
      }),
    );
  }
}

Lastly we add our interceptor to our module providers

import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpInterceptorService } from './http-interceptor.service';

@NgModule({
  ...
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
  ],
})
export class AppModule {}

This sample code and repos can be usefull to know more about Angular HttpInterceptor



标签: angular http jwt