nextauth-react-native
v1.0.12
Published
NextAuth utilities for React Native.
Maintainers
Readme
nextauth-react-native
Credentials-only NextAuth / Auth.js session client for React Native.
Ports the familiar NextAuth frontend session API (SessionProvider, useSession, signIn, signOut, update, etc.) to mobile. Talks to your Auth.js / NextAuth backend over HTTP, keeps session + CSRF cookies in local storage, and exposes a shared axios instance that attaches those cookies to API requests.
Scope: frontend session handling only. Credentials provider only — OAuth / social / WebAuthn are not supported.
Table of contents
- Features
- Installation
- Quick start
- How it works
authUrl- API reference
- Cookie storage
- Custom storage
- TypeScript types
- Full app example
- Limitations
- Package exports
Features
| Feature | Description |
| --- | --- |
| SessionProvider | Wraps the app, loads session on mount, exposes context |
| useSession | Same status model as NextAuth: loading / authenticated / unauthenticated |
| signIn / signOut | Credentials sign-in + sign-out against Auth.js endpoints |
| update | POST session updates (same shape as web update()) |
| Cookie jar | Parses Set-Cookie, persists cookies, injects Cookie on requests |
| Shared axios | Business API calls reuse the same cookie jar as auth |
| Refetch | Poll interval, refetch on app focus, optional offline pause |
| Storage | AsyncStorage by default; pluggable AuthStorage |
Installation
npm install nextauth-react-nativeQuick start
import React from "react"
import { ActivityIndicator, Button, Text, View } from "react-native"
import {
SessionProvider,
useSession,
signIn,
signOut,
axios,
} from "nextauth-react-native"
const AUTH_URL = "https://api.example.com/"
export default function App() {
return (
<SessionProvider authUrl={AUTH_URL}>
<Root />
</SessionProvider>
)
}
function Root() {
const { data, status } = useSession()
if (status === "loading") {
return <ActivityIndicator />
}
if (status === "unauthenticated") {
return (
<Button
title="Sign in"
onPress={() =>
signIn("credentials", {
email: "[email protected]",
password: "password",
redirect: false,
})
}
/>
)
}
return (
<View>
<Text>Signed in as {data?.user?.email}</Text>
<Button title="Sign out" onPress={() => signOut({ redirect: false })} />
<Button
title="Call API"
onPress={async () => {
const res = await axios.get("/api/me")
console.log(res.data)
}}
/>
</View>
)
}How it works
React Native has no browser cookie jar. This package recreates Auth.js cookie parity locally:
SessionProvidertakes your API origin (authUrl) and initializes auth + axios against it.- Auth calls go to
{authUrl}/api/auth/*(CSRF, session, credentials callback, signout). Set-Cookieheaders are parsed and stored (AsyncStorage key@nextauth.cookies).- Later requests attach a
Cookieheader from that jar (shared with the exportedaxios). - After
signIn/signOut/update, session context refreshes souseSessionstays in sync.
Auth endpoints (always under /api/auth on your origin):
| Method | Path | Purpose |
| --- | --- | --- |
| GET | /api/auth/csrf | CSRF token |
| GET | /api/auth/session | Current session |
| GET | /api/auth/providers | Provider list |
| POST | /api/auth/callback/credentials | Credentials sign-in |
| POST | /api/auth/signout | Sign out |
| POST | /api/auth/session | Session update (update()) |
authUrl
Required. Your API origin only — no /api/auth suffix.
<SessionProvider authUrl="https://api.example.com/" />| What you pass | Auth base (internal) | Axios baseURL |
| --- | --- | --- |
| https://api.example.com/ | https://api.example.com/api/auth | https://api.example.com |
| https://api.example.com | https://api.example.com/api/auth | https://api.example.com |
Any path on the URL is ignored; only the origin is used. Auth always uses /api/auth, and axios uses the same origin for business routes:
await axios.post("/api/users/fetch", { page: 1 })
// → https://api.example.com/api/users/fetchAPI reference
SessionProvider
import { SessionProvider } from "nextauth-react-native"
<SessionProvider
authUrl="https://api.example.com/"
refetchInterval={0}
refetchOnAppFocus={true}
// refetchWhenOffline={false}
// session={null}
// storage={myStorage}
>
{children}
</SessionProvider>| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| authUrl | string | — | Required. API origin, e.g. https://api.example.com/ |
| children | ReactNode | — | App tree |
| session | Session \| null | undefined | Optional initial session |
| refetchInterval | number | 0 | Poll interval in seconds. 0 disables polling |
| refetchOnAppFocus | boolean | true | Refetch when app becomes active |
| refetchWhenOffline | false | — | Set to false to stop polling while offline |
| storage | AuthStorage | AsyncStorage | Custom cookie persistence |
useSession
import { useSession } from "nextauth-react-native"
const { data, status, update } = useSession()| Field | Type | Description |
| --- | --- | --- |
| data | Session \| null | Session when authenticated; otherwise null |
| status | "loading" \| "authenticated" \| "unauthenticated" | Session lifecycle |
| update | (data?: any) => Promise<Session \| null> | Refresh or mutate session |
useSession({
required: true,
onUnauthenticated: () => {
// e.g. navigate to Login
},
})function RootNavigator() {
const { status } = useSession()
if (status === "loading") return <Splash />
if (status === "authenticated") return <Home />
return <Login />
}signIn
Credentials-only. Defaults to redirect: false.
import { signIn } from "nextauth-react-native"
const res = await signIn("credentials", {
email: "[email protected]",
password: "secret",
redirect: false,
})
if (res?.error) {
// res.error, res.code, res.status, res.ok
}signIn(
provider?: string,
options?: SignInOptions,
authorizationParams?: string | Record<string, string> | URLSearchParams
): Promise<SignInResponse | void>| Option | Type | Default | Description |
| --- | --- | --- | --- |
| email / password / … | any | — | Form fields for the credentials callback |
| redirect | boolean | false | RN does not navigate; you handle url if needed |
| redirectTo | string | "/" | Callback target sent to Auth.js |
| callbackUrl | string | — | Deprecated alias for redirectTo |
{
error: string | undefined
code: string | undefined
status: number
ok: boolean
url: string | null
}Non-credentials providers throw. On success, session context refreshes automatically.
signOut
import { signOut } from "nextauth-react-native"
await signOut({ redirect: false })| Option | Type | Default | Description |
| --- | --- | --- | --- |
| redirect | boolean | false | No browser navigation |
| redirectTo | string | "/" | Auth.js callbackUrl |
| callbackUrl | string | — | Deprecated alias for redirectTo |
{ url: string }Clears the local cookie jar and refreshes session context.
getSession
import { getSession } from "nextauth-react-native"
const session = await getSession() // Session | nullgetCsrfToken
import { getCsrfToken } from "nextauth-react-native"
const csrf = await getCsrfToken()getProviders
import { getProviders } from "nextauth-react-native"
const providers = await getProviders()update (session)
const { update } = useSession()
await update()
await update({ name: "New Name" })axios
Shared Axios instance. baseURL is the origin from authUrl. Same cookie jar as auth.
import { axios } from "nextauth-react-native"
const res = await axios.post("/api/users/fetch", {
search: "",
limit: 10,
page: 1,
})Cookie storage
Cookies are parsed from Set-Cookie, pruned when expired, persisted under @nextauth.cookies, and re-injected on later requests. signOut clears the jar.
Custom storage
import type { AuthStorage } from "nextauth-react-native"
const secureStorage: AuthStorage = {
getItem: async (key) => { /* ... */ },
setItem: async (key, value) => { /* ... */ },
removeItem: async (key) => { /* ... */ },
}
<SessionProvider authUrl="https://api.example.com/" storage={secureStorage}>TypeScript types
import type {
Session,
DefaultSession,
SessionProviderProps,
SignInOptions,
SignInResponse,
SignInAuthorizationParams,
SignOutParams,
SignOutResponse,
UpdateSession,
SessionContextValue,
UseSessionOptions,
ClientSafeProvider,
AuthStorage,
} from "nextauth-react-native"interface DefaultSession {
user?: {
name?: string | null
email?: string | null
image?: string | null
}
expires: string
}
interface Session extends DefaultSession {}A payload counts as authenticated only if it has a non-empty expires string.
Full app example
// App.tsx
import { SessionProvider, useSession } from "nextauth-react-native"
const AUTH_URL = "https://api.example.com/"
export default function App() {
return (
<SessionProvider authUrl={AUTH_URL}>
<RootNavigator />
</SessionProvider>
)
}
function RootNavigator() {
const { status } = useSession()
if (status === "loading") return null
if (status === "authenticated") return <SessionScreen />
return <LoginScreen />
}import { signIn } from "nextauth-react-native"
const res = await signIn("credentials", {
email,
password,
redirect: false,
})import { axios, signOut, useSession } from "nextauth-react-native"
const { data } = useSession()
await axios.post("/api/users/fetch", { page: 1, limit: 10 })
await signOut({ redirect: false })Limitations
| Area | Behavior |
| --- | --- |
| Providers | Credentials only |
| Redirects | No window.location; handle navigation yourself |
| UI | No built-in sign-in screens |
| Auth path | Always {origin}/api/auth — not configurable |
Package exports
SessionProvider
SessionContext
useSession
signIn
signOut
getSession
getCsrfToken
getProviders
axios
// Types
Session, DefaultSession, SessionProviderProps,
SignInOptions, SignInResponse, SignInAuthorizationParams,
SignOutParams, SignOutResponse,
UpdateSession, SessionContextValue, UseSessionOptions,
ClientSafeProvider, AuthStorageLicense
MIT
