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 thenelmio_cors.yaml
file - change
withCredentials: true
withaxios.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 thenelmio_cors.yaml
file - change
withCredentials: true
withaxios.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
1 Answer
Reset to default 0Ok 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
withwithCredentials
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条)