Authentication
Sign a person in, recover an account and verify a sensitive operation.
Preview
This page describes a pre-release version of the SDK. Names, versions and APIs on this page can change before the release.
AuthStore runs the authentication ceremony: the steps a person goes through to sign in to an
account, to recover an account, or to confirm that it is really them before a sensitive operation.
Folio decides which steps the person sees. The SDK asks Folio for the next step, tells your app what
to show through the store state, and sends the answer your app collects back to Folio. Your app
draws the screens; it does not choose a method or build a request.
When a sign-in or a recovery finishes, the SDK switches the session to the account. You see the
new identity in SessionStore.
How it works
- Mount
AuthStoreon the runtime. - Dispatch
Startwith what the person wants to do: sign in, recover an account or verify. - The state moves to
Busywhile the SDK talks to Folio, then toAwaitingInputwith a phase: the input to ask for, such as a password or a one-time code. - Show the input for that phase and dispatch
Answerwith what the person entered. The ceremony can ask for several phases in a row. - The ceremony ends in
Authenticated, or inFailedwith an error. A new account first passes throughAwaitingRecoveryCodeAckto show its recovery code.
let auth = try AuthStore.mount(runtime: sdk)
try auth.dispatch(action: .start(value: .signIn(value: .withIdentifier(
identifier: .email(value: "person@example.com")
))))
let flow = auth.$state
.map(\.flow)
.sink { flow in
switch flow {
case .idle, .busy:
showSpinner()
case let .awaitingInput(phase, alternatives, error):
showInput(phase, alternatives, error)
case let .awaitingRecoveryCodeAck(code):
showRecoveryCode(code)
case .authenticated:
closeSignIn()
case let .failed(error):
showFailure(error)
}
}
try auth.dispatch(action: .answer(value: .otp(value: "123456")))AuthStore takes no init value. It does not have to stay mounted while your app uses the session:
the runtime itself ends a session that Folio has ended. See
Expired sessions.
On iOS AuthStore is an ObservableObject that publishes its state as @Published state,
updated on the main actor; on Android state is a StateFlow<AuthUiModel>; on the web read state
and register a listener with subscribe, which returns the function that removes it. mount takes
the runtime, a FolioSdk. Close the store with close() when you no longer need it.
React
On the web, useAuthStore from @folio/sdk/stores mounts AuthStore for the component that calls
it. It needs a FolioSDKProvider from @folio/sdk/provider above that component.
import { useAuthStore } from '@folio/sdk/stores';
import { AuthAction, AuthAnswer } from '@folio/sdk';
function SignIn() {
const { store, state } = useAuthStore();
if (store === undefined || state === undefined) return null;
const { flow } = state;
if (flow.type !== 'AWAITING_INPUT' || flow.value.phase.type !== 'OTP') return null;
return (
<form
onSubmit={(event) => {
event.preventDefault();
const code = new FormData(event.currentTarget).get('code');
store.dispatch(AuthAction.answer(AuthAnswer.otp(String(code))));
}}
>
<input name="code" maxLength={flow.value.phase.value.length} />
{flow.value.phase.value.canResend && (
<button type="button" onClick={() => store.dispatch(AuthAction.resendOtp)}>
Send a new code
</button>
)}
</form>
);
}useAuthStore returns { store, state }. Both are undefined until the store is mounted after the
first render. The hook re-renders the component on every state change, and closes the store when the
component unmounts or the runtime changes. Every component that calls useAuthStore mounts its own
AuthStore. Call it once, in the component that holds the sign-in screens, and pass store and
state down to them.
Actions
| Action | What it does |
|---|---|
Start { value: AuthStart } | Starts a ceremony. See Start a ceremony. A ceremony in progress is replaced. |
Answer { value: AuthAnswer } | Sends the input for the current phase. See Answers. |
SelectAlternative { method: AuthMethod } | Switches the current step to another method from alternatives. See Alternatives. |
SelectDataRegion { region: DataRegion } | Records the data region the person picks for a new account. See Data region. |
ResendOtp | Sends a new one-time code. See One-time codes. |
AcknowledgeRecoveryCode | Confirms that the person has saved the recovery code shown in AwaitingRecoveryCodeAck, and finishes the ceremony. |
CompleteDeviceLink { challengeId, transferAck } | Answers a DeviceApproval phase. See Device approval. |
Cancel | Abandons the ceremony and returns to Idle. Keys the SDK prepared for the unfinished ceremony are deleted from the device. |
| Action | Swift | Kotlin | TypeScript |
|---|---|---|---|
Start | .start(value:) | AuthAction.Start(value) | AuthAction.start(value) |
Answer | .answer(value:) | AuthAction.Answer(value) | AuthAction.answer(value) |
SelectAlternative | .selectAlternative(method:) | AuthAction.SelectAlternative(method) | AuthAction.selectAlternative(method) |
SelectDataRegion | .selectDataRegion(region:) | AuthAction.SelectDataRegion(region) | AuthAction.selectDataRegion(region) |
ResendOtp | .resendOtp | AuthAction.ResendOtp | AuthAction.resendOtp |
AcknowledgeRecoveryCode | .acknowledgeRecoveryCode | AuthAction.AcknowledgeRecoveryCode | AuthAction.acknowledgeRecoveryCode |
CompleteDeviceLink | .completeDeviceLink(challengeId:transferAck:) | AuthAction.CompleteDeviceLink(challengeId, transferAck) | AuthAction.completeDeviceLink(challengeId, transferAck) |
Cancel | .cancel | AuthAction.Cancel | AuthAction.cancel |
An action that does not fit the current state does nothing. For example, SelectAlternative and
CompleteDeviceLink do nothing when no step is waiting for input, and AcknowledgeRecoveryCode
does nothing outside AwaitingRecoveryCodeAck. ResendOtp also acts while a sign-in or a
recovery is Busy: it restarts that ceremony for the same identifier, as long as the ceremony was
started with one.
Start a ceremony
AuthStart says what the ceremony is for.
| Case | Meaning |
|---|---|
SignIn(NewSession) | Signs the person in to an account. Folio decides whether this signs in to an existing account or creates a new one. |
Recovery(NewRecovery) | Recovers an account whose person can no longer sign in, for example with a recovery code. NewRecovery has one field, identifier. |
Verification(VerificationRequirement) | Confirms the identity of the person who is already signed in. See Verification. |
NewSession is Anonymous, which starts the sign-in without an identifier, or
WithIdentifier { identifier }, which starts it for an email address or a phone number. The
identifier is an AuthIdentifierInput: Email { value } or Phone { value }.
A Recovery started while a sign-in is waiting for input continues from that sign-in.
| Value | Swift | Kotlin | TypeScript |
|---|---|---|---|
| Sign in without identifier | .signIn(value: .anonymous) | AuthStart.SignIn(NewSession.Anonymous) | AuthStart.signIn(NewSession.anonymous) |
| Sign in with an email address | .signIn(value: .withIdentifier(identifier: .email(value: email))) | AuthStart.SignIn(NewSession.WithIdentifier(AuthIdentifierInput.Email(email))) | AuthStart.signIn(NewSession.withIdentifier(AuthIdentifierInput.email(email))) |
| Sign in with a phone number | .signIn(value: .withIdentifier(identifier: .phone(value: phone))) | AuthStart.SignIn(NewSession.WithIdentifier(AuthIdentifierInput.Phone(phone))) | AuthStart.signIn(NewSession.withIdentifier(AuthIdentifierInput.phone(phone))) |
| Recover an account | .recovery(value: NewRecovery(identifier: .email(value: email))) | AuthStart.Recovery(NewRecovery(AuthIdentifierInput.Email(email))) | AuthStart.recovery({ identifier: AuthIdentifierInput.email(email) }) |
| Verify | .verification(value: VerificationRequirement(operation: nil)) | AuthStart.Verification(VerificationRequirement(null)) | AuthStart.verification({ operation: undefined }) |
State
The state of the store is AuthUiModel. Its field flow is an AuthFlowStep; dataRegions and
dataRegion describe the data region choice of a sign-up, see Data region.
| Step | Meaning |
|---|---|
Idle | No ceremony is running. The state after mounting, after Cancel and after Folio ended the session. |
Busy | The SDK is waiting for Folio or for the system passkey dialog. Show progress and do not dispatch answers. |
AwaitingInput { phase, alternatives, error } | The ceremony waits for the input described by phase. alternatives lists the other methods the person may switch to. error is set when the last answer was rejected and the person can try again. |
AwaitingRecoveryCodeAck { code } | A new recovery code was created for the account. Show code to the person, ask them to keep it, then dispatch AcknowledgeRecoveryCode. |
Authenticated | The ceremony has finished. After a sign-in or a recovery, the session switches to the account unless the services for it cannot start; see below. |
Failed { error } | The ceremony has ended with an error that another answer cannot fix. Start a new ceremony to try again. |
| Step | Swift | Kotlin | TypeScript |
|---|---|---|---|
Idle | .idle | AuthFlowStep.Idle | { type: 'IDLE' } |
Busy | .busy | AuthFlowStep.Busy | { type: 'BUSY' } |
AwaitingInput | .awaitingInput(phase:alternatives:error:) | AuthFlowStep.AwaitingInput(phase, alternatives, error) | { type: 'AWAITING_INPUT', value: { phase, alternatives, error } } |
AwaitingRecoveryCodeAck | .awaitingRecoveryCodeAck(code:) | AuthFlowStep.AwaitingRecoveryCodeAck(code) | { type: 'AWAITING_RECOVERY_CODE_ACK', value: { code } } |
Authenticated | .authenticated | AuthFlowStep.Authenticated | { type: 'AUTHENTICATED' } |
Failed | .failed(error:) | AuthFlowStep.Failed(error) | { type: 'FAILED', value: { error } } |
Authenticated stays until you start or cancel another ceremony. The identity the sign-in or
recovery ended on reaches SessionStore: Authenticated with the account's user id
and email address, or Transient when Folio signed the person in to a guest account. If the SDK
cannot switch the session to that identity, for example because the services for it cannot start,
the flow moves on from Authenticated to Failed with SessionUnavailable, and SessionStore
reports the previous identity again with status Device (see
SessionStatus). A
verification does not change the identity.
Phases
AuthPhase is the input the current step waits for.
| Phase | Show | Answer with |
|---|---|---|
Password | A password field. | Password(password) |
Otp { channel, destination, canResend, length } | A field for the one-time code sent to destination. See One-time codes. | Otp(code) |
Totp { length } | A field for the code from the person's authenticator app. length is the number of digits, when known. | Totp(code) |
RecoveryCode | A field for the account's recovery code. | RecoveryCode(code) |
NewPassword | A field to choose a new password, for example for a new account or at the end of a recovery. | NewPassword(password) |
SocialRedirect { authorizationUrl, provider, state } | Sign-in with an external provider. provider is an AuthSocialProvider. See External providers. | SocialRedirect { provider, redirectUri } |
SocialCallback | The return from the external provider. | SocialCallback { code, state } |
IntegratorAttestation { integratorId, nonce } | An attestation from the integrator named by integratorId, over nonce. See Integrator attestation. | IntegratorAttestation { integratorAttestation } |
DeviceApproval { challengeId, freshDeviceFingerprint, freshDevicePlatform, expiresInSeconds } | Approval of this device from a device where the person is already signed in. See Device approval. | CompleteDeviceLink action |
AuthSocialProvider is Google, Apple, Microsoft, Github or Facebook. It is spelled like
AuthMethod: see Alternatives.
| Phase | Swift | Kotlin | TypeScript |
|---|---|---|---|
Password | .password | AuthPhase.Password | { type: 'PASSWORD' } |
Otp | .otp(channel:destination:canResend:length:) | AuthPhase.Otp(channel, destination, canResend, length) | { type: 'OTP', value: { channel, destination, canResend, length } } |
Totp | .totp(length:) | AuthPhase.Totp(length) | { type: 'TOTP', value: { length } } |
RecoveryCode | .recoveryCode | AuthPhase.RecoveryCode | { type: 'RECOVERY_CODE' } |
NewPassword | .newPassword | AuthPhase.NewPassword | { type: 'NEW_PASSWORD' } |
SocialRedirect | .socialRedirect(authorizationUrl:provider:state:) | AuthPhase.SocialRedirect(authorizationUrl, provider, state) | { type: 'SOCIAL_REDIRECT', value: { authorizationUrl, provider, state } } |
SocialCallback | .socialCallback | AuthPhase.SocialCallback | { type: 'SOCIAL_CALLBACK' } |
IntegratorAttestation | .integratorAttestation(integratorId:nonce:) | AuthPhase.IntegratorAttestation(integratorId, nonce) | { type: 'INTEGRATOR_ATTESTATION', value: { integratorId, nonce } } |
DeviceApproval | .deviceApproval(challengeId:freshDeviceFingerprint:freshDevicePlatform:expiresInSeconds:) | AuthPhase.DeviceApproval(challengeId, freshDeviceFingerprint, freshDevicePlatform, expiresInSeconds) | { type: 'DEVICE_APPROVAL', value: { challengeId, freshDeviceFingerprint, freshDevicePlatform, expiresInSeconds } } |
The numeric fields have these types:
| Field | Swift | Kotlin | TypeScript |
|---|---|---|---|
Otp.length, Totp.length | UInt32? | Long? | number | undefined |
DeviceApproval.expiresInSeconds | Int64 | Long | bigint |
freshDevicePlatform is a Platform value that describes this device, such as its operating
system.
Some accounts ask for two inputs in one step. When a step needs a password and an authenticator
code, the phase is first Password; after the password the phase becomes Totp, and the SDK sends
both together when you answer the code. When a step needs a passkey and a password, the phase is
Password and the SDK runs the passkey dialog when you answer with the password.
Answers
AuthAnswer is the input you send with Answer. Send the answer that matches the current phase:
an answer for another phase is not sent, and the step reports the error Unknown.
| Answer | Swift | Kotlin | TypeScript |
|---|---|---|---|
Password(String) | .password(value:) | AuthAnswer.Password(value) | AuthAnswer.password(value) |
Otp(String) | .otp(value:) | AuthAnswer.Otp(value) | AuthAnswer.otp(value) |
Totp(String) | .totp(value:) | AuthAnswer.Totp(value) | AuthAnswer.totp(value) |
RecoveryCode(String) | .recoveryCode(value:) | AuthAnswer.RecoveryCode(value) | AuthAnswer.recoveryCode(value) |
NewPassword(String) | .newPassword(value:) | AuthAnswer.NewPassword(value) | AuthAnswer.newPassword(value) |
SocialRedirect { provider, redirectUri } | .socialRedirect(provider:redirectUri:) | AuthAnswer.SocialRedirect(provider, redirectUri) | AuthAnswer.socialRedirect(provider, redirectUri) |
SocialCallback { code, state } | .socialCallback(code:state:) | AuthAnswer.SocialCallback(code, state) | AuthAnswer.socialCallback(code, state) |
IntegratorAttestation { integratorAttestation } | .integratorAttestation(integratorAttestation:) | AuthAnswer.IntegratorAttestation(integratorAttestation) | AuthAnswer.integratorAttestation(integratorAttestation) |
Passwords and recovery codes never leave the device as entered: the SDK derives what Folio needs from them on the device.
External providers
The SDK passes authorizationUrl through and never opens it: opening the provider's page, for
example in the system browser or an authentication session, and catching the redirect back to your
app are up to you. The SocialRedirect answer names the provider and the redirect URI the provider
returns to. The SocialCallback answer carries the authorization code from that redirect and the
state it echoes, which must be the state of the SocialRedirect phase.
Integrator attestation
Folio asks for an integrator attestation when an account is signed up through an integrator. The
SDK neither creates nor checks it, and FolioSdkConfig has no setting for it: the integrator that
integratorId names issues it from its backend. It is a signed JWT that asserts the person's
identity and carries the nonce of the phase, signed with the key the integrator registered with
Folio. Fetch it from that backend and send it unchanged as the IntegratorAttestation answer;
Folio checks the signature against the registered key.
Alternatives
alternatives in AwaitingInput lists the other methods, as AuthMethod values, that the person
may use for the current step instead of the one in phase. Dispatch SelectAlternative with one of
them to switch; the state moves to AwaitingInput with the phase of that method.
AuthMethod is Password, Otp, Totp, RecoveryCode, NewPassword, SocialRedirect,
SocialCallback, IntegratorAttestation, Passkey or DeviceApproval.
AuthMethod, AuthSocialProvider, OtpChannel and VerificationOperationType have cases without
fields and follow one pattern, shown here for AuthMethod:
| Platform | Spelling |
|---|---|
| Swift | .password, .recoveryCode, .passkey, .deviceApproval, and so on |
| Kotlin | AuthMethod.Password, AuthMethod.RecoveryCode, AuthMethod.Passkey, and so on |
| TypeScript | the value { type: 'PASSKEY' }, { type: 'RECOVERY_CODE' }, and so on, built by the constants AuthMethod.passkey, AuthMethod.recoveryCode, and so on |
On the web these are objects, not strings: compare their type, for example
method.type === 'PASSKEY'.
Passkeys
A passkey has no phase of its own, because the system shows the passkey dialog. When
alternatives contains Passkey, offer a button such as "Use a passkey" and dispatch
SelectAlternative with Passkey: the state moves to Busy while the dialog is shown, then on to
the next step. When a step offers only a passkey, the SDK opens the dialog by itself.
The SDK offers passkeys only on a device that supports them. It checks once when the runtime
starts; until then, and on a device without passkey support, Passkey is not in alternatives.
When a step can only be completed with a passkey and the device has no passkey support, the
ceremony ends in Failed with Unsupported.
if case let .awaitingInput(_, alternatives, _) = auth.state.flow, alternatives.contains(.passkey) {
try auth.dispatch(action: .selectAlternative(method: .passkey))
}When the person closes the passkey dialog, the step reports PasskeyCancelled; when the passkey
fails, it reports PasskeyFailed. The person can try again or choose another method.
One-time codes
The Otp phase describes where the code was sent:
| Field | Meaning |
|---|---|
channel | OtpChannel: Email or Phone. |
destination | The address or number the code was sent to, as Folio shows it, for example partly masked. |
canResend | Whether Folio allows sending a new code for this step. |
length | The number of characters in the code, when Folio states it. |
ResendOtp starts the sign-in or the recovery again with the identifier it was started with, which
makes Folio send a new code. It does nothing for a ceremony started without an identifier and for a
verification. Show a resend button only when canResend is true.
Recovery codes
When a ceremony creates the credentials of an account, the SDK also creates a recovery code for it.
Before the ceremony finishes, the state is AwaitingRecoveryCodeAck with the code. Show the code,
ask the person to store it somewhere safe, and dispatch AcknowledgeRecoveryCode. Only then does
the state become Authenticated and the session switch to the account. The person uses this code
later to recover the account in the RecoveryCode phase.
Verification
Some operations need a fresh confirmation that the person who is signed in is really them. Start
such a confirmation with Start and AuthStart.Verification. It runs the same phases as a sign-in
and ends in Authenticated; it does not change the session's identity.
VerificationRequirement has one optional field, operation:
- Without
operation, the verification confirms the person for the account in general. - With
operation, aVerificationOperation, the verification is bound to one operation.
| Field | Type | Meaning |
|---|---|---|
operationType | VerificationOperationType | DeleteAccount, RotateAccountKey or DeviceLinkApprove. |
binding | String | The value that ties the verification to that operation. |
displayText | String, optional | Text that describes the operation. |
let operation = VerificationOperation(
operationType: .deleteAccount,
binding: binding,
displayText: nil
)
try auth.dispatch(action: .start(value: .verification(value: VerificationRequirement(
operation: operation
))))On Android displayText defaults to null and operation to null, so
VerificationRequirement() starts a verification without an operation. On the web
VerificationRequirement and VerificationOperation are plain objects in which every field must be
present; pass undefined for a field you leave out.
Data region
A sign-up screen can let the person pick where the documents of a new account are stored.
dataRegions lists the options in display order, European Union first, then United States. Each
DataRegionOption has region, a DataRegion (.eu and .us in Swift, EU and US in Kotlin
and TypeScript), title, the name to show in the SDK locale, and selected. dataRegion is the
region picked so far, or none. Dispatch SelectDataRegion when the person taps an option; the
store only records the choice. In this version the SDK does not send the region to Folio, and no
phase of the ceremony waits for it. Start and Cancel clear the choice.
Device approval
In the DeviceApproval phase, Folio asks for this sign-in to be approved from a device where the
person is already signed in. The phase carries the id of the approval request (challengeId), the
fingerprint and platform of this device (freshDeviceFingerprint, freshDevicePlatform) and how
long the request stays valid (expiresInSeconds). When the approval arrives, dispatch
CompleteDeviceLink with the challenge id and the transfer acknowledgement of the approval.
CompleteDeviceLink does nothing when the current step offers no device approval.
transferAck is a signature that the trusted device produces when it approves the request and
hands over the account key. FolioSDK has no API that produces or receives it; Folio's own app does
this on the trusted device. An app built on FolioSDK alone cannot answer this phase: offer the
methods in alternatives, or dispatch Cancel.
Errors
AuthError appears in two places:
- In
AwaitingInput.error, when the step is still open and the person can answer again. - In
Failed.error, when the ceremony is over.
| Error | Reported in | Meaning |
|---|---|---|
WrongPassword | AwaitingInput | The password is wrong, or it does not unlock the account key Folio sent for the step. |
WrongCode | AwaitingInput | The one-time or authenticator code is wrong or has expired. |
WrongRecoveryCode | AwaitingInput | The recovery code is wrong. |
WeakPassword | AwaitingInput | Folio did not accept the new password. |
PasskeyFailed | AwaitingInput | The passkey could not be used. |
PasskeyCancelled | AwaitingInput | The person closed the passkey dialog. |
Locked { until } | AwaitingInput | Too many attempts; answers are blocked for now. until is when they unblock, in Unix seconds, when Folio states it. |
RateLimited { retryAfter } | AwaitingInput | Too many attempts. retryAfter is how many seconds to wait, when Folio states it. |
Network | both | Folio could not be reached. In AwaitingInput the person can send the answer again. |
Unsupported { capability } | both | The step needs something this device or SDK does not support. capability names it. |
Unknown | both | The answer did not fit the step, or an error the SDK cannot classify. |
Expired | Failed | The ceremony or the session it belongs to has expired. Start again. |
RecoveryRequired | Failed | The account can only be entered through a recovery. Start Recovery. |
NotPermitted | Failed | Folio refused the ceremony, for example for a suspended or unknown account, or an identifier already in use. |
ServerError | Failed | Folio failed or rejected the request as invalid. |
TokenPersistFailed | Failed | The ceremony succeeded but the SDK could not store the session on the device. Start again. |
KeyUnavailable | Failed | The SDK could not read or write the account keys on the device. |
SessionUnavailable { message } | Failed | The ceremony succeeded but the SDK could not switch the session to the new identity. message says why. |
An error that would leave a step open is reported in Failed instead when there is no step to go
back to, for example when Start itself fails. A failure the SDK cannot classify while a
Password, Otp, Totp, RecoveryCode or NewPassword phase waits is reported as that phase's
wrong-input error, WrongPassword, WrongCode, WrongRecoveryCode or WeakPassword, instead of
Unknown.
| Error | Swift | Kotlin | TypeScript |
|---|---|---|---|
WrongPassword | .wrongPassword | AuthError.WrongPassword | { type: 'WRONG_PASSWORD' } |
WrongCode | .wrongCode | AuthError.WrongCode | { type: 'WRONG_CODE' } |
WrongRecoveryCode | .wrongRecoveryCode | AuthError.WrongRecoveryCode | { type: 'WRONG_RECOVERY_CODE' } |
WeakPassword | .weakPassword | AuthError.WeakPassword | { type: 'WEAK_PASSWORD' } |
PasskeyFailed | .passkeyFailed | AuthError.PasskeyFailed | { type: 'PASSKEY_FAILED' } |
PasskeyCancelled | .passkeyCancelled | AuthError.PasskeyCancelled | { type: 'PASSKEY_CANCELLED' } |
Locked | .locked(until:) | AuthError.Locked(until) | { type: 'LOCKED', value: { until } } |
RateLimited | .rateLimited(retryAfter:) | AuthError.RateLimited(retryAfter) | { type: 'RATE_LIMITED', value: { retryAfter } } |
Network | .network | AuthError.Network | { type: 'NETWORK' } |
Unsupported | .unsupported(capability:) | AuthError.Unsupported(capability) | { type: 'UNSUPPORTED', value: { capability } } |
Unknown | .unknown | AuthError.Unknown | { type: 'UNKNOWN' } |
Expired | .expired | AuthError.Expired | { type: 'EXPIRED' } |
RecoveryRequired | .recoveryRequired | AuthError.RecoveryRequired | { type: 'RECOVERY_REQUIRED' } |
NotPermitted | .notPermitted | AuthError.NotPermitted | { type: 'NOT_PERMITTED' } |
ServerError | .serverError | AuthError.ServerError | { type: 'SERVER_ERROR' } |
TokenPersistFailed | .tokenPersistFailed | AuthError.TokenPersistFailed | { type: 'TOKEN_PERSIST_FAILED' } |
KeyUnavailable | .keyUnavailable | AuthError.KeyUnavailable | { type: 'KEY_UNAVAILABLE' } |
SessionUnavailable | .sessionUnavailable(message:) | AuthError.SessionUnavailable(message) | { type: 'SESSION_UNAVAILABLE', value: { message } } |
until is a time in seconds since the Unix epoch: an Int64? on iOS, a Long? on Android and a
bigint | undefined on the web.
retryAfter is a number of seconds: a UInt64? on iOS, a Long? on Android and a
bigint | undefined on the web. capability and message are strings.
dispatch itself fails with a CoreError when the store cannot take the action,
for example after the runtime was shut down. For what a closed store throws, see
Store errors.