Connection Authorization

Connection Authorization

When you issue a successful connect request, Plane returns a URL that can be used to route traffic to that particular backend.

Such a URL might look like this:

The random-looking string in the path is a connection token. It tells the Plane proxy which backend to route traffic to. Treat the connection token like a bearer token, because any client that knows it can access the backend.

One of the design goals of Plane is to allow you to keep authorization logic in one place, your primary application backend.

The use of connection tokens allows you to delegate backend access business logic to your own application backend. Typically, the way it works is:

  • A user of your application performs an action that requires a session backend, such as opening a new document or starting a notebook session.
  • In your (traditional; non-session) app backend, you verify (usually with a cookie) that the user who needs to access the backend is authenticated and authorized to access that backend, based on your application’s access control business logic.
  • If the user is authorized, you issue a connect request API call to Plane, resulting in a connection token (a tokenized URL for connecting to the backend).
  • You return the connection token to the user’s browser, which then connects to the backend via the connection token (using fetch(...), new WebSocket(...), etc.)

Associating data with a connection token

You can also associate other information with a connection token, such as the username on whose behalf the connection token was generated. This can be done by passing a string as the user field of the connect request.

You can also specify a JSON object that can be used to associate other arbitrary data with a connection token. This is passed as the optional auth field of the connect request.

When an HTTP request passes through a Plane proxy, the proxy will pass the user and auth data associated with the connection token to the backend as HTTP headers:

  • x-verified-username will pass the user field of the connect request, if it exists.
  • x-verified-user-data will pass the auth field of the connect request, if it exists.

The x-verified-* prefix in Plane is reserved for data that comes from the Plane proxy itself. Plane will strip these headers from any incoming HTTP requests, so that they cannot be spoofed.

user and auth data is treated as secret from the client by Plane; it is only available to the client if you expose it to the client via your session backend.

Secondary secret validation

While embedding bearer tokens in a URL is now accepted practice (opens in a new tab) on the web, it is possible that some environments may treat URLs as non-secret. For example, your application may use a third-party telemetry system that logs metadata associated with fetch requests including the URL, or a user may have a browser extension that logs URLs.

If these are concerns for your application, Plane provies a mechanim for you to do an additional check in your session backend that would prevent someone from using a connection token without knowing an additional secret.

Here’s how it works:

  • When you make a connect request, one of the fields returned is a string field called secret_token. This contains a random string that is unique to the connection token.
  • When you make a request to the backend, you pass along the secret token in any way you like. For example, you could pass it as a header, as a field in a request body, or in a WebSocket handshake message.
  • When a client connects to a backend using a connection token, the Plane proxy will pass the same token in the HTTP request as the x-verified-secret header.
  • The code running in the application backend should then unpack both the token sent by the client (however you decide to encode it) as well as the x-verified-secret header, and ensure that they are the same string.

Note that as far as Plane is concerned, the secret token is just a random string associated with a connection token. It is meant to provide a way for you to optionally do extra validation, but Plane itself does not implement that validation.

Static tokens

By default, every unique connection request will receive a unique connection token. This is the recommended approach when you are deploying your own code to the session backend, because it allows you to revoke tokens independently and attach optional metadata to them, as described above.

The downside of this approach is that it requires special care if your application generates URLs that point in to the session backend, because those URLs will need to take the dynamic path into account.

In those cases, you may want to have a single static token which is available to the backend at spawn time, instead of a different connection token for each user. This can be accomplished by setting use_static_token to true in the spawn configuration. This will cause Plane to generate a single token for the backend, which is passed to the backend as the SESSION_BACKEND_STATIC_TOKEN environment variable.

Note that when using static tokens, since every client shares the token, each client has the same level of access to the backend. This means that static tokens can't be provided with user or auth data.