Relock TCP server¶
The Relock TCP server is the core component responsible for continuous cryptographic session validation and key rotation. This section details how to deploy, run, connect to storage, and configure the Relock server for your specific environment.
Server start¶
For ease of access from other containers via Docker networking, by default, “strict access mode” is off. This means that if the port is exposed outside the host (e.g., via -p on docker run), it will be open without a password. However, all information in storage is encrypted by external browser-side cryptographic keys, making stored data useless to an adversary.
$ docker run -d --restart always \
-it relockid/server \
--multiprocessing \
--host 0.0.0.0 \
--cache 172.17.0.2 \
--port 8111
Connecting to storage¶
To enable access to the data storage, it is essential to provide the correct IP address and port of the database to the Relock server. These parameters can be configured either via the initialization arguments --cache
and --cache_port
, or by modifying the internal /relock/.env
file. If no external address is explicitly provided, the program will attempt to establish a connection to the internal storage system at the default address 127.0.0.1
.
Docker deployment¶
The Relock service currently doesn’t support NATed environments or any setup where IP addresses or TCP ports are remapped. If the --ip
option is not explicitly provided during initialization, the service attempts to automatically discover its IP address. However, when running inside a Docker container without using --network=host
, the discovered IP address will point to the container’s internal network interface, not the host. Docker employs port mapping, where applications inside a container may be assigned different IP addresses or ports than expected.
To ensure proper IP address discovery and compatibility with the Relock service, Docker containers must be run in host networking mode using the --network=host
option. If needed, the --ip
option can be used to manually specify the correct IP address, which will be published to the service members pool and used by connected clients to establish a connection to the new server.
Observability¶
For monitoring and troubleshooting, the Relock service outputs operational logs (including connection events and key rotation specifics) to standard output. These can be accessed using standard container logging tools, and resource consumption can be tracked with typical Docker or orchestration monitoring solutions.
OpenTelemetry¶
Relock can be seamlessly integrated with OpenTelemetry to provide comprehensive observability into its operations. OpenTelemetry’s instrumentation allows collecting detailed metrics, traces, and logs from Relock instances, enabling performance monitoring, anomaly detection, and effective troubleshooting. This integration supports distributed tracing across multiple Relock nodes, helping to gain insights into request flows and latency throughout the ring architecture. OpenTelemetry compatibility ensures that Relock’s telemetry data can be exported to a wide range of monitoring and analysis platforms, providing flexibility in how service health and performance are visualized and acted upon.
TCP endpoints¶
The Relock service communicates exclusively using JSON-formatted messages over TCP sockets. Each message must include a route field to specify the desired endpoint. If the route is invalid or the client lacks proper authorization, the socket connection will be automatically terminated. This structured approach facilitates access to various server functions.
after¶
When the web application finishes processing an HTTP request and is ready to generate its response, it should call the after
TCP route to finalize processing. The Relock service may respond with cookie directives if any changes are required for the client.
For an expanded overview of the after
route, refer to After the request.
before¶
When the web application receives an incoming HTTP request, it should call the before
TCP route. During this “before” phase, the Relock service performs authentication prior to the application processing the response. The web application must provide the Relock service with user metadata, request-related data, and any available cookies. The Relock service then responds with a security state specific to the request.
For an expanded overview of the before
route, refer to Before the request.
check¶
The check
route validates if a raw token matches the server-side token. This route does not validate the token’s signature, even if provided as an argument. The token should be provided in its raw bytes form or as a hexlified string.
{'route': 'check',
'sid': session.sid,
'rid': request.id,
'token': request.headers.get('token', str()),
'reuse': False}
The reuse argument indicates whether the token can be verified multiple times. If set to False
, the Relock service assumes the token is for one-time use only and forbids reuse.
clear¶
The clear
route is invoked by the JavaScript client upon a key agreement failure. When called, it instructs the server to delete all device-related information associated with the current session from server-side storage. The request requires only the session ID (sid
) and request ID (rid
); no additional parameters are needed. Neither TCP nor HTTP responses return any data upon successful execution.
{'route': 'clear',
'sid': session.sid,
'rid': request.id,
'host': app.config.get('SERVER_HOST')}
This mechanism ensures that, in the event of a key agreement failure, sensitive data is promptly removed from the server, enhancing security by preventing unauthorized access.
close¶
The close
route is invoked by the JavaScript client when a browser tab is closed or navigated away, triggering the unloading of the web page content within that tab’s sandbox. This route informs the Relock service to remove all data associated with the specific screen (tab) from the active session. If the user does not reopen the web page in the same tab sandbox, the corresponding screen identifier is permanently deleted.
{'route': 'close',
'sid': session.sid,
'rid': request.id,
'screen': request.form.get('screen', str()),
'xsid': request.form.get('xsid', str()),
'origin': request.form.get('origin', str()),
'path': request.form.get('path', str()),
'host': app.config.get('SERVER_HOST')}
This process enables Relock to accurately track open tabs and detect when all browser tabs have been closed. Consequently, it allows the service to automatically terminate the user session without requiring manual logout, improving security by reducing the risk of orphaned active sessions and enhancing the user experience.
confirm¶
The confirm
route checks the authenticity and integrity of data received from the client as well as confirms that the provided token was generated using a current and valid version of the shared secret. This additional validation step ensures that tokens are tied to the correct session state, preventing the use of outdated or tampered tokens.
{'route': 'verify',
'sid': session.sid,
'rid': request.id,
'token': request.json.get('token'),
'signature': request.json.get('signature'),
'host': app.config.get('SERVER_HOST')}
Upon successful verification, the route returns a boolean value indicating whether the data are valid. This verification process is critical for maintaining secure communication, as it guards against forgery, replay attacks, and unauthorized access by ensuring both the token and signature are legitimate and up-to-date.
exchange¶
The exchange
route is invoked by the JavaScript client during the initial phase of a Relock session. Its purpose is to establish a secure communication channel by negotiating shared secret material between the client (browser) and the server. Before trust can be established, both the client and the server must agree on a shared secret that will be used for cryptographic operations throughout the session. This process begins with an HTTP request, initiated by the JavaScript client, containing key material and identification parameters. This data must then be forwarded to the Relock service via a TCP client.
{'key': request.json.get('key'),
'hash': request.json.get('hash'),
'xsid': request.json.get('xsid'),
'screen': request.json.get('screen')}
The Relock server responds with a JSON payload that must be forwarded as-is back to the JavaScript client. This response contains the cryptographic materials needed to finalize session initialization on the client side.
{"key": [7, 192, 87, 151, 31, 95, 155, 226, 169, 152, 216, 40, 28, 63, 92, 10, 32, 169, 107, 50, 246, 76, 62, 189, 150, 224, 114, 11, 175, 101, 49, 205], "signer": [225, 180, 249, 227, 15, 4, 236, 80, 120, 126, 181, 250, 198, 56, 31, 130, 31, 194, 243, 169, 85, 123, 151, 65, 199, 225, 126, 32, 109, 10, 88, 8],
"token": "48a52c2f887ba6e792854f1d12b1e5cc51361f642ac80612e2371eec422f7af2368c976f7dca0711f9569897380236bb6b4623ba500d6321999cfeedcac3e24d",
"xsid": "cbd1777b70d8354948aff49f0a948af5",
"recovery": [3, 40, 178, 66, 168, 211, 234, 41, 25, 41, 87, 175, 65, 205, 42, 165, 33, 43, 40, 125, 10, 73, 200, 70, 95, 4, 156, 115, 21, 96, 189, 135, 122, 107, 6, 41, 57, 45, 67, 246, 213, 83, 13, 150, 201, 149, 161, 229, 30, 192, 226, 65, 188, 244, 199, 150, 93, 135, 189, 78],
"restore": false,
"status": true,
"error": ""}
This response includes:
key
: Encrypted symmetric session key to be used for communication.
signer
: Public key used to verify server signatures.
token
: Validation session-bound token derived from the shared secret.
xsid
: Public-safe session identifier.
recovery
: Optional recovery key material.
restore
: Flag indicating if session recovery is in progress.
status
: Indicates success (true) or failure (false).
error
: Contains any relevant error messages if status is false.
expose¶
By default, the Relock service treats all HTTP routes (URLs) as restricted. This requires users to be authenticated and associated with a registered device (i.e., a device assigned to a verified owner) before access is granted. To permit public access without authentication, a route must be explicitly declared as public prior to the server handling HTTP requests.
{"route": "expose",
"url": "/auth/password"}
members¶
The members
route returns the current list of active servers participating in the Relock service ring. The list includes each server’s address, listening host, and the unique identifier assigned to that server within the ring.
{"route": "members"}
missing¶
If the TCP client on the web application side detects a broken connection with a server, it can notify the service ring that the host is down via the missing
route. To invoke this route, the unique identifier (id
) of the affected server must be provided.
{"route": "missing",
"addr": "172.17.0.4",
"host": "0.0.0.0",
"port": 8111,
"id": "ef4b1fad-68e7-4752-9225-12bea43d8d04"}
nonce¶
Key rotation is inevitable after a nonce call, as the service consumes the registered nonce prior to validating the incoming token.
{"route": "nonce"}
The nonce
route generates a rotation nonce and signs it using a private key associated with the currently used device (a.k.a. the user’s browser).
open¶
The open
route is invoked by the JavaScript client when a user opens a new browser tab. The screen
parameter is a randomly generated identifier created by the client-side JavaScript, accessible only within that specific browser tab’s sandbox. The xsid
value, provided by the server and embedded within the HTML document, serves as a safe session identifier exposed to client-side scripts. Similarly, the server
parameter represents the screen identifier currently marked as the active tab on the Relock server side.
{'route': 'screen',
'sid': session.sid,
'rid': request.id,
'screen': request.form.get('screen', str()),
'origin': request.form.get('origin', str()),
'path': request.form.get('path', str()),
'xsid': request.form.get('xsid', str()),
'server': request.form.get('server', str()),
'host': app.config.get('SERVER_HOST')}
This route helps the Relock service maintain accurate tracking of multiple tabs, ensuring consistent session management and security across the browser environment.
protected¶
The protected
route enables protected mode (strict verification) for a device. When protected mode is set to True
, the Relock service prevents the creation of any new devices for the user account. Additionally, all requests to the application will be accepted only from previously authorized devices.
{'route': 'protected',
'sid': session.sid,
'rid': request.id,
'state': None,
'user': session.get('_user_id'),
'email': session.get('email')}
The boolean state
argument sets the protected mode for the user account. If state is passed as None
, the route returns the current status of protected mode without making any changes.
revoke¶
The revoke
route can be used to revoke a previously registered and exposed HTTP route (URL), preventing further access. Once revoked, the route becomes inaccessible unless accessed with valid cryptographic key validation, effectively restricting unauthorized usage.
{"route": "revoke",
"url": "/auth/password"}
screen¶
The screen
route helps the Relock service manage browser multi-tab behavior by tracking the currently active or visible tab. It returns the hash identifier of the screen (tab) that is currently registered and marked as active by the service. This functionality enables the application to maintain consistent session state and user experience across multiple tabs.
{'route': 'screen',
'sid': session.sid,
'rid': request.id,
'host': app.config.get('SERVER_HOST')}
By identifying the active screen, the Relock service can coordinate session-related activities and enforce key rotation appropriately in multi-tab environments, ensuring security and consistency across all open tabs.
sign¶
The sign
route allows the client to request the server to generate a digital signature over a specified data payload. The payload (value
) is submitted as bytes, and the server signs this data using a private key dedicated to the specific device (a.k.a. the client’s browser). This signature enables the client to prove the authenticity and integrity of the data to third parties or for subsequent verification processes.
{'route': 'sign',
'sid': session.sid,
'rid': request.id,
'value': bytes,
'host': app.config.get('SERVER_HOST')}
This route ensures that data signing is securely performed on the server side, leveraging cryptographic secrets that remain protected and never leave the server.
token¶
The token
route generates a server-side token that is cryptographically bound to the current state of the shared secret. This token serves as proof to the client that the data originates from a legitimate and trusted server.
{'route': 'token',
'sid': session.sid,
'rid': request.id,
'host': app.config.get('SERVER_HOST')}
user_accessed¶
When an authenticated user is loaded on the web application (from cookie), the application should notify the Relock service to verify session session integrity via the user_accessed
route. The Relock service may require the user to be logged out if all browser tabs were closed prior to user reinitialization—this refers to a mismatch between an existing authenticated session and missing screen context.
{'route': 'user_accessed',
'sid': session.sid,
'rid': request.id,
'host': app.config.get('SERVER_HOST')}
If a screen context mismatch is detected, the TCP response will return a “423 Locked” status. In the case of a successful operation, the response will always return a “200 OK status.”
user_logged_in¶
Once a user logs into the web application, the application should update the user’s state in the Relock service by calling the user_logged_in
route. User-specific data such as email or ID may be anonymized, as they are not essential for the operation of the service.
{'route': 'user_logged_in',
'sid': session.sid,
'rid': request.id,
'user': user.get_id(),
'email': user.email,
'authenticated': user.is_authenticated,
'active': user.is_active,
'anonymous': user.is_anonymous,
'host': app.config.get('SERVER_HOST')}
If sign-in to the Relock service fails, the TCP response will return a “423 Locked” status if the session is currently inaccessible, or a “410 Gone” status if the session no longer exists. In case of a successful operation, the status is always “200 OK.”
user_logged_out¶
The user_logged_out
route notifies the Relock service that a user has logged out from the current session. It helps the server update session state and perform any necessary cleanup or security measures related to the user’s disconnection.
{'route': 'user_logged_out',
'sid': session.sid,
'rid': request.id,
'addr': request.remote_addr,
'host': app.config.get('SERVER_HOST')}
This route ensures that the Relock service accurately tracks user session status and maintains secure session lifecycle management.
validate¶
The validate
route is invoked automatically by the JavaScript client every time the symmetric key has been rotated or whenever key confirmation is needed. This route should not be triggered manually, as it is an integral part of the identity verification process.
{'screen': request.json.get('screen', str()),
'nonce': request.json.get('nonce', str()),
'token': request.headers.get('X-Key-Token', str()),
'signature': request.headers.get('X-Key-Signature', str())}
The nonce argument has no effect on key rotation at this stage. However, it should be attached to the request to validate potential mismatches at this level, which may indicate a key chain breach.
Note
The JSON response generated by the Relock service should be forwarded strictly as-is to the JavaScript client.
verify¶
The verify
route is responsible for verifying the authenticity and integrity of data received from the client. By validating the provided signature against the signed data and an authentic token, the server confirms that the data has not been tampered with and was generated by a trusted client.
{'route': 'verify',
'sid': session.sid,
'rid': request.id,
'token': request.json.get('token'),
'signature': request.json.get('signature'),
'host': app.config.get('SERVER_HOST')}
Upon successful verification, the route returns a boolean confirmation indicating the validity of the signature.
xsid¶
The xsid
route generates and returns a hash of the current session ID on the Relock server side. Unlike the standard web application session ID, the xsid is designed to be safely exposed to client-side JavaScript. It can then be used in subsequent requests to uniquely identify the Relock session without exposing sensitive session information.
{'route': 'xsid',
'sid': session.sid,
'rid': request.id,
'host': app.config.get('SERVER_HOST')}
This approach enhances security by allowing client-side scripts to reference the session safely while protecting the underlying session identifiers from exposure.
Server configuration¶
The Relock service’s behavior can be extensively customized using environment variables. These variables can be set directly in the operating system’s environment, passed as arguments during docker run
, or defined within the /relock/.env
file. Below is a comprehensive list of available configuration options, along with their default values and descriptions.
General settings¶
These settings define the fundamental identity, network binding, and core routing for your Relock service instance.
NAME
: The name identifier for the Relock service instance. Default:Relock-Service
.
VERSION
: The version string of the Relock service.
HOST
: The network interface IP address the Relock service binds to for incoming TCP connections.0.0.0.0
binds to all available interfaces. Default:0.0.0.0
.
IP
: The specific IP address that this Relock service instance will publish to other members of the ring for peer discovery. Crucial for correct inter-service communication in distributed deployments, especially in Docker. Default:0.0.0.0
(attempts auto-detection if not specified).
PROTOCOL
: Defines the protocol used for internal communications within the Relock service, if applicable. Default:https
.
BLUEPRINT
: Defines the URL prefix under which Relock’s API endpoints are exposed. For example, if set torelock
, Relock’s endpoints will be accessible at/relock/status
,/relock/clear
, etc. This is similar to Flask’s blueprints and allows you to integrate Relock into applications that might have other services running on the same domain or require a specific base path for Relock’s routes. Default:relock
.
Time-to-live (TTL) settings¶
These settings define the expiration durations for various data types managed by Relock, impacting session validity, temporary data retention, and long-term user/device persistence.
SESSION_TTL
: The maximum duration a cryptographic session is considered valid before requiring re-authentication. Default:3600
(1 hour).
REQUEST_TTL
: The maximum duration Relock will maintain temporary, in-memory data associated with a specific ongoing request (e.g., for key exchange or validation). This data can include session-specific details such as user IDs or emails, which Relock creates to process the request, after which it’s automatically discarded. Default:10
(seconds).
USER_TTL
: Defines the time-to-live for anonymous user records in Relock’s in-memory cache. When a user interacts with the client system but has not yet logged in, Relock creates a temporary object to manage their session. This parameter specifies how long that anonymous user object remains active in memory. If the user doesn’t log in within this duration, their anonymous record will be automatically discarded. Default:60
(1 minute).
USER_PERSIST_TTL
: The long-term persistence time-to-live for user data in the storage backend, allowing for recovery after extended periods of inactivity. Default:2592000
(30 days).
DEVICE_TTL
: The time-to-live for active device-related data in the in-memory cache. Default:60
(1 minute).
DEVICE_PERSIST_TTL
: The long-term persistence time-to-live for device data in the storage backend. Default:2592000
(30 days).
Storage and caching settings¶
Relock relies on an external Redis-compatible database for managing session states and caching critical data. These settings define how Relock connects to this storage and how it names its internal session cache within it.
CACHE_HOST
: The hostname or IP address of the Redis OSS-compatible storage backend used by the Relock service. Default:127.0.0.1
.
CACHE_PORT
: The port of the Redis OSS-compatible storage backend. Default:6379
.
SESSION_CACHE
: The name of the session cache used internally by the Relock service. Default:relock_cache
.
Behavior settings¶
These settings define the core operational policies of the Relock server, including how it manages user sessions, handles concurrent access, enforces security by default, and responds to various error or security-critical conditions.
RELOCK_SERVICE_TIMEOUT
: Defines the maximum duration that an idle TCP socket connection for internal Relock service operations will remain open before being automatically terminated. Default:30
(seconds).
RELOCK_SERVICE_TAB_LOGOUT
: Controls whether a user’s Relock session is terminated when all browser tabs associated with the client domain are closed.
If
True
, closing all browser tabs for the domain will result in the user being logged out.If
False
, the user’s session will remain active even after all browser tabs for the domain are closed. The user will stay logged in until the session naturally expires due to inactivity timeout or an explicit logout action.Default:
True
.
RELOCK_SERVICE_MULTITABS
: Controls whether a user is allowed to maintain multiple concurrent active sessions across different browser tabs for the same domain.
If
True
, a user can open several browser tabs for the same domain and remain logged in on all of them simultaneously.If
False
, Relock enforces a strict single active session per user per domain. If a user attempts to open a new browser tab for the same domain while already logged in elsewhere, they will be automatically logged out from all existing active sessions for that domain.Default:
True
.
RELOCK_SERVICE_PROTECTED
: Controls Relock’s default security policy for HTTP route access.
If
True
, Relock adopts a “secure by default” posture, treating all HTTP routes (URLs) as restricted. Access to these routes requires the user to be authenticated and associated with a registered device (i.e., a device assigned to a verified owner). Attempts to access protected routes without the necessary authorization will result in the user being automatically logged out. In this mode, only routes explicitly declared as public using the expose endpoint will be accessible without authentication.If
False
, Relock’s default route protection is disabled, meaning routes are not automatically restricted by this mechanism and may be accessible without authentication unless other security controls are specifically implemented.Default:
True
.
RELOCK_SERVICE_REPROCESS
: Defines Relock’s behavior when a key collision is detected.
If
True
, Relock will log out the affected user, clearing the corrupted key information and allowing the user to re-authenticate with a fresh session.If
False
, Relock will lock the user out, which can trigger an alert to an administrator, requiring manual intervention to investigate and resolve the key integrity issue.Default:
True
.
RELOCK_ABORT_WHEN_NETWORK_CHANGE
: Controls Relock’s policy regarding session continuity when a client’s network location changes during an active session.
If
True
, Relock will automatically terminate (abort) the user’s session if it detects a change in the client’s network location (e.g., a different IP address or network egress point). This enhances security by helping to prevent potential session hijacking or unauthorized access if a session token is illicitly used from a new location.If
False
, Relock will allow the user’s session to persist even if their network location changes. While this offers greater convenience for users (e.g., when switching between Wi-Fi and mobile data, or using a VPN), it may slightly increase the risk of session hijacking if other robust security measures are not in place.Default:
True
.
RELOCK_ABORT_ON_BAD_REQUEST
: Defines Relock’s behavior when a “400 Bad Request” error occurs. This typically indicates that the client’s device cookie is invalid or missing, suggesting potential data manipulation or suspected malicious behavior, where the device can no longer be considered trusted.
If
True
, Relock will log out the affected user, clearing the corrupted client-side key information and allowing the user to re-authenticate with a fresh session.If
False
, Relock will lock the user out, which can trigger an alert to an administrator, requiring manual intervention to investigate and resolve the issue.Default:
False
.
RELOCK_ABORT_ON_CONFLICT
: Defines Relock’s behavior when a “409 Conflict” error occurs. This happens when the device data on the Relock service side is either corrupted or no longer exists (e.g., due to expiration after a long period of inactivity or manual removal during maintenance).
If
True
, Relock will log out the affected user, clearing the corrupted client-side key information and allowing the user to re-authenticate with a fresh session.If
False
, Relock will lock the user out, which can trigger an alert to an administrator, requiring manual intervention to investigate and resolve the issue.Default:
True
.
RELOCK_ABORT_WHEN_GONE
: Defines Relock’s behavior when a “410 Gone” error occurs. This typically means the Relock service could not find the device cookie key, as the associated cryptographic key is no longer present in server storage (e.g., due to an invalid or deprecated cookie, malicious tampering, or inconsistent browser state).
If
True
, Relock will log out the affected user, clearing the corrupted client-side key information and allowing the user to re-authenticate with a fresh session.If
False
, Relock will lock the user out, which can trigger an alert to an administrator, requiring manual intervention to investigate and resolve the issue.Default:
True
.
Key rotation settings¶
This setting controls the behavior of Relock’s continuous client verification and ephemeral key rotation process, which is core to maintaining ongoing session integrity and client legitimacy.
REKEYING_NONCE_TTL
: Defines the maximum duration a client’s current ephemeral key remains valid before the server prompts a key rotation. When this TTL expires, the Relock server’s next response to the client will embed a new, unique nonce within the webpage. The client is then required to use this nonce to generate a new ephemeral key and a corresponding cryptographic proof. This action triggers a fresh challenge-response verification, ensuring the client’s continuous legitimacy. Default:1
(second).
JavaScript client settings¶
This setting controls the caching behavior for the Relock JavaScript library served by the service.
RELOCK_JS_MAX_AGE
: The maximum duration that the web browser is instructed to cache therelock.js
JavaScript library served by Relock. This value is used to set themax-age
directive within theCache-Control
HTTP header for therelock.js
file. Once this duration expires, the browser will request a fresh copy of therelock.js
library from the server, replacing any older cached version. Default:3600
(1 hour).
Observability settings¶
These parameters control Relock’s ability to integrate with external systems for sharing security signals and enabling comprehensive observability.
CAEP_ENABLED
: If true, enables Relock to send and process signals as part of the CAEP (Continuous Access Evaluation Profile) Shared Signals framework. This integration allows for real-time security event sharing between services. Default:False
.
OTEL_ENABLED
: If true, enables Relock to send telemetry data (including traces, metrics, and logs) via OpenTelemetry. This integration allows for centralized collection and analysis of Relock’s operational data for enhanced observability and monitoring. Default:False
.