Skip to content

Conversation

@IMax153
Copy link
Collaborator

@IMax153 IMax153 commented Dec 20, 2025

This PR adds support for authentication to the Amp TypeScript SDK.

To propagate authentication information along with each request, we leverage a feature of Connect called Context Keys, which are not too dissimilar from Context / Tag in Effect.

An example program that uses the ArrowFlight service to send a query might look like the following:

import { ArrowFlight, Auth } from "@edgeandnode/amp"
import * as ArrowFlightNode from "@edgeandnode/amp/ArrowFlight/Node"
import { NodeHttpClient, NodeKeyValueStore, NodeRuntime } from "@effect/platform-node"
import { Effect, Layer } from "effect"

const program = Effect.gen(function*() {
  const flight = yield* ArrowFlight.ArrowFlight
  yield* flight.query(`SELECT * FROM "_/counter@dev".active_blocks LIMIT 10`)
})

/**
 * Setup the gRPC transport layer with an interceptor that will provide
 * authentication information
 */
const TransportLayer = ArrowFlightNode.layerTransportGrpc({
  baseUrl: `http://localhost:8080/amp`
}).pipe(Layer.provide(ArrowFlight.layerInterceptorBearerAuth))

/**
 * Setup the Arrow Flight layer to be able to execute Arrow Flight SQL queries
 */
const ArrowFlightLayer = ArrowFlight.layer.pipe(
  Layer.provide(TransportLayer)
)

/**
 * Setup the platform-specific dependencies required for our application
 */
const PlatformLayer = Layer.mergeAll(
  NodeHttpClient.layerUndici,
  NodeKeyValueStore.layerFileSystem(".cache")
)

/**
 * Setup the layer which provides authentication services
 */
const AuthLayer = Auth.layer.pipe(
  Layer.provide(PlatformLayer)
)

/**
 * Provide the Auth layer to the Arrow Flight layer and merge the outputs so
 * we can use both in our program
 */
const MainLayer = ArrowFlightLayer.pipe(
  Layer.provideMerge(AuthLayer)
)

program.pipe(
  Effect.provide(MainLayer),
  NodeRuntime.runMain
)

One improvement for the future would be to further abstract the way that authentication tokens are propagated through with each request. At the moment, they are always propagated from the filesystem cache, but we could create an abstraction on top that allows the authentication information to come from anywhere.


readonly requestDeviceAuthorization: (codeChallenge: CodeChallenge) => Effect.Effect<
DeviceAuthorizationResponse,
HttpClientError.HttpClientError | TimeoutException | ParseResult.ParseError
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One big TODO item is to create a more descriptive and targeted error domain for each of these services, but for now while we're developing heavily I'm just propagating all errors through.

@IMax153 IMax153 requested review from cmwhited and fubhy December 20, 2025 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants