Raster

Authentication

Sign users in with a code they approve in Raster, or connect an organization API key, and choose where the credential is stored.

A client uses one credential: a user sign-in or an organization API key. The client checks it with Raster, then saves it in the credentials store you pass to createRasterClient, except a shared key.

Device sign-in

signInWithDevice uses the OAuth device authorization grant:

import {
  createRasterClient,
  localStorageCredentialStore,
  signInWithDevice,
} from '@raster-app/sdk'

const raster = createRasterClient({
  host: { name: 'My App', openExternal: (url) => window.open(url, '_blank') },
  credentials: localStorageCredentialStore(),
})

const controller = new AbortController()
const credentials = await signInWithDevice(raster, {
  onCode: (device) => console.log(`Approve ${device.userCode} in your browser`),
  signal: controller.signal,
})
  1. onCode receives the code. Show device.userCode to the user.
  2. The client opens device.verificationUrl through host.openExternal. Pass openBrowser: false to open it yourself.
  3. On the Connect page, the user signs in, checks the code, and allows access.
  4. The call resolves with the stored credentials, including userName and organizations ({ id, name } each).

To cancel, abort the signal. The call rejects with ABORTED when cancelled, access_denied when the user denies access, and expired_token when the code expires (see Errors).

Users can revoke your app, listed by host.name, under Profile settings → Connected apps.

Sign in to one organization

By default, the user grants every organization they belong to, or picks one. To require exactly one, pass scope: 'org' and the organization's slug as organizationId:

await signInWithDevice(raster, {
  scope: 'org',
  organizationId: 'acme',
  onCode: (device) => console.log(`Approve ${device.userCode} in your browser`),
  signal: controller.signal,
})

The slug is the first path segment of the organization's URL, like acme in https://raster.app/acme. Tell the user which organization to choose. If they grant another one or the whole account, the call rejects with ORGANIZATION_MISMATCH and the previous credential stays.

API keys

An organization API key reaches one organization, with the library access set on the key. Create one under Organization settings → API keys (see API keys), then connect it:

import { connectApiKey } from '@raster-app/sdk'

await connectApiKey(raster, { apiKey: 'your-api-key' })

connectApiKey checks the key and resolves with the stored credentials: userName is null, and organizations lists the key's organization.

  • An empty key fails with API_KEY_REQUIRED.
  • A rejected key fails with the API's error, such as INVALID_API_KEY, and the previous credential stays.

Share an API key with every user

To let every user of your app browse without signing in, connect an organization API key your app holds:

import { connectSharedApiKey } from '@raster-app/sdk'

await connectSharedApiKey(raster, {
  apiKey: 'your-shared-api-key',
  organizationId: 'acme',
})

The key stays in memory only, so connect it on each load. With organizationId, only a key of that organization connects. In RasterPicker, pass the key as apiKey.

Every user can read a shared key, so give it Read access to only the libraries they need.

Check a key before saving it

import { checkApiKey } from '@raster-app/sdk'

await checkApiKey(raster, {
  apiKey: 'your-shared-api-key',
  organizationId: 'acme',
})

Where the credential is stored

The credential holds tokens or the API key in plain text, so keep it in a store as private as you need. The SDK ships two:

StoreWhere the credential lives
memoryCredentialStore()In memory. The user signs in on every load.
localStorageCredentialStore(key?)In localStorage under key (default raster.credentials). Any script on your origin can read it. If localStorage is blocked, it lasts until reload.

Or pass your own CredentialStore:

interface CredentialStore {
  load(): Promise<StoredCredentials | null>
  save(credentials: StoredCredentials): Promise<void>
  clear(): Promise<void>
}

load resolves with the saved credentials, or null. save receives the whole StoredCredentials object; store it as one value. If save rejects, the call that triggered it rejects with that error.

Give each client its own store, for example a localStorageCredentialStore with a different key per organization.

Sign out

import { signOut } from '@raster-app/sdk'

await signOut(raster)

Signing out saves a signed-out credential and revokes the sign-in, which removes your app from Connected apps. It completes even when Raster can't be reached.

For an API key, signing out only removes it from the store. The key stays valid until you regenerate or delete it in Organization settings.

On this page