@synqauth/react-native
Synq for React Native: sign-in through the system browser, with tokens in the device's secure storage.
@synqauth/react-native
CHUNK_SIZE
Constant. The most one item holds: iOS's keychain takes more, but expo-secure-store
warns past 2048 bytes, and a session's tokens are bigger than that.
const CHUNK_SIZE: 1800createSynqNative
Function. Synq for a React Native app: the system browser for sign-in, the device's secure storage for the session.
function createSynqNative(options: SynqNativeOptions): SynqNativesecureStorage
Function. The device's secure storage (the iOS keychain, Android's keystore) as a
SynqStorage, through expo-secure-store: the session's tokens, the
refresh token included, and a sign-in's transaction. A value too big for
one item is split across several (<key>.0, <key>.1...), with the count
under the key itself. One app is one process, so the lock is in memory.
function secureStorage(store: SecureStoreModule): SynqStorageSecureStoreModule
Interface. The part of expo-secure-store the SDK uses: pass the module itself.
interface SecureStoreModule {
getItemAsync(key: string): Promise<string | null>;
setItemAsync(key: string, value: string): Promise<void>;
deleteItemAsync(key: string): Promise<void>;
}SignInHandover
Interface. What only the hosted page can do for this sign-in, and what to take there.
interface SignInHandover {
readonly reason: RedirectReason;
readonly method?: ChallengeMethod;
readonly loginHint?: string;
}SignInProblem
Interface. What went wrong with the last step: branch on code, never on the English.
interface SignInProblem {
readonly code: ChallengeProblem | 'expired' | 'refused' | 'unavailable';
readonly reason?: DeniedReason;
readonly message: string;
readonly retryAfter?: number;
}SignInStep
Type. Where a sign-in is: what the screen shows.
type SignInStep = 'start' | 'code' | 'verify-email' | 'done';SynqNative
Interface. Synq in a React Native app: @synqauth/js's client, signing in through
the system browser (never an embedded web view, which can read what the
person types) with PKCE and a callback on a link or scheme the app owns,
and keeping the session in the device's secure storage.
interface SynqNative {
readonly client: SynqClient;
readonly resource: string | undefined;
signIn(options?: AuthorizationUrlOptions): Promise<Session>;
signOut(options?: {
browser?: boolean;
}): Promise<void>;
}SynqNativeOptions
Interface. What createSynqNative takes: the app at the brand, and the two Expo modules it runs on.
interface SynqNativeOptions {
issuer: string;
clientId: string;
redirectUri: string;
postLogoutRedirectUri?: string;
scope?: string;
resource?: string;
webBrowser: WebBrowserModule;
secureStore: SecureStoreModule;
fetch?: typeof fetch;
}SynqNativeProvider
Component. Gives the hooks the device's session: it reads it once from secure storage, then follows every sign-in, refresh and sign-out.
function SynqNativeProvider({ synq, issuer, children }: SynqNativeProviderProps): ElementSynqNativeProviderProps
Interface. What SynqNativeProvider takes.
interface SynqNativeProviderProps {
synq: SynqNative;
issuer: string;
children?: ReactNode;
}SynqResult
Type. A call's outcome: its data, or the SynqError it failed with.
type SynqResult<T> = {
readonly data: T;
readonly error: null;
} | {
readonly data: null;
readonly error: SynqError;
};useAuth
Function. Signing in and out.
function useAuth(): UseAuthUseAuth
Interface. What useAuth() answers: signing in and out, each answering { data, error }.
interface UseAuth {
readonly isLoaded: boolean;
readonly isSignedIn: boolean;
signIn(options?: AuthorizationUrlOptions): Promise<SynqResult<Session>>;
signOut(options?: {
browser?: boolean;
}): Promise<SynqResult<null>>;
}useSession
Function. The device's session.
function useSession(): UseSessionUseSession
Interface. What useSession() answers: whether the device's session is read yet, and who is signed in.
interface UseSession {
readonly isLoaded: boolean;
readonly isSignedIn: boolean;
readonly session: Session | null;
}useSignIn
Function. One sign-in on the app's own screens. The provider follows the session
it ends with, as after useAuth().signIn().
function useSignIn(options?: StartSignInOptions): UseSignInUseSignIn
Interface. What useSignIn() answers: the sign-in's step, what went wrong, and each method's steps.
interface UseSignIn {
readonly step: SignInStep;
readonly pending: boolean;
readonly problem: SignInProblem | null;
readonly email: string | undefined;
readonly canSkip: boolean;
readonly handover: SignInHandover | null;
readonly password: {
readonly signIn: (input: {
email: string;
password: string;
}) => Promise<void>;
readonly signUp: (input: {
email: string;
password: string;
}) => Promise<void>;
};
readonly emailCode: {
readonly send: (email: string) => Promise<void>;
readonly verify: (code: string) => Promise<void>;
readonly resend: () => Promise<void>;
};
readonly verifyEmail: {
readonly verify: (code: string) => Promise<void>;
readonly resend: () => Promise<void>;
readonly skip: () => Promise<void>;
};
readonly continueInBrowser: (options?: {
method?: string;
loginHint?: string;
}) => Promise<SynqResult<Session>>;
readonly startOver: () => void;
}useUser
Function. Who is signed in, and their account.
function useUser(): UseUserUseUser
Interface. What useUser() answers: the ID token's claims, and the brand's account API for the person.
interface UseUser {
readonly isLoaded: boolean;
readonly user: IdTokenClaims | null;
readonly account: AccountClient | null;
}WebBrowserModule
Interface. The part of expo-web-browser the SDK uses: pass the module itself.
interface WebBrowserModule {
openAuthSessionAsync(url: string, redirectUrl: string): Promise<{
type: 'success';
url: string;
} | {
type: string;
}>;
}See every package.