Marko P
Marko P

Reputation: 89

Angular2 JWT Authorization header missing in http response (CORS support added)

I'm trying to do an authorization using JWT (Json Web Token). On front-end I'm using Angular2, on back-end Spring REST api. I've added CORS filter on back-end side.

In http request I'm sending username and password and expecting token in 'Authorization' header of response. Everything works fine when I use Postman, I receive all headers including 'Authorization'.

Also, when I record the traffic in Chrome Console (while doing user login through the form) 'Authorization' header is present in response, so obviously it returns back to the browser. But when I list headers in my angular app, there is just few headers in array:

   // auth.service.ts

   login(username, password): Observable<boolean> {

    // call remote service to authenticate user        
     return this.http.post(this.authUrl, JSON.stringify({ username: username, password: password }))
        .map((response: Response) => {

            console.log("Authorization header: " + response.headers.get('Authorization'));
            console.log("all headers: " + response.headers.keys());

            // TODO - login successful if there's a jwt token in the response

        });     
} 

Result of those 2 console output is:

 Authorization header: null 

 all headers: Pragma,Cache-Control,Expires

Here is the screenshot from Google Chrome console where you can see that all needed headers are present on client side:

Chrome console

Server-side token generation (Spring Boot):

public void addAuthentication(HttpServletResponse response, String username) throws UnsupportedEncodingException {
    // Token generation
    String JWT = Jwts.builder()
            .setSubject(username)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(SignatureAlgorithm.HS512, secret.getBytes("UTF-8"))
            .compact();

    response.addHeader(headerString, tokenPrefix + " " + JWT);
}

Does anyone has some useful advice?

Thanks

SOLUTION:

public class CORSFilter implements Filter{


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        response.setHeader("Access-Control-Expose-Headers", "Authorization");
        chain.doFilter(req, response);

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}

Upvotes: 2

Views: 2174

Answers (1)

Evans M.
Evans M.

Reputation: 1951

Authorization header is present but since it's a custom header the browser will not allow you to access it directly even though chrome will see it.

To solve that you need one more important header in you cors config.

Access-Control-Expose-Headers: Authorization, CustomHeader2, e.tc

Make sure to expose any other custom headers that you want your app to have access to.

Upvotes: 7

Related Questions