---
title: "Authentication"
package: "WebSocketBundle"
version: "1.x"
canonical_url: "https://www.babdev.com/open-source/packages/websocketbundle/docs/1.x/authentication"
package_supported: true
version_released: false
notice:
  - "Version 1.x of WebSocketBundle has not been released yet. Its API may change before release."
---
# Authentication

The bundle automatically handles authenticating users on every connection to your websocket server by registering additional middleware with the server, allowing your message handlers to use your authenticated user data.

## Authentication Providers

An authentication provider is an implementation of `BabDev\WebSocketBundle\Authentication\Provider\AuthenticationProvider` which processes a `BabDev\WebSocket\Server\Connection` and creates a security token representing the current user.

A provider is required to have two methods:

- `supports()` - Determines if the provider can authenticate the given connection
- `authenticate()` - Authenticates the connection and returns the security token

### Session Authentication

The bundle provides a session authentication provider which will authenticate users using their HTTP session from your website's frontend.

To enable the session authenticator, you must add it to the `providers` list in the authentication configuration and configure the session handler that will be used. In this example, your Symfony application will use the PDO session handler.

```yaml
services:
  session.handler.pdo:
    class: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
    arguments:
      - !service { class: PDO, factory: ['@database_connection', 'getNativeConnection'] }
      - { lock_mode: 0 }

framework:
  session:
    handler_id: 'session.handler.pdo'

babdev_websocket:
  authentication:
    providers:
      session:
        firewalls: ~
  server:
    session:
      handler_service_id: 'session.handler.pdo'
```

Configuring the session handler will add the [`InitializeSession` middleware](/open-source/packages/websocket-server/docs/1.x/middleware/initialize-session) to the websocket server which will provide a read-only interface for the session data from your website.

The `handler_service_id` option reads sessions using the same options as your website, such as the session cookie name, so sessions must be enabled in the `framework.session` configuration. To read sessions without the FrameworkBundle session configuration, use the `factory_service_id` or `storage_factory_service_id` option instead.

When using session authentication, you should also restrict the [allowed origins](/open-source/packages/websocketbundle/docs/1.x/securing-connections#allowed-origins-and-session-authentication) so other websites cannot open connections authenticated as your users.

When the session ID sent by the client is not a valid session ID, or does not match an existing session when PHP's `session.use_strict_mode` setting is enabled, the session is treated as empty and the connection is authenticated as an anonymous user.

By default, the session authentication provider will attempt to authenticate to any of the firewalls set in your `security.firewalls` configuration in the same order which the firewalls are defined. You can specify the firewall(s) to use with the `firewalls` configuration key on the session provider.

The security token is read from the session using each firewall's context, which is the firewall name unless the firewall sets a `context` to share authentication with other firewalls. Firewalls sharing a context are only checked once, and stateless firewalls and firewalls with security disabled are skipped as they do not store a token in the session.

When a connection is authenticated, the user from the session's token is refreshed from your user providers in the same way as when the token is read for an HTTP request. If the user has changed (for example, their roles or password changed) or no longer exists, the connection is authenticated as an anonymous user. The user is only refreshed when the connection is authenticated, so a long-lived connection keeps the user from when it was opened; if your application needs to check the user again while the connection is open, this should be handled by your message handlers.

```yaml
babdev_websocket:
  authentication:
    providers:
      session:
        firewalls: ['main'] # This can be an array to specify multiple firewalls or a string when specifying a single firewall 
```

### Registering New Authenticators

In addition to creating a class implementing `BabDev\WebSocketBundle\Authentication\Provider\AuthenticationProvider`, you must also register the authenticator with a `BabDev\WebSocketBundle\DependencyInjection\Factory\Authentication\AuthenticationProviderFactory` to the bundle's container extension. Similar to factories used by Symfony's `SecurityBundle`, this factory is used to allow you to configure the authenticator for your application and build the authentication provider service. 

A factory is required to have these methods:

- `getKey()` - A unique name to identify the provider in the application configuration, this name is used as the key in the `providers` list
- `getPriority()` - Defines the priority at which the authentication provider is called
- `addConfiguration()` - Defines the configuration nodes (if any are required) for the authenticator
- `createAuthenticationProvider()` - Registers the authentication provider service to the dependency injection container and returns the provider's service ID

The factory must be registered to this bundle's container extension when the container is being built. Typically, this would be in the `build()` method of your application's `Kernel` or a bundle's `Bundle` class.

```php
<?php

namespace App;

use App\DependencyInjection\Factory\Authentication\CustomAuthenticationProviderFactory;
use BabDev\WebSocketBundle\DependencyInjection\BabDevWebSocketExtension;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    protected function build(ContainerBuilder $container): void
    {
        /** @var BabDevWebSocketExtension $extension */
        $extension = $container->getExtension('babdev_websocket');
        $extension->addAuthenticationProviderFactory(new CustomAuthenticationProviderFactory());
    }
}
```

## Storing Tokens

After authentication is complete, the token is stored in a `BabDev\WebSocketBundle\Authentication\Storage\TokenStorage` instance. The default implementation uses a `BabDev\WebSocketBundle\Authentication\Storage\Driver\StorageDriver` as an abstraction layer for where authentication tokens are stored.

By default, the bundle provides and uses an in-memory storage driver. You can provide your own driver implementation by creating a class implementing the driver interface and updating the service container to point the '`BabDev\WebSocketBundle\Authentication\Storage\Driver\StorageDriver`' alias to your implementation.

## Fetching Tokens

The `BabDev\WebSocketBundle\Authentication\ConnectionRepository` provides several helper methods for querying the token storage to find the connections and tokens for any connected user. For example, this repository could be used to find all authenticated users connected to a given topic to send a message.

When a connection's token is no longer in the token storage, the repository authenticates the connection again. If this fails while searching a topic's connections, the connection is treated as an anonymous user so the remaining connections are still searched.

### Token Connection DTO

The `BabDev\WebSocketBundle\Authentication\TokenConnection` object is a DTO which is returned by many of the repository methods and contains the `BabDev\WebSocket\Server\Connection` and its security token from the authenticator. 

### Retrieving All Connections For A Topic

The `findAll()` method is used to find all connections for a given topic. By default, only the connections for authenticated users are returned; the optional `$anonymous` parameter can be set to `true` to also include the connections for unauthenticated users. The list will be returned as an array of `BabDev\WebSocketBundle\Authentication\TokenConnection` objects.

### Retrieving All Connections For A Username

The `findAllByUsername()` method is used to find all connections to a given topic for a user with the given username. This is helpful if a user has multiple active connections (i.e. has multiple tabs in their browser open). The list will be returned as an array of `BabDev\WebSocketBundle\Authentication\TokenConnection` objects.

### Retrieving All Connections For A User With A Role

The `findAllWithRoles()` method is used to find all connections to a given topic for a user who has any of the given roles. Note that this method checks the list of roles on the underlying security token and does not use the site's role hierarchy. The list will be returned as an array of `BabDev\WebSocketBundle\Authentication\TokenConnection` objects.

### Retrieving The Token For A Connection

The `findTokenForConnection()` method is used to find the security token for the given connection.

### Retrieving The User For A Connection

The `getUser()` method is used to retrieve the user for the given connection. This is a shortcut for `$repository->findTokenForConnection($connection)->getUser()`.

### Checking For A Connection By Username

The `hasConnectionForUsername()` method is used to determine if there is a connection to a given topic for the given username and will return true when the first connection matches.
