Milano
Milano

Reputation: 176

Angular 4 not send cookie to server

When I use withCredentials I can see that cookies are sent to the server, but are send anything to the server. I use laravel as backend and angular 4 as frontend. Also, the cookie not shown on chrome developer tools and I can't access them using.

Also, I used Cors middleware in laravel like:

<?php

namespace App\Http\Middleware;

use Closure;

class Cors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
      $response = $next($request);
      $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:4200');
      $response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
      $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Request-With');
      $response->headers->set('Access-Control-Expose-Headers', 'Content-Disposition, x-total-count, x-filename');
      $response->headers->set('Access-Control-Allow-Credentials', 'true');

      return $response;

    }
}

and when I request first time to the server for set cookie, these below response show:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Accept, Authorization, X-Request-With
Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin:http://localhost:4200
Access-Control-Expose-Headers:Content-Disposition, x-total-count, x-filename
Cache-Control:no-cache, private
Connection:keep-alive
Content-Type:application/json
Date:Tue, 02 Jan 2018 09:04:32 GMT
Server:nginx/1.11.9
Set-Cookie:refreshToken=def502005a2ccf60eafdee2137df25a628d49f70c4571bedde628d50e45c0fe4b73f84f86bb469f0f77247dc2abc13c0c5c938027beb13fe534eb7bb41f4aed99faf49ebf2a238a007ce9514108951366db45a311d70d17d65dd48f5df6aa50f257c828cce16e589983c1e06c9e8d7d52806a1a9401569f87b3a394469e938c4ddbfcc7985e257d8f0d0df416e7b8a5bbd19e86050db3be5b90953c515934f529489f4e0ba62fb66ab883d1689349bbfb962332bceb322d978b7d20fa7e32bb94eb0050d8f94bfd3a780c4edfeea8eaa6954222b57c30229c2494fec38ee5292396400b25fadee04cad1729f9e9b9ccf12d21a6ed3f9663d41c5423536e64f83542df19fcede28247bfc12accf354e035182c3e019e4a2b55c807924cc50a12fa187b2f655fb19c1b42a1ae526763dd08dbd0d288b3a9c649216ab1abc60cd51bb97dfb0cb7b7b020ff270cf5c81bc94f2acd40f92edeefaf585d46d0750bf; expires=Sun, 25-Aug-2019 09:04:32 GMT; Max-Age=51840000; path=/; HttpOnly
Transfer-Encoding:chunked
X-RateLimit-Limit:60
X-RateLimit-Remaining:58

and when I request from frontend:

refreshToken(){

const headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + this.getToken()})
let options = new RequestOptions({ headers: headers, withCredentials: true });
return this.http.post(API_DOMAIN + 'refresh', JSON.stringify({}), options)
  .map(
    (response) => {
      console.log(response);
      return response.json()
    },
  )
  .do(
    tokenData =>{
      localStorage.setItem('token', tokenData.access_token)
      localStorage.setItem('expires_in', tokenData.expires_in)
    }
  )
}

Chrome developer:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Accept, Authorization, X-Request-With
Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin:http://localhost:4200
Access-Control-Expose-Headers:Content-Disposition, x-total-count, x-filename
Cache-Control:no-cache, private
Connection:keep-alive
Content-Type:application/json
Date:Tue, 02 Jan 2018 08:57:28 GMT
Server:nginx/1.11.9
Transfer-Encoding:chunked
X-RateLimit-Limit:60
X-RateLimit-Remaining:59

Front and back servers use different ports.

Upvotes: 4

Views: 5227

Answers (1)

Dmitry
Dmitry

Reputation: 7276

You can't save cookies because your development node.js server and your Laravel Vagrant box are on different domains. What you can do is to proxy calls from node.js to the the Laravel server.

Create proxy.conf.json in the root of Angular app. Put an object with routes inside:

{
  "/api": {
    "target": "http://mydomian.test/",
    "secure": false
  }
}

I just have /api defined here because all my backend URIs are inside api.php. All calls that look like http://localhost:4200/api/someitems/1 will be proxied to http://mydomian.test/api/someitems/1.
Then edit package.json and change the value of start inside scripts to ng serve --proxy-config proxy.conf.json. Now npm run start will start with proxy. The problem I had with this proxy is that it resolves your URL (http://mydomian.test/) to an IP. When it calls Laravel with just an IP the nginx server does not know what to do because it must receive a domain name. nginx allows multiple website on the same IP so it must receive a domain name or to have a default website to which it redirects all calls those have no domain name. In case this is still not fixed in Angular's proxy go to /etc/nginx/sites-available on the Laravel machine, you'll have a mydomian.test config file there. It has listen 80; line there, change it to listen 80 default;.

Now you can change the API_DOMAIN variable to http://localhost:4200 (or remove it all together) and disable the CORS.

Upvotes: 5

Related Questions