Angular 2 doesn't save my Authentication Cooki

2020-03-27 14:52发布

问题:

I have an angular 2 app which should authenticate to a Node Express backend where it sends an login request to the backend and receives a cookie. It should send this cookie with every consecutive request (which it does not).

I have in my angular app:

class LoginService

private requestOptions = new RequestOptions({headers: this.headers, withCredentials: true});`


    login(username: string, password: string): Promise<boolean> {
     return this.http.post(this.myUrl + "login",
     JSON.stringify({username:username, password: password}), this.requestOptions)
      .toPromise()
      .then(res => true)
      .catch(this.handleError);
  }

some DataService

private requestOptions =  new RequestOptions({headers: this.headers, withCredentials: true})

getData(): Promise<any> {
        return this.http.get(this.myUrl, this.requestOptions)
        .toPromise()
        .then (res => res.json())
        .catch(this.handleError)
    }

On my node backend, I have:

response.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
response.header("Access-Control-Allow-Origin", http://localhost:4200);
response.header('Access-Control-Allow-Credentials', true);
response.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept');

When I send the login request in angular, I can see that it got accepted on the server side, but when i send a consecutive request, it gives me 401 Not authorized, which is the error I send if your not authenticated.

However, when i send the login request via HttpRequester (Firefox Plugin for HTTP Requests), i can access all the data in my angular app.

My angular version is 2.4.10

+++ UPDATE +++

So, i made some tests and I found out, that my authentication works fine, as long as I use the same service.

I have a service called login.service.ts and a service called data.service.ts.

What I can do: Login via login.service.ts and fetch the data via login.service.ts.

What I can't do: Login via login.service.ts and continue to use data.service.ts.

This is not very practical for my use case. Does someone have any ideas on this?

回答1:

By default angular is not sending cookies. Try pass { withCredentials: true } to your RequestOptions:

let options = new RequestOptions({ headers: headers, withCredentials: true });
this.http.post(this.connectUrl, <stringified_data> , options);


回答2:

I had your situation. With Maciej answer I solved my problem. I added the { withCredentials: true } to my request options that already had the headers.

Then server-side, on my express base file server.js, i added

var cors = require("cors");
var corsSettings = {
  origin: true,
  methods: ['POST'],
  credentials: true
};
app.use(cors(corsSettings));

I actually excluded the Access-Control-Allow-Origin:*, so my only header (server-side) is

app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, access-control-allow-origin, access-control-allow-headers");
    next();
});

Just wanna point out that as Maciej mentioned, you need some body in your request. So even if your query doesn't need it you need to call it with an empty body string.

const jsonHeads = new Headers();
jsonHeads.append('Content-Type', 'application/x-www-form-urlencoded');
jsonHeads.append('Access-Control-Allow-Origin', '*');
jsonHeads.append('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, access-control-allow-origin');
options = { headers : myHeaders, withCredentials: true }
this.http.post('http://myApi:8080/list', '', options);

This way, angular started sending cookies and authenticating properly. I hope this helps. I needed this myself a couple of hours ago.