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,
})onCodereceives the code. Showdevice.userCodeto the user.- The client opens
device.verificationUrlthroughhost.openExternal. PassopenBrowser: falseto open it yourself. - On the Connect page, the user signs in, checks the code, and allows access.
- The call resolves with the stored credentials, including
userNameandorganizations({ 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:
| Store | Where 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.