简体   繁体   中英

Symfony / Mercure / JS EventSource don't send cookie

I've been blocking this issue for 2 days now. I'm trying to set up authentication for Mercure so that a customer can subscribe to "private" hubs. So I configured my environment variables as stipulated in the Symfony and Mercury documentation here they are:

my.env of my app Symfony:

###> mercure/bundle ###
MERCURE_URL=http://mydemoapp.com:80/.well-known/mercure
MERCURE_PUBLIC_URL=http://mydemoapp.com:80/.well-known/mercure
MERCURE_JWT_SECRET=MySecretKeyJWT
MERCURE_JWT_TOKEN=MyTokenJWT
###< mercure/bundle ###

my caddyFile:

{
    # Debug mode (disable it in production!)
    debug
    # HTTP/3 support
    experimental_http3
}

:80

log

route {
    redir / /.well-known/mercure/ui/
    encode gzip

    mercure {
        # Enable the demo endpoint (disable it in production!)
        demo
        # Publisher JWT key
        publisher_jwt MySecretKeyJWT
        # Subscriber JWT key
        subscriber_jwt MySecretKeyJWT
        # CORS
        cors_origins http://127.0.0.1:3005
        # Allow anonymous subscribers (double-check that it's what you want)
        anonymous
        # Enable the subscription API (double-check that it's what you want)
        subscriptions
    }

    respond "Not Found" 404
}

my container Mercure:

  mercure:
    image: dunglas/mercure
    container_name: mercure
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - mercure:/data
    labels:
      - traefik.docker.network=proxy
      - traefik.enable=true
      - traefik.http.routers.mercure.rule=Host(`mydemoapp.com`)
    expose:
      - "80"
    networks:
      - app

And here is the code of my controllers to generate the authorization cookie and the route publishing the hub:

my routes authorization:

    /**
     * @Route("/api/v1.0/ms-security/authorization", name="security.index", methods={"GET"})
     */
    public function index(Authorization $authorization, Request $request): Response
    {

        $response = $this->json([
            'message' => 'Your authorization has been generated !',
            'code' => '200',
        ]);

       $response->headers->setCookie($authorization->createCookie($request, ["http://mydemoapp.com:80/api/v1.0/ms-security/23"]));
       return $response;
    }

my routes for publish on hub ( This routes is only a test route to know if my client is well subscribed and receives the notifications ):

  /**
     * @Route("/api/v1.0/ms-match/invitations/test", name="invitation.test", methods={"GET"})
     */
    public function test(HubInterface $hub)
    {
       
        $update = new Update("{$this->getParameter('base.url')}/ms-security/23", json_encode("Hy it's me {$this->getUser()->getId()} !"), true);
        $hub->publish($update);

        return $this->json(["message" => "ok"]);
    }

and my javascript:


async mounted(){
    let data = {"phone": "myPhone", "password": "myPassword"};
    const resAuth = await fetch("http://mydemoapp.com:80/api/v1.0/ms-security/login", {method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data)});
    const dataAuth = await resAuth.json();
    console.log(dataAuth);

    const res = await fetch("http://mydemoapp.com:80/api/v1.0/ms-security/authorization", {method: "GET", headers: {'Authorization': `Bearer ${await dataAuth.token}`}});
    const dataCookie = await res.json();
    console.log(dataCookie)

    const url = new URL('http://mydemoapp.com:80/.well-known/mercure');
    url.searchParams.append('topic', 'http://mydemoapp.com:80/api/v1.0/ms-security/23');

    const eventSource = new EventSource(url, {withCredentials: true});
    console.log(eventSource.withCredentials)
    eventSource.onmessage = e => console.log(e.data);
  }

When I call my route "authorization" I see in my response header that I really have the cookie to send. When I decode it on JWT.IO we can see that my jwt contains the information to subscribe to this hub, however when I call my test route the client does not receive the notification if I send this hub in private (in public everything goes very well). So I have the impression that cookies do not send.

I had a similar issue, but I can only give you hints about a not ideal solution. Some browsers have problems to set cookies under localhost in combination with different ports. Symfony with port 8000 (separate webserver) sets the cookie - the UI with port 8080 does not show it under localhost, although the response in the headers transmits the corresponding token via "Set-Cookie". On the other hand, in production systems (with the same ports for UI and API) everything worked.

As a workaround I took the valid token from the response headers (can also be generated on jwt.io). In the debugging tools of Mercure (http://localhost:3000) in the settings section I selected the type cookie and inserted the generated token. If "Discover" is clicked, the cookie is set and can also be accessed in the UI. Probably mercure uses less restrictive settings when setting the cookie. I have tried many other settings, but have not found a direct solution. The use of a local tunnel could possibly also solve the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM