BA
Better Auth•5mo ago
Oupsla

Expo web doesn't retrieve the token

Hello 👋 I'm trying to use better-auth with expo on the web part. It is working great on the native part, but when trying to sign-in on the web part, it seems that the token is not retrieved. First, I had to make a custom storage and not using SecureStore directly, because it is not available on the web (I have used localStorage at the moment for simplicity, but could use mmkv or something else)
import * as SecureStore from "expo-secure-store";
import { Platform } from "react-native";

export function getItem(key: string): string | null {
if (Platform.OS === "web") {
const value = localStorage.getItem(key);
console.log("getItem", key, value);
return value ?? null;
} else {
return SecureStore.getItem(key);
}
}

export function setItem(key: string, value: string): void {
console.log("setItem", key, value);
if (Platform.OS === "web") {
return localStorage.setItem(key, value);
} else {
return SecureStore.setItem(key, value);
}
}
import * as SecureStore from "expo-secure-store";
import { Platform } from "react-native";

export function getItem(key: string): string | null {
if (Platform.OS === "web") {
const value = localStorage.getItem(key);
console.log("getItem", key, value);
return value ?? null;
} else {
return SecureStore.getItem(key);
}
}

export function setItem(key: string, value: string): void {
console.log("setItem", key, value);
if (Platform.OS === "web") {
return localStorage.setItem(key, value);
} else {
return SecureStore.setItem(key, value);
}
}
Then I use those functions directly in my authClient
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";
import { getItem, setItem } from "./storage";

export const authClient = createAuthClient({
baseURL: baseUrl,
plugins: [
expoClient({
scheme: "myapp",
storagePrefix: "myapp",
storage: {
getItem: getItem,
setItem: setItem,
},
}),
],
});
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";
import { getItem, setItem } from "./storage";

export const authClient = createAuthClient({
baseURL: baseUrl,
plugins: [
expoClient({
scheme: "myapp",
storagePrefix: "myapp",
storage: {
getItem: getItem,
setItem: setItem,
},
}),
],
});
After sign-in and doing a first call, I tried to retrieve the cookie with
const cookies = authClient.getCookie();
const cookies = authClient.getCookie();
but the storage is empty. I see that the
setItem
setItem
seems not to be called on the web, and so
getItem
getItem
is called but return a null value. Do I need to store the token from sign-in method myself on the web, and retrieve it myself ? Thank you for the help !
Solution:
I have finally succeed to make it works. To complete what I have found, I think on the web the set-cookie from the response header should be enough to store the cookie, this is why the "setItem" is skipped on the web. But this should be documented IMO. ...
Jump to solution
7 Replies
Oupsla
OupslaOP•5mo ago
Anyone ? Do I open a issue on github ?
Oupsla
OupslaOP•5mo ago
Hello @bekacru , I have digged in the code source of the expo plugin and found out that the storage of the cookie is disabled on web part (https://github.com/better-auth/better-auth/blob/main/packages/expo/src/client.ts#L153) Do you remember why ? Do we have to handle the token ourself or via another plugin ? Thank you !
GitHub
better-auth/packages/expo/src/client.ts at main · better-auth/bett...
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
Oupsla
OupslaOP•5mo ago
Maybe @Ping you know why ?
Ping
Ping•5mo ago
Sorry, I don't know why
Matheus Pires
Matheus Pires•5mo ago
Hey guys, any updates on this? I'm also trying to implement it in a cross-platform Expo project (web and native), but it's simply not working on the web. I tried the same approach of creating a custom function to define the storage, but so far, no success…
const getStorage = () => {
if (Platform.OS === "web") {
return {
getItem: (key: string) => localStorage.getItem(key),
setItem: (key: string, value: string) => localStorage.setItem(key, value),
removeItem: (key: string) => localStorage.removeItem(key),
};
}
return SecureStore;
};
const getStorage = () => {
if (Platform.OS === "web") {
return {
getItem: (key: string) => localStorage.getItem(key),
setItem: (key: string, value: string) => localStorage.setItem(key, value),
removeItem: (key: string) => localStorage.removeItem(key),
};
}
return SecureStore;
};
Solution
Oupsla
Oupsla•5mo ago
I have finally succeed to make it works. To complete what I have found, I think on the web the set-cookie from the response header should be enough to store the cookie, this is why the "setItem" is skipped on the web. But this should be documented IMO. So to make it work : - Verify that the sign-in response has correct "set-cookie" header, and that cookies are correctly stored (can not be the case for wrong domain, etc...) - Cookies are httponly, so you can't access it from javascript - On fetch, don't retrieve the cookie from authClient, but just set "credentials=include", that will retrieve all cookies and send it to your api
Oupsla
OupslaOP•5mo ago
@Ping do you think could be a good idea to add this to expo plugin documentation ?

Did you find this page helpful?