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.
Device sign-in
auth.signInWithDevice uses the OAuth device authorization grant:
import { createRasterClient, localStorageCredentialStore } 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 raster.auth.signInWithDevice({
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 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 raster.auth.signInWithDevice({
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:
await raster.auth.connect({ apiKey: 'your-api-key' })auth.connect 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.
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
await raster.auth.signOut()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.