---
title: Authentication
description: API reference for authentication classes.
---

webrockets provides authentication classes for validating WebSocket connections, following patterns similar to Django REST Framework.

## Import

```python
# Base class (for custom implementations)
from webrockets import BaseAuthentication
from webrockets.auth import AuthenticationFailed

# Django authentication classes
from webrockets.django.auth import (
    SessionAuthentication,
    CookieTokenAuthentication,
    HeaderTokenAuthentication,
    QueryStringTokenAuthentication,
)
```

## BaseAuthentication

Abstract base class for all authentication implementations.

```python
class BaseAuthentication(ABC):
    @abstractmethod
    def authenticate(self, conn: IncomingConnection) -> Any | None:
        """
        Authenticate the connection.

        Returns:
            User object if authentication succeeds.
            None to skip this authenticator and try the next one.

        Raises:
            AuthenticationFailed: If authentication explicitly fails.
        """
        pass
```

### Creating Custom Authentication

```python
from webrockets import BaseAuthentication, IncomingConnection
from webrockets.auth import AuthenticationFailed

class APIKeyAuthentication(BaseAuthentication):
    def authenticate(self, conn: IncomingConnection):
        api_key = conn.get_header("x-api-key")
        if not api_key:
            raise AuthenticationFailed("API key required", close_code=4001)

        user = validate_api_key(api_key)
        if not user:
            raise AuthenticationFailed("Invalid API key", close_code=4003)

        return user
```

## AuthenticationFailed

Exception to raise when authentication fails.

```python
AuthenticationFailed(
    detail: str = "Authentication failed",
    close_code: int = 4003
)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `detail` | `str` | `"Authentication failed"` | Error message |
| `close_code` | `int` | `4003` | WebSocket close code |

```python
raise AuthenticationFailed("Token expired", close_code=4001)
```

## SessionAuthentication

Authenticates using Django's session framework. Ideal for browser clients with active Django sessions.

```python
SessionAuthentication(session_cookie_name: str | None = None)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `session_cookie_name` | `str \| None` | `None` | Cookie name (defaults to Django's `SESSION_COOKIE_NAME`) |

### Usage

```python
from webrockets.django import server
from webrockets.django.auth import SessionAuthentication

chat = server.create_route(
    "ws/chat/",
    "chat",
    authentication_classes=[SessionAuthentication()]
)

@chat.receive
def on_message(conn, data):
    # conn.user is the Django user from the session
    print(f"Message from {conn.user.username}")
```

### Custom Cookie Name

```python
auth = SessionAuthentication(session_cookie_name="my_session")
```

## CookieTokenAuthentication

Base class for token-based authentication via cookies. Subclass and implement `validate_token`.

```python
class CookieTokenAuthentication(BaseAuthentication):
    cookie_name: str = "auth_token"

    def validate_token(self, token: str) -> Any:
        """Override to validate token and return user."""
        raise NotImplementedError()
```

### Usage

```python
import jwt
from django.conf import settings
from django.contrib.auth import get_user_model
from webrockets.django.auth import CookieTokenAuthentication, AuthenticationFailed

class JWTCookieAuth(CookieTokenAuthentication):
    cookie_name = "jwt_token"

    def validate_token(self, token):
        try:
            payload = jwt.decode(
                token,
                settings.SECRET_KEY,
                algorithms=["HS256"]
            )
            User = get_user_model()
            return User.objects.get(pk=payload["user_id"])
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed("Token expired", close_code=4001)
        except (jwt.InvalidTokenError, User.DoesNotExist):
            raise AuthenticationFailed("Invalid token", close_code=4003)
```

## HeaderTokenAuthentication

Base class for token-based authentication via HTTP headers.

:::note
Browser WebSocket connections cannot set custom headers during the handshake. Use this for non-browser clients (mobile apps, backend services) or combine with other authentication methods.
:::

```python
class HeaderTokenAuthentication(BaseAuthentication):
    header_name: str = "authorization"
    keyword: str = "Bearer"

    def validate_token(self, token: str) -> Any:
        """Override to validate token and return user."""
        raise NotImplementedError()
```

### Usage

```python
from webrockets.django.auth import HeaderTokenAuthentication

class BearerTokenAuth(HeaderTokenAuthentication):
    header_name = "authorization"
    keyword = "Bearer"

    def validate_token(self, token):
        return verify_and_get_user(token)
```

Expected header format: `Authorization: Bearer <token>`

## QueryStringTokenAuthentication

Base class for token-based authentication via URL query parameters. Useful for browser clients that cannot set headers.

```python
class QueryStringTokenAuthentication(BaseAuthentication):
    query_param: str = "token"

    def validate_token(self, token: str) -> Any:
        """Override to validate token and return user."""
        raise NotImplementedError()
```

### Usage

```python
from webrockets.django.auth import QueryStringTokenAuthentication

class TokenQueryAuth(QueryStringTokenAuthentication):
    query_param = "auth_token"

    def validate_token(self, token):
        return verify_and_get_user(token)
```

Connection URL: `ws://example.com/ws/chat/?auth_token=xyz123`

:::caution
Query string tokens may appear in server logs. Use short-lived tokens for this authentication method.
:::

## Multiple Authentication Classes

Combine multiple authentication methods. They are tried in order until one succeeds:

```python
from webrockets.django import server
from webrockets.django.auth import SessionAuthentication

class TokenAuth(QueryStringTokenAuthentication):
    def validate_token(self, token):
        return verify_token(token)

chat = server.create_route(
    "ws/chat/",
    "chat",
    authentication_classes=[
        SessionAuthentication(),  # Try session first
        TokenAuth(),              # Fall back to token
    ]
)
```

### Authentication Flow

1. First authenticator's `authenticate()` is called
2. If it returns a user, authentication succeeds
3. If it returns `None`, try the next authenticator
4. If it raises `AuthenticationFailed`, connection is rejected
5. If all return `None`, `conn.user` is `None`

## Complete Example

```python
import jwt
from django.conf import settings
from django.contrib.auth import get_user_model
from webrockets.django import server
from webrockets.django.auth import (
    SessionAuthentication,
    CookieTokenAuthentication,
    QueryStringTokenAuthentication,
    AuthenticationFailed,
)

User = get_user_model()

class JWTCookieAuth(CookieTokenAuthentication):
    cookie_name = "jwt"

    def validate_token(self, token):
        try:
            payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
            return User.objects.get(pk=payload["user_id"])
        except Exception:
            raise AuthenticationFailed("Invalid JWT")

class JWTQueryAuth(QueryStringTokenAuthentication):
    query_param = "token"

    def validate_token(self, token):
        try:
            payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
            return User.objects.get(pk=payload["user_id"])
        except Exception:
            raise AuthenticationFailed("Invalid token")

# Support multiple auth methods
chat = server.create_route(
    "ws/chat/",
    "chat",
    authentication_classes=[
        SessionAuthentication(),  # Browser with session
        JWTCookieAuth(),          # Browser with JWT cookie
        JWTQueryAuth(),           # Any client with token in URL
    ]
)

@chat.receive
def on_message(conn, data):
    if conn.user:
        conn.broadcast(["chat"], f"{conn.user.username}: {data}")
    else:
        conn.send("Anonymous users cannot send messages")
```
