Skip to main content

Authentication and authorization

Authentication and authorization are cross-cutting: they apply whether you use ingests, outlets, or APIs, call the control plane or the CLI, or attach a product to an application in an organization.

  • Identity — Callers use short-lived bearer tokens (usually JWTs) on the data plane. You obtain a Dataspine access token from the platform's Security Token Service (STS) using one of the flows below, or you supply a token you already have (file, static, or a custom provider in your client).
  • Authorization — The platform decides what each identity may do. See Authorization model.
  • Applications — An application adds CORS and other front-door rules; applications are org-scoped and may span multiple data products. AWS SigV4 and SSH key registration are principal-scoped, not application-scoped — see below.

Wire details, status codes, and SDK configuration (token providers, exchange endpoints) are in Application integration and the transports reference.

Authorization model

The platform is built around principals, resources, and permissions.

  • A principal is an actor the platform recognizes after authentication—typically a person or an automation account. The bearer token is tied to a principal with a stable id you see in UIs, CLIs, and logs.
  • A resource is something the platform governs: an organization (or a node in the org tree), a data product, a specific ingest or outlet version, an application, a type library, and so on. Policies attach to these identifiers. Organizations matter for inheritance: rules that apply to a parent org can flow to children according to your tenant's model, and you can set narrower rules on specific products or applications when needed.
  • A permission is a named capability on a resource: for example appending to an ingest, reading an outlet, calling a given unary API, or using control-plane management APIs. The exact permission strings are the contract between the platform and your administrator tooling; the mental model is always: this principal may perform this action on this resource.
  • Grants are the assignments your administrators create (and revoke) to link a principal, a permission, and a resource. The control plane and data plane both enforce the same model for their respective operations.
  • Enforcement happens on every request using the token: the service checks that the principal in the token is allowed to perform the operation on the target resource. Depending on the failure mode, the platform responds with unauthenticated (unknown or invalid token) or unauthorized / forbidden (known identity but not permitted).

That model applies consistently to gRPC and REST on the data product, and to control plane APIs for org and product lifecycle.

Token exchange

Apps usually do not store a long-lived Dataspine password. Instead, you prove a federated or infrastructure identity, and the STS issues a short-lived Dataspine access token (with a normal expiry) for Authorization: Bearer … on ingest, outlet, and API calls. Client libraries can refresh the token on a schedule by re-running the same exchange; the TypeScript client documents exchange-token, aws-sigv4, and ssh-ed25519 configuration shapes.

The subsections below describe three common proof methods. All end in the same kind of Dataspine bearer token; they differ in how you authenticate before the exchange.

OIDC (ID token)

  1. A user or workload completes sign-in with your organizational identity provider using OpenID Connect, in the way your admin has connected that IdP to Dataspine (interactive login, device code, or other supported patterns).
  2. The IdP issues an OIDC ID token (and your application may also receive refresh material managed outside Dataspine).
  3. Your app or automation posts the ID token to the Dataspine token exchange endpoint for the right region (and, with applications, you may pass an application id to scope the resulting token to that delivery context, when your org uses that option).
  4. The request uses the standard OAuth 2.0 token exchange parameters (grant type urn:ietf:params:oauth:grant-type:token-exchange, with the subject token and a subject token type that identifies an ID token; see RFC 8693 for the general pattern). The STS validates the IdP's signature and claims against your tenant's identity configuration, maps the subject to a Dataspine principal, and returns a Dataspine access token with a suitable lifetime.

CLI: dataspine sts exchange-token with the ID token as the argument; use -a / --application when you need to scope the exchange to an application. Overview: dataspine sts.

When to use: End users and services that already use your IdP and should not need AWS keys or SSH keys in that tier.

AWS SigV4 (IAM)

  1. The client has AWS credentials through the usual chain (environment, profile, instance role, etc.).
  2. The client (for example the Dataspine CLI) builds a signed HTTP request that proves control of that AWS identity: the signature follows AWS Signature Version 4 for a well-defined Security Token Service GetCallerIdentity–style call, and includes headers the platform needs to bind the proof to a pre-registered Dataspine principal id and the correct token-exchange URL.
  3. That signed payload is submitted to Dataspine's STS as the token-exchange subject. The service verifies the SigV4 signature, resolves the AWS identity to the linked Dataspine principal, and returns a Dataspine access token.

Principal setup (orthogonal model): An AWS IAM ARN is associated directly with a principal — not with an application. This means one principal can hold multiple IAM ARNs, and the same principal can be used across multiple applications and data products without duplicating the registration. Use create-principal-aws-association:

dataspine create-principal-aws-association \
--principal <principal-selector> \
--iam-principal-arn arn:aws:iam::123456789012:role/MyRole

The infrastructure reconciler reads the Principal CR and creates the corresponding Vault entity alias. CORS and other application-level rules are configured separately on the application.

CLI: dataspine sts exchange-aws-token with the Dataspine principal UUID; optional -a / --application for application scoping.

When to use: CI, workloads on AWS (EC2, EKS, Lambda, etc.) where IAM is the natural trust root and a principal has been linked to a known cloud identity in your org.

SSH proof-of-possession (ed25519)

  1. The client requests a fresh one-time nonce from the Dataspine STS (the CLI fetches it over HTTP before building the subject token for the exchange).
  2. The operator or agent signs that nonce with an ed25519 OpenSSH private key; the corresponding public key must be registered for the target Dataspine principal in your tenant's key policy.
  3. The client sends principal id, public key material, nonce, and signature in the subject of the token exchange request. The STS verifies the cryptographic signature and that the key is allowed for that principal, then issues the Dataspine access token. Expired or reused nonces are rejected to limit replay.

Principal setup (orthogonal model): SSH public keys are associated directly with a principal — not with an application. Use create-principal-ssh-association:

dataspine create-principal-ssh-association \
--principal <principal-selector> \
--ssh-public-key "ssh-ed25519 AAAA..."

CLI: dataspine sts exchange-ssh-pop-token with the principal UUID and paths to the ed25519 private and public key files; optional -a / --application for application scoping.

When to use: Developers and operators who already use SSH keys and want a proof-of-possession style flow without using an IdP on that host.

See alsoClient SDKs · Applications · Organizations · Control plane · Observability (correlation and audit with identity context) · dataspine sts

Client library access

Each data product has a generated client library (npm and cargo) published to the Dataspine artifact repository — a private package registry scoped to your tenant. Access to a data product's client library is a separate, per-data-product permission (client_read) that must be explicitly granted to each principal that needs to install it.

Slug: the stable package identifier

When a data product is created, the platform generates a canonical slug from its root_namespace:

  • Characters are lowercased; . and _ become -; consecutive hyphens are collapsed; leading/trailing hyphens are stripped.
  • An 8-character base32 hash derived from the data product's UUID is always appended (e.g. com-example-product-a1b2c3d4). This disambiguates data products that share a root_namespace and makes the slug stable across renames.
  • A separate cargo slug is generated for the Rust ecosystem so that dataspine-client-{cargo_slug}-{major}-{minor}-{patch} fits within Cargo's 64-character crate name limit. When the namespace is short enough, cargo_slug == slug.

The slug is embedded verbatim in every package name; it is also the OpenFGA resource identifier used to check access.

Granting client library access

An organization administrator (or data product administrator) can grant client_read on a data product's client library to any principal:

dataspine grant-permission \
--principal <principal-uuid> \
--resource data_product_client:<slug> \
--permission client_read

Replace <slug> with the canonical slug of the data product (visible in dataspine list-data-products output or the control plane UI). The grant applies to both npm and cargo; Cargo requests for the cargo_slug variant resolve to the canonical grant via an internal alias.

To revoke access:

dataspine revoke-permission \
--principal <principal-uuid> \
--resource data_product_client:<slug> \
--permission client_read

Inherited access

Data product administrators and organization administrators automatically inherit client_read — no explicit grant is needed for principals with those roles.

Configuring npm credentials

Configure npm to authenticate against the Dataspine artifact repository using a Dataspine bearer token:

npm config set @dataspine:registry https://<artifact-repository-host>/npm/
npm config set //<artifact-repository-host>/npm/:_authToken <dataspine-token>

After configuration, install a data product client library with:

npm install @dataspine/dataspine-client-node-<slug>-<major>-<minor>-<patch>

Configuring cargo credentials

Add the Dataspine registry to your ~/.cargo/config.toml:

[registries.dataspine]
index = "sparse+https://<artifact-repository-host>/cargo/"

[registry]
token = "<dataspine-token>"

Or supply the token in the environment:

CARGO_REGISTRIES_DATASPINE_TOKEN=<dataspine-token> cargo add dataspine-client-<cargo_slug>-<major>-<minor>-<patch>

Status codes

SituationHTTP status
No bearer token provided401 Unauthorized
Valid token but client_read not granted404 Not Found (prevents leaking the existence of private data products)
Authorization service temporarily unavailable503 Service Unavailable