# PIP-292: Enforce token expiration time in the Websockets plugin

# Background knowledge

This pip is about the websockets plugin of apache pulsar.


# Motivation

When a client connects via Websockets and uses a token as authentication mechanism, the validity of the token is only checked when the connection is established. When the expiry time of the token has passed, the client remains connected.

This is insecure, and makes the websocket implementation unsuitable for a use case where the enforcement of the token expiry time is important.


# Goals

## In Scope
This feature is already supported by the 'regular' pulsar broker. (Only not by the websocket plugin)

The goal is to make token authentication via websockets more secure. And to reduce the difference between a pulsar connection and a websocket connection.

## Out of Scope
It is out of scope to integrate the websocket plugin with the 'regular' pulsar broker. (Even though I believe that is what should happen)


# High Level Design
The implementation should be identical to the implementation that already exists with the 'regular' pulsar broker. This is:

On successful connect: periodically start a task to check the validity of the used authentication.
If a token is expired, a request is sent to the client to provide a new token. If the client does not provide a new token the connection will be closed.

# Detailed Design

## Design & Implementation Details

The design is fully based on the implementation in de Pulsar broker. To summarize:

Extend the [onWebsocketConnect function](https://github.com/apache/pulsar/blob/2ab184e49a036a1dd10dc537bef4ab034a5ad5e0/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/AbstractWebSocketHandler.java#L192) to periodically check the validitity of the supplied AuthenticationData, with the logic as already implemented in the [ServerCnx class](https://github.com/apache/pulsar/blob/2ab184e49a036a1dd10dc537bef4ab034a5ad5e0/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/ServerCnx.java#L886)

Furthermore, the authenticationData used to perform the initial authentication (which includes the token) needs to remain available for the function above to check periodically.
Therefore, some of the authentication logic needs to be placed in the AbstractWebSocketHandler class. Or an extension needs to be made on the [AuthenticationService](https://github.com/apache/pulsar/blob/master/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationService.java) to expose this.


Fully working code has already been created (as a starting point).


## Public-facing Changes

Clients connected with websockets and authenticated with a token can expect to receive the following message:
```{"type":"AUTH_CHALLENGE","authChallenge":{"challenge":{"authMethodName":"token","authData":"token"},"protocolVersion":0}}```

Existing websocket clients might interpret this message as a regular message, and not as a Command message. This could break existing implementations which use expired tokens.

Websocket clients are intended to reply with:
```{"type": "AUTH_RESPONSE", "authResponse": {"clientVersion": "v0", "protocolVersion": 0, "response": {"authMethodName": "token", "authData": "[TOKEN]"}}}```

Existing websocket clients will simply be disconnected in case they do not reply. A reconnect with a new token will suffice to reestablish a connection.


### Public API
NA

### Binary protocol
NA

### Configuration
The already existing variable 'AuthenticationRefreshCheckSeconds' is used.

### CLI
NA

### Metrics
NA


# Monitoring
NA

# Security Considerations
The client has the ability to update the authentication data after a websocket connection has been established. It is technically possible to use a different authentication mechanism than the initial mechanism. However, it is expected that this does not pose any security risks.



# Backward & Forward Compatibility

## Revert
No changes to the websocket client need to be made to use a previous version of the websocket broker.

## Upgrade
Websocket clients need to handle incoming messages containing '"type":"AUTH_CHALLENGE"' as a command. And respond with a new token in a '"type":"AUTH_RESPONSE"' command.


# Alternatives
NA

# General Notes

# Links

* Mailing List discussion thread: https://lists.apache.org/thread/t2vz7rfnply6frrbozw78zg62lgy8g3t
* Mailing List voting thread: https://lists.apache.org/thread/wc9zvrn4977hgndvhzr35f1bb0w59pso
