13

in my App (Angular 2 / Ionic 2) I implemented my own login/authentication. Basically it works like this: On login, username and password is being validated by the PHP backend. A token is generated, which is sent back to then frontend in the header (Authorization). The response from backend looks like this:

HTTP/1.1 200 OK
Host: localhost:8080
Connection: close
X-Powered-By: PHP/5.6.28
Set-Cookie: PHPSESSID=jagagi2le1b8i7r90esr4vmeo6; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: application/json
 Authorization: d7b24a1643a61706975213306446aa4e4157d167eaad9aac989067a329c492d3
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Content-Length: 301

There's clearly an Authorization header with a token present. CORS seems also to be setup correctly, since I see Authorization in the Allow-Headers header.

But, when I try to get the header in Angular 2, it always returns null:

private extractDataAndSetAuthHeader(res: Response) {

    // Set auth header if available.
    // If not available - user is not logged in. Then 
    // we also have to remove the token from localStorage
    if(res.headers.has("Authorization"))
    {
        let token = res.headers.get("Authorization");

        this.setToken(token);
    }
    else
    {
        // If no token is sent, remove it
        this.removeToken();
    }

    let body = res.json();
    return body.data || { };
}

The first line of the method gives back false. Also, when I check the headers object in my response, it shows me only the following (Chrome dev tools):

[[Entries]]:
Array[4]
0:{"pragma" => Array[1]}
1:{"content-type" => Array[1]}
2:{"cache-control" => Array[1]}
3:{"expires" => Array[1]}

There's no Authorization header present in that object.

Can anyone please help me out?

Thanks in advance :)

DilumN
  • 2,889
  • 6
  • 30
  • 44
dave0688
  • 5,372
  • 7
  • 33
  • 64
  • `Authorization` is typically used as a request header, not as response. Why don't you return the access token in the body of the response? – Darin Dimitrov Feb 18 '17 at 10:46
  • Because as far as I know that's what the `Authorization` header is for. At every request (when the user is logged in) I'm sending an Authorization header in the request, check if the token is still valid, then, to be more secure, regenerate the token, and send it back to frontend with an `Authorization` header. Am I missing something? – dave0688 Feb 18 '17 at 11:11
  • 3
    http://stackoverflow.com/q/42306684/2587435 – Paul Samsotha Feb 18 '17 at 11:45
  • That doesn't look like a good strategy to me. What if the client sends several requests in parallel? What if the response to the second request comes before the response to the first? What's the point in changing the token at every request: it should be protected by TLS anyway if you care about security. – JB Nizet Feb 18 '17 at 12:05
  • @peeskillet Your hint was the solution, thanks a lot! – dave0688 Feb 18 '17 at 12:44
  • @JBNizet Ok, yes, you're right - didn't think of that. My point was, that, if someone should somehow get access to the token, it's only valid for one request. From DB point of view (updating of the user at every request) it doesn't matter because the user needs to be updated anyway (updating token_expire date). – dave0688 Feb 18 '17 at 12:50

3 Answers3

25

Just wanted to post the answer as it might help others: The solution as to set

Access-Control-Expose-Headers: Authorization

Then - frontend can read the Authorization header as well.

dave0688
  • 5,372
  • 7
  • 33
  • 64
5

This answer helped me : link

It shows how to add it in the backend and how use it in the frontend

Java backend:

public void methodJava(HttpServletResponse response){
...
response.addHeader("access-control-expose-headers", "Authorization");
}

And access the header on angular like this:

return this.http
    .get(<your url here for your backend>)
    .map(res => console.log("cookie: " + res.headers.get("Authorization") )
}
EssaidiM
  • 7,924
  • 1
  • 18
  • 22
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – Rob Dec 02 '17 at 14:40
0

That's not related to Angular. The problem is CORS limits headers by default and you do not see "Authorization" header when call CORS requests. So, adjust server to let it send Authorization header

Access-Control-Allow-Headers must be provided in response of OPTIONS request (pre-flight).

Access-Control-Expose-Headers must be provided in response of POST/GET request.

Access-Control-Expose-Headers: Authorization

Durgesh Pal
  • 695
  • 5
  • 13