reactjs - Unable to send cookie from React frontend to Symfony backend - Stack Overflow

I'm working with an API made with ApiPlatform. My endpoints are accessible via http:localhost:80

I'm working with an API made with ApiPlatform. My endpoints are accessible via http://localhost:8000/api/myendpoint. I use LexikJWTAuthenticationBundle and NelMioCorsBundle.

The route /api/login_check allows me to authenticate the user and return a Set-Cookie header with the generated token in the response headers. But then, I don't understand why my browser doesn't send the cookie back to my backend when I make an API call. I make my API calls from http://localhost:5000/ (same domain but different ports).

I also use Docker. The back and front are two distinct services.

Here are my firewalls in security.yaml file:

    login:
      pattern: ^/api/login
      provider: app_user_provider
      stateless: true
      json_login:
        check_path: /api/login_check
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure
    api:
      pattern: ^/api
      provider: app_user_provider
      stateless: true
      jwt: ~
    admin:
      pattern: ^/admin
      provider: admin_user_provider
      form_login:
        login_path: app_login
        check_path: app_login
        default_target_path: /admin
      logout:
        path: /admin/logout
        target: app_login
    main:
      lazy: true
      provider: app_user_provider

I followed the documentation to automatically generate a cookie. Here is my configuration in lexik_jwt_authentication.yaml file:

lexik_jwt_authentication:
  secret_key: "%env(resolve:JWT_SECRET_KEY)%"
  public_key: "%env(resolve:JWT_PUBLIC_KEY)%"
  pass_phrase: "%env(JWT_PASSPHRASE)%"
  token_ttl: 3600

  token_extractors:
    authorization_header:
      enabled: false
      prefix: Bearer
      name: Authorization

    # check token in a cookie 
    cookie:
      enabled: true
      name: BEARER
  
  set_cookies:
    BEARER:
      samesite: lax
      httpOnly: true 
      secure: false

Here are my CORS configuration in the nelmio_cors.yaml file:

nelmio_cors:
  defaults:
    origin_regex: true
    allow_credentials: true
    allow_origin: ["%env(CORS_ALLOW_ORIGIN)%"]
    allow_methods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
    allow_headers: ["Content-Type", "Authorization"]
    expose_headers: ["Link"]
    max_age: 3600
  paths:
    "^/api/":
      allow_origin: ["*"]
      allow_headers: ["*"]
      allow_methods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
      max_age: 3600

The authentication is a success and I get the token in the response headers:

Set-Cookie : BEARER=eyJ0eXA.....; expires=Sun, 02 Feb 2025 17:56:51 GMT; Max-Age=3600; path=/; httponly; samesite=lax

Then after the success of my authentication I have a redirection to /home and I try to contact an endpoint with axios with the option withCredentials = true. Here is my API call in my activitySlice.ts file:

export const privateAxiosInstance = axios.create({
  baseURL: apiUrl,
  headers: {
    "Content-Type": "application/json",
  },
  withCredentials: true,
});

export const getActivities = createAsyncThunk(
  "activity",
  async (_, { rejectWithValue }) => {
    try {
      const response = await privateAxiosInstance.get("activities");
      console.log(response);
    } catch (err: any) {
      return rejectWithValue(err.response.data);
    }
  }
);

And here is the problem: I always have a 401 Unauthorized "JWT token not found" error, without any cookie in the request. I don't understand what I'm doing wrong, I'm sure I'm missing something. I read a lot of posts about this problem but I can find a solution that works for me. I tried to:

  • add "localhost" or ".localhost" for the "domain" option in the cookie
  • change my apiUrl to 127.0.0.1 instead of localhost
  • update the cors in the nelmio_cors.yaml file by adding, for example, "http://localhost:5000" in allow_origin
  • change the cookie configuration in the lexik_jwt_authentication.yaml file
  • change the "paths" to ^/api/ instead of "/" in the nelmio_cors.yaml file
  • change withCredentials: true with axios.defaults.withCredentials = true

I don't know if it has something to do with my problem but here is my docker-compose.yaml file configuration if it can help you:

services:
  backend:
    build:
      context: ./back
      dockerfile: Dockerfile
    volumes:
      - ./back:/var/www/html
      - ./docker/conf/vhost.conf:/etc/apache2/sites-available/000-default.conf
    depends_on:
      - mysql
    ports:
      - 8000:80
  frontend:
    build:
      context: ./front
      dockerfile: Dockerfile
    depends_on:
      - backend
    volumes:
      - ./front:/front
    ports:
      - 5000:5000
  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - volume_mysql:/var/lib/mysql
    ports:
      - 3307:3306
  adminer:
    image: adminer:latest
    ports:
      - 8001:8080
    environment:
      ADMINER_DEFAULT_SERVER: mysql
      ADMINER_DESIGN: pappu687
volumes:
  volume_mysql:

Thanks for your help.

I'm working with an API made with ApiPlatform. My endpoints are accessible via http://localhost:8000/api/myendpoint. I use LexikJWTAuthenticationBundle and NelMioCorsBundle.

The route /api/login_check allows me to authenticate the user and return a Set-Cookie header with the generated token in the response headers. But then, I don't understand why my browser doesn't send the cookie back to my backend when I make an API call. I make my API calls from http://localhost:5000/ (same domain but different ports).

I also use Docker. The back and front are two distinct services.

Here are my firewalls in security.yaml file:

    login:
      pattern: ^/api/login
      provider: app_user_provider
      stateless: true
      json_login:
        check_path: /api/login_check
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure
    api:
      pattern: ^/api
      provider: app_user_provider
      stateless: true
      jwt: ~
    admin:
      pattern: ^/admin
      provider: admin_user_provider
      form_login:
        login_path: app_login
        check_path: app_login
        default_target_path: /admin
      logout:
        path: /admin/logout
        target: app_login
    main:
      lazy: true
      provider: app_user_provider

I followed the documentation to automatically generate a cookie. Here is my configuration in lexik_jwt_authentication.yaml file:

lexik_jwt_authentication:
  secret_key: "%env(resolve:JWT_SECRET_KEY)%"
  public_key: "%env(resolve:JWT_PUBLIC_KEY)%"
  pass_phrase: "%env(JWT_PASSPHRASE)%"
  token_ttl: 3600

  token_extractors:
    authorization_header:
      enabled: false
      prefix: Bearer
      name: Authorization

    # check token in a cookie 
    cookie:
      enabled: true
      name: BEARER
  
  set_cookies:
    BEARER:
      samesite: lax
      httpOnly: true 
      secure: false

Here are my CORS configuration in the nelmio_cors.yaml file:

nelmio_cors:
  defaults:
    origin_regex: true
    allow_credentials: true
    allow_origin: ["%env(CORS_ALLOW_ORIGIN)%"]
    allow_methods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
    allow_headers: ["Content-Type", "Authorization"]
    expose_headers: ["Link"]
    max_age: 3600
  paths:
    "^/api/":
      allow_origin: ["*"]
      allow_headers: ["*"]
      allow_methods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
      max_age: 3600

The authentication is a success and I get the token in the response headers:

Set-Cookie : BEARER=eyJ0eXA.....; expires=Sun, 02 Feb 2025 17:56:51 GMT; Max-Age=3600; path=/; httponly; samesite=lax

Then after the success of my authentication I have a redirection to /home and I try to contact an endpoint with axios with the option withCredentials = true. Here is my API call in my activitySlice.ts file:

export const privateAxiosInstance = axios.create({
  baseURL: apiUrl,
  headers: {
    "Content-Type": "application/json",
  },
  withCredentials: true,
});

export const getActivities = createAsyncThunk(
  "activity",
  async (_, { rejectWithValue }) => {
    try {
      const response = await privateAxiosInstance.get("activities");
      console.log(response);
    } catch (err: any) {
      return rejectWithValue(err.response.data);
    }
  }
);

And here is the problem: I always have a 401 Unauthorized "JWT token not found" error, without any cookie in the request. I don't understand what I'm doing wrong, I'm sure I'm missing something. I read a lot of posts about this problem but I can find a solution that works for me. I tried to:

  • add "localhost" or ".localhost" for the "domain" option in the cookie
  • change my apiUrl to 127.0.0.1 instead of localhost
  • update the cors in the nelmio_cors.yaml file by adding, for example, "http://localhost:5000" in allow_origin
  • change the cookie configuration in the lexik_jwt_authentication.yaml file
  • change the "paths" to ^/api/ instead of "/" in the nelmio_cors.yaml file
  • change withCredentials: true with axios.defaults.withCredentials = true

I don't know if it has something to do with my problem but here is my docker-compose.yaml file configuration if it can help you:

services:
  backend:
    build:
      context: ./back
      dockerfile: Dockerfile
    volumes:
      - ./back:/var/www/html
      - ./docker/conf/vhost.conf:/etc/apache2/sites-available/000-default.conf
    depends_on:
      - mysql
    ports:
      - 8000:80
  frontend:
    build:
      context: ./front
      dockerfile: Dockerfile
    depends_on:
      - backend
    volumes:
      - ./front:/front
    ports:
      - 5000:5000
  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - volume_mysql:/var/lib/mysql
    ports:
      - 3307:3306
  adminer:
    image: adminer:latest
    ports:
      - 8001:8080
    environment:
      ADMINER_DEFAULT_SERVER: mysql
      ADMINER_DESIGN: pappu687
volumes:
  volume_mysql:

Thanks for your help.

Share Improve this question edited Feb 2 at 21:12 Drew Reese 204k18 gold badges246 silver badges274 bronze badges asked Feb 2 at 20:46 caden.kingcaden.king 91 bronze badge 1
  • I did blog here nestenius.se/net/debugging-cookie-problems about how to troubleshoot cookie problems in the browser. – Tore Nestenius Commented Feb 3 at 8:22
Add a comment  | 

1 Answer 1

Reset to default 0

Ok I found my problem. I've made 2 instances of axios:

  • the first one without withCredentials option (used to call /api/login_check for the authentication)
  • the second one the privateAxiosInstance with withCredentials option (to call the endpoints after the authentication, cf. my question)

Conclusion: The first instance of axios must also have the withCredentials option!

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745257221a4619029.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信