Home > database >  Laravel echo server works on web, but does not authenticate with api
Laravel echo server works on web, but does not authenticate with api

Time:04-11

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: App\Events\PrivateMessageSent
- 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...

CodePudding user response:

You should use auth::api as a middleware on BroadcastServiceProvider

class BroadcastServiceProvider extends ServiceProvider
{
    public function boot()
    {        
        Broadcast::routes(['middleware' => ['auth:api']]);

        require base_path('routes/channels.php');
    }
}

Then, you have to send api token for authorization in your request header.

CodePudding user response:

I downgraded (back) to php 7.4 and laravel 8.0. And everything works as expected.

The package lcobucci/jwt within composer.json that needed to be added is deleted again. It is probably this package causing issues as there are raised issues for php 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 setting platform-check to true:

{
    ...
    "config": {
        "platform-check": true
    },
    ...
}

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:

RUN apk add icu-dev
RUN docker-php-ext-configure intl && docker-php-ext-install intl

Later, I will trying updating to laravel 9 again with the last insights...

  • Related