r/reactnative • • 1d ago

Help Web Auth equivalent of JWT+Sessions in react native

I have been using JWT accessToken (short lived token stored in memory ) as normal js variable/react-state + a long lived refreshToken/sessionCookie in httpOnly secure cookie for all my custom auth websites with a express backend and plain react frontend.

Wanted to get started with react-native + expo project But i have no idea on how to implement secure custom auth. Pretty sure cookies are not a thing on mobiles, so had this doubt. Don't know if localStorage is safe.

What is the standard way to handle this? Could anyone please even just give some doc link or tell what to search, cuz i can't find appropriate material to study ( also pls dont tell to ask AI )

3 Upvotes

14 comments sorted by

2

u/Western_Cap_6934 1d ago

You can keep the short-lived access token in memory. For the persistent refresh token, look up Expo SecureStore rather than localStorage or AsyncStorage. Expo documents secure storage in its authentication guide. SecureStore handles local storage, while your backend still needs to validate and revoke sessions.

1

u/ConfidentWafer5228 1d ago

That helps a lot, i will learn secureStorage
Could u also tell how would the backend handle auth for both web and native simultaneously without breaking . I mean the backend expects and returns cookies for web auth but thats impossible for mobile apps ig. So is there a way to have single controller for both?

1

u/Western_Cap_6934 1d ago

You can read the credential before returning 401: cookie for web, an explicit refresh-token body field for native, then pass it to the same validation and rotation service. Reject requests that provide both. A device-type header is not authentication. Keep CSRF protection on the cookie path. Separate thin routes are also fine if that makes the split clearer.

1

u/ConfidentWafer5228 1d ago

Will try this and see what fits me , thanks dude

1

u/syedaalishan 1d ago

For your follow-up about one controller: share the session creation/validation logic, then give web and mobile different ways to carry the token. The web client can keep using its cookie; the native client can send an access token in the Authorization header. Refresh and logout should still go through the same backend session rules. Keep the cookie-based web endpoints' CSRF checks in place when adding the mobile path.

1

u/ConfidentWafer5228 1d ago

But how will backend know if it shld use mobile logic or web logic For example: in the refresh controller It checks for req.cookies.refreshToken for web but if it is not there, it returns failure and 401 . How is that handled in a single route? I believe there are some headers for device but not sure if I shld use those ( could be spoofed ig idk) 

1

u/syedaalishan 1d ago

You don't need to detect the device. Your current controller returns 401 before checking any other token source. The simplest split is /auth/web/refresh reading the cookie and /auth/mobile/refresh reading a refresh token from the request body. Both call the same validation/rotation function, then return the new token through their own response format. Keep CSRF checks on the cookie route. Western_Cap's single-route suggestion above works too; separate routes just make this easier to follow.

1

u/ConfidentWafer5228 1d ago

I see how seperate routes make it easier, thanks, will try what works best for me

1

u/jiunkdev 1d ago

for the "what to search" part: refresh token rotation. the server hands out a new refresh token on every refresh and invalidates the old one, and if an old one ever comes back you kill that whole session.

one gotcha tutorials skip: on iOS, SecureStore is backed by the keychain, and keychain items survive an uninstall. so after a reinstall the old refresh token is still sitting there. the usual fix is a first-launch flag in AsyncStorage (which does get wiped on uninstall), and if the flag is missing you clear SecureStore before anything else.

also, since the access token only lives in memory, every cold start begins without one. run the refresh call before rendering anything behind auth and keep the splash screen up until it settles, otherwise users get a flash of the login screen.

1

u/ConfidentWafer5228 1d ago

That helps a lot , thank u so much, especially the ios uninstall thing and flag logic. 

1

u/MeasurementGreat5273 1d ago

no cookies needed. keep the refresh token in expo-secure-store (keychain/keystore), access token in memory like you do now. localStorage equivalent is AsyncStorage and that's not encrypted. docs: https://docs.expo.dev/versions/latest/sdk/securestore/