Skip to content

Security

spark-connect-js handles TLS and bearer-token authentication through the connection string. Token-over-insecure is rejected unconditionally; anything beyond that (custom CAs, mTLS, custom verify callbacks) drops down to GrpcTransportOptions. The full URL parameter reference lives in Configuration.

Spark Connect 4.0’s gRPC server listens in plaintext. Production deployments terminate TLS at a reverse proxy in front of the port, and use_ssl=true on the connection string makes spark-connect-js do the TLS handshake against that proxy. Spark itself never sees the encrypted bytes.

connect("sc://spark.internal:443/;use_ssl=true");

use_ssl=true swaps the underlying gRPC channel to grpc.credentials.createSsl(), which trusts whatever roots Node’s TLS layer trusts (the bundled Mozilla CA list plus anything in NODE_EXTRA_CA_CERTS). For a self-signed or private-CA cert, point NODE_EXTRA_CA_CERTS at the CA bundle before starting the process. For a custom ChannelCredentials (mTLS, custom verify callback), drop down to GrpcTransportOptions.channelCredentials; see the Node integration page.

The node-tls-behind-proxy example demonstrates the full deployment topology end to end with Caddy in front of apache/spark:4.0.0.

connect("sc://spark.internal:443/;token=abc;use_ssl=true");

The token is attached as authorization: Bearer <token> on every RPC via combineChannelCredentials(createSsl(), createFromMetadataGenerator(...)). The presence of token= implicitly enables TLS; an explicit use_ssl=false together with token= is rejected at parse time.

Once a session is built, the bearer token is sealed into the channel and can’t be swapped in place. To rotate, build a new session with the new token, drain in-flight queries on the old session, then call stop() on it.

const stale = oldSession;
const fresh = connect(`sc://spark.internal:443/;token=${newToken};use_ssl=true`);
await drain(stale);
await stale.stop();

Any unreserved ;key=value pair on the URL is attached to every RPC as gRPC metadata. Use it for tenant tags or proxy-auth headers your reverse proxy expects.

connect("sc://spark.internal:443/;use_ssl=true;tenant=acme;x-deploy=blue");

Reserved keys are token, user_id, session_id, use_ssl, user_agent, and grpc_max_message_size.

Each RPC carries the spark.connect.Plan (or analyze/config/interrupt request) in the body, plus metadata:

  • user-agent: <your prefix> spark-connect-js/<version> (node <version>; <platform>).
  • authorization: Bearer <token> if a token is configured.
  • client_observed_server_side_session_id: the most recent serverSideSessionId the server has emitted for this session, echoed back so the server can detect a stale-session mismatch. Cleared on ReleaseSession.
  • Any unreserved connection-string params, as-is.
FeatureStatus
Mutual TLS via the public connect() URLNot implemented. Achievable today through GrpcTransportOptions.channelCredentials directly.
Request IDs / trace propagation (x-request-id, grpc-trace-bin)Not implemented. Set them yourself via custom metadata params if a proxy needs them.
OAuth refresh-token flowsNot implemented. Wrap your token source in code that builds a new session when the bearer expires.

SECURITY.md has the disclosure policy. Don’t file security issues on the public tracker.