You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I’m working on a Symfony 6 project with API Platform where users can log in and receive JWT tokens (I use lexik_jwt_authentication) to access private pages. I’m using the Mercure protocol to send real-time updates, and I’d like to create private updates, such as notifications, for authenticated users. I’m also using MongoDB as my database.
I’ve set up my Notification entity as an API resource and configured it to use Mercure for real-time updates. Here’s the relevant configuration for my Notification entity:
// src/Document/Notification.php
namespace App\Document;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Get;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Symfony\Component\Serializer\Annotation\Groups;
#[MongoDB\Document]
#[ApiResource(
normalizationContext: [
'groups' => [
'notification:get',
]
],
mercure: ['private' => true],
)]
#[GetCollection(
uriTemplate: '/notifications',
normalizationContext: [
'groups' => [
'notification:get',
]
],
security: "is_granted('IS_AUTHENTICATED_FULLY')",
)]
#[Get(
normalizationContext: [
'groups' => [
'notification:get',
]
],
security: "is_granted('IS_AUTHENTICATED_FULLY') and object.getTo() === user",
)]
class Notification
{
#[MongoDB\Id()]
#[Groups(['notification:get'])]
private $id;
#[MongoDB\Field(type: 'string')]
#[Groups(['notification:get'])]
private $message;
// Other fields and getter/setter methods...
}
I’ve also created a JWTCreatedListener to add Mercure claims to the JWT payload:
// src/EventListener/JWTCreatedListener.php
namespace App\EventListener;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
use Symfony\Component\Security\Core\User\UserInterface;
class JWTCreatedListener
{
public function onJWTCreated(JWTCreatedEvent $event): void
{
$user = $event->getUser();
if (!$user instanceof UserInterface) {
return;
}
$payload = $event->getData();
// Define the topics the user can subscribe to
$topics = ["http://localhost/api/notifications/65437333e5ddba2e970a2dd2"];
// Add Mercure claims to the payload
$payload['mercure'] = [
'subscribe' => $topics,
];
$event->setData($payload);
}
}
On the client side, I’m using the EventSource to include the JWT token in the request headers:
<!DOCTYPE html>
<html>
<head>
<title>Mercure Real-Time Updates Test</title>
</head>
<body>
<h1>Real-Time Updates with JWT</h1>
<div id="update-container">
<!-- Real-time updates will be displayed here -->
</div>
<script type="module">
// Replace with your actual Mercure hub URL
const mercureHubURL = 'http://localhost:8082/.well-known/mercure';
// Replace with the actual topic URL for the resource you want to track updates for
const topicURL = 'http://localhost/api/notifications/65437333e5ddba2e970a2dd2';
const userJwtToken = 'your_jwt_token_here';
const eventSource = new EventSource(`${mercureHubURL}?topic=${topicURL}`, {
withCredentials: true,
headers: {
Authorization: `Bearer ${userJwtToken}`
}
});
eventSource.onmessage = (event) => {
// Handle the real-time update received from Mercure
const updateData = JSON.parse(event.data);
// Display the real-time update in the container
const updateContainer = document.getElementById('update-container');
updateContainer.innerHTML += `<p>Real-time update: ${JSON.stringify(updateData)}</p>`;
// You can update your UI or perform any necessary actions with the updated data here
};
</script>
</body>
</html>
Despite this setup, I’m encountering a 401 Unauthorized error when trying to receive updates:
GET http://localhost:8082/.well-known/mercure?topic=http://localhost/api/notifications/65437333e5ddba2e970a2dd2 net::ERR_ABORTED 401 (Unauthorized)
I’ve verified that the JWT token includes the correct Mercure claims and that the secret used to sign the JWT token matches the one configured in the Mercure hub.
Can anyone help me identify what might be going wrong or suggest any steps I might have missed?
Thank you in advance!
The text was updated successfully, but these errors were encountered:
Hello everyone,
I’m working on a Symfony 6 project with API Platform where users can log in and receive JWT tokens (I use lexik_jwt_authentication) to access private pages. I’m using the Mercure protocol to send real-time updates, and I’d like to create private updates, such as notifications, for authenticated users. I’m also using MongoDB as my database.
I’ve set up my Notification entity as an API resource and configured it to use Mercure for real-time updates. Here’s the relevant configuration for my Notification entity:
I’ve also created a JWTCreatedListener to add Mercure claims to the JWT payload:
On the client side, I’m using the EventSource to include the JWT token in the request headers:
Despite this setup, I’m encountering a 401 Unauthorized error when trying to receive updates:
GET http://localhost:8082/.well-known/mercure?topic=http://localhost/api/notifications/65437333e5ddba2e970a2dd2 net::ERR_ABORTED 401 (Unauthorized)
I’ve verified that the JWT token includes the correct Mercure claims and that the secret used to sign the JWT token matches the one configured in the Mercure hub.
Can anyone help me identify what might be going wrong or suggest any steps I might have missed?
Thank you in advance!
The text was updated successfully, but these errors were encountered: