Auth Hooks and Rate Limits
Handle session state and rate limits in custom auth screens
- Stable unknown
- Release candidate since 1.16.1-rc.3
- Development since 1.16.1-dev.2111+9796905
Use the auth hooks and helpers when a custom form needs to share session state
or implement the same retry behavior as the built-in auth forms. These hooks
require the active client from OvokProvider.
Apply rate limits to a custom form
The SDK's sign-in, registration, and password-reset buttons already disable
submission during a supported cooldown. For a custom Formik screen, use
setRateLimitFormError in the submit handler and useRateLimitCooldown in the
rendering component.
import { useOvok } from "@ovok/core/next/react";
import { useFormik } from "formik";
import {
setRateLimitFormError,
useRateLimitCooldown,
} from "@ovok/native";
import * as Yup from "yup";
import { Button, Text, TextInput } from "react-native-paper";
type RecoveryValues = { email: string; submit: string };
export function CustomRecoveryForm() {
const client = useOvok();
const formik = useFormik<RecoveryValues>({
initialValues: { email: "", submit: "" },
validationSchema: Yup.object({
email: Yup.string().email("Enter a valid email").required("Enter an email"),
submit: Yup.string(),
}),
onSubmit: async (values, helpers) => {
try {
await client.auth.resetPassword({ email: values.email, type: "Patient" });
} catch (error) {
const details = setRateLimitFormError(error, helpers);
if (!details) helpers.setFieldError("submit", "auth.request-failed");
}
},
});
const rateLimitUntil = (
formik.status as { rateLimitUntil?: number } | undefined
)?.rateLimitUntil;
const remainingMs = useRateLimitCooldown(rateLimitUntil);
return (
<>
<TextInput
label="Email"
value={formik.values.email}
onChangeText={formik.handleChange("email")}
onBlur={formik.handleBlur("email")}
error={!!formik.errors.email}
/>
{formik.errors.submit && <Text>{formik.errors.submit}</Text>}
<Button
disabled={formik.isSubmitting || remainingMs > 0}
loading={formik.isSubmitting}
onPress={() => void formik.submitForm()}
>
{remainingMs > 0
? `Try again in ${Math.ceil(remainingMs / 1000)}s`
: "Continue"}
</Button>
</>
);
}Localize the button label and error keys for your app. setRateLimitFormError
stores an absolute rateLimitUntil timestamp in Formik status, sets the
submit error to auth.rate-limit, and returns the parsed details.
Recognized response shapes
getRateLimitDetails(error) recognizes code: "rate_limit", status: 429,
and response.status: 429. It returns a message key and retry delay. A positive
retryAfterMs from @ovok/core's rate-limit error is used when present;
otherwise DEFAULT_RATE_LIMIT_RETRY_MS is 60_000. Unrecognized errors return
undefined, so your form should handle them normally.
The built-in sign-in, registration, and password-reset forms use the same server
delay for their submit cooldown. A wrong password answers 401 (older servers answered 400); both show the
invalid-credentials message. A password the server refuses, such as one shorter than 12 characters or a common
one, answers 422 and its message is shown on the password field. Field errors come from @ovok/core's
readOvokError, so each one has a path; update @ovok/core to read the field errors of newer servers. Their onError callback receives the parsed
SignInError, including retryAfterMs when the server provides it.
useRateLimitCooldown(until) takes the absolute timestamp from Formik status,
returns remaining milliseconds, and updates once per second while active. It
returns 0 when no cooldown remains.
Session state
useSession exposes the current auth status, profile, sessions, refresh
operations, logout, and session revocation. It does not protect routes or choose
where the app navigates. It also exposes switching during account changes and
reason: "session-ended" when the active login ends unexpectedly. See
Session Management for its lifecycle, error behavior, and backend
requirements.
Related guides
Last updated on