When upgrading different packages (php 8.1, laravel 9, …) there is something strange going with the laravel echo server. Using the web domain there is no issue with the echo server, but using the mobile app (through api) it does not authenticate.
It is currently working normally as expected with php 7.3 and laravel 8 without docker as monolith.
I am not sure where to look for the fix as everything was working normally and the configuration itself did not change.
Log output npm start
Laravel Echo Server:
-ryM0******AAAB authenticated for: private-chat.private.1.2
-ryM0******AAAB joined channel: private-chat.private.1.2
Channel: private-chat.private.1.2
Event: AppEventsPrivateMessageSent
- Sending auth request to: https://*.com/broadcasting/auth
⚠ - DdLxkG******AAAC could not be authenticated to private-chat.private.1.2
{
"message": "",
"exception": "Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException",
"file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.php",
"line": 69,
"trace": [ ...
}
laravel-echo-server.json
{
"authHost": "https://*.com",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "*",
"key": "****"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "*.cache.amazonaws.com"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "https",
"socketio": {},
"sslCertPath": "/etc/ssl/certs/selfsigned.crt",
"sslKeyPath": "/etc/ssl/private/selfsigned.key",
"sslCertChainPath": "*",
"sslPassphrase": "*",
"subscribers": {
"http": true,
"redis": true
}
}
We are also migrating to docker services, so here you can find the Dockerfile for the echo worker:
FROM node:alpine
WORKDIR /app
ADD package.json /app/package.json
RUN npm config set registry http://registry.npmjs.org
RUN npm install && npm ls
RUN mv /app/node_modules /node_modules
# Create certs
RUN apk add openssl;
RUN mkdir /etc/ssl/private/
RUN openssl req -x509 -nodes -days 365 -subj "/C=CA/ST=QC/O=Company, Inc./CN=*.com" -addext "subjectAltName=DNS:*.com" -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key -out /etc/ssl/certs/selfsigned.crt;
ADD . /app
ENV PORT 6001
EXPOSE 6001
CMD ["npm", "start", "--force"]
composer.json
{
"require": {
"php": "^8.1",
"laravel-notification-channels/apn": "^4.0",
"laravel-notification-channels/fcm": "^2.4",
"laravel/framework": "^9.0",
"laravel/helpers": "^1.2",
"laravel/passport": "^10.3.3",
"laravel/socialite": "^5.5",
"lcobucci/jwt": "^4.1",
"predis/predis": "^1.1",
"socialiteproviders/apple": "^5.0",
}
}
The BroadcastServiceProvider did not change:
class BroadcastServiceProvider extends ServiceProvider
{
public function boot()
{
if (request()->hasHeader('authorization')){
Broadcast::routes(['middleware' => 'auth:api']);
} else {
Broadcast::routes();
}
require base_path('routes/channels.php');
}
}
Neither did the frontend change:
window.echo = new Echo({
broadcaster: 'socket.io',
...
auth: {
headers: {
Authorization: 'Bearer ' + accessToken,
},
},
});
Tests:
As a test I changed the auth function within channels.php
:
Broadcast::channel('chat.private.1.2', function ($user) {
return true;
});
But this still gives the same error: could not be authenticated… This should be abnormal behaviour as it always should return true…
2
Answers
I downgraded (back) to
php 7.4
andlaravel 8.0
. And everything works as expected.The package
lcobucci/jwt
withincomposer.json
that needed to be added is deleted again. It is probably this package causing issues as there are raised issues forphp 8.1
(https://github.com/lcobucci/jwt/issues/819).Furthermore, I found some interesting things when downgrading.
When using
composer install --no-scripts --no-autoloader
without the flag--ignore-platform-reqs
and allowing platform checks by settingplatform-check
totrue
:There were some interesting raised issues. It tells when there is php version issue and about some missing php extensions, which I added to
Dockerfile
:Later, I will trying updating to
laravel 9
again with the last insights...You should use
auth::api
as a middleware onBroadcastServiceProvider
Then, you have to send api token for authorization in your request header.