Invalid request: both auth code and code verifier should be non-empty
Answered
Spectacled bear posted this in #help-forum
Original message was deleted.
Answered by Spectacled bear
Found the issue :D. Will add it also on github
It seems in dev mode... Next clears Node.js cache on run, so every time there is a "compiling..." in the terminal (which happens per page render), it starts as a new app, losing any previous variable.
Supabase has a memory store that is basicaly lost the first time you go to
It seems in dev mode... Next clears Node.js cache on run, so every time there is a "compiling..." in the terminal (which happens per page render), it starts as a new app, losing any previous variable.
Supabase has a memory store that is basicaly lost the first time you go to
/auth/callback12 Replies
Spectacled bear
It is weird that it works the second/3rd etc time if i try. But it always fails the first time i start the server
Spectacled bear
After some debugging, it seems inside
we have this code:
First time when i start the app i get:
Second/third etc:
I tried this method in both astro / remix and there it works first time. In Next, it seems it doesn't find that storageItem
node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.jswe have this code:
async _exchangeCodeForSession(authCode) {
const storageItem = await getItemAsync(this.storage, `${this.storageKey}-code-verifier`);
console.log(`${this.storageKey}-code-verifier`)
console.log({storageItem});
const [codeVerifier, redirectType] = (storageItem !== null && storageItem !== void 0 ? storageItem : '').split('/');
const { data, error } = await _request(this.fetch, 'POST', `${this.url}/token?grant_type=pkce`, {
headers: this.headers,
body: {
auth_code: authCode,
code_verifier: codeVerifier,
},
xform: _sessionResponse,
});First time when i start the app i get:
storageKey: 'sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier'
storageItem: nullSecond/third etc:
storageKey: 'sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier'
storageItem: 'e3b9d9ff99232e41d08d4f29a56675f8db1cc82a3csomerandomtoken'I tried this method in both astro / remix and there it works first time. In Next, it seems it doesn't find that storageItem
On the first call. But not sure how to debug it further
Spectacled bear
After some aditional tests, i discovered this
const store:Record<string, string> = {
"now": new Date().toISOString(),
};
/**
* Returns a localStorage-like object that stores the key-value pairs in
* memory.
*/
export function memoryLocalStorageAdapter(store: { [key: string]: string } = {}) {
return {
getItem: (key: string) => {
console.log('getting item', key, 'from store', store);
return store[key] || null
},
setItem: (key: string, data: string) => {
console.log('setting item', key, 'from store', store);
store[key] = data
console.log('store is now', store);
},
removeItem: (key:string) => {
console.log('deletting item', key, 'from store', store);
delete store[key]
},
}
}
export const supabase = createClient(
process.env.SUPABASE_URL as string,
process.env.SUPABASE_ANON_KEY as string,
{
auth: {
flowType: "pkce",
autoRefreshToken: false,
detectSessionInUrl: true,
persistSession: true,
storage: memoryLocalStorageAdapter(store),
},
},
);I added this implementation
The first time it errors it goes:
Notice the different now.
The aditional times i get:
So, the Store is not the same instance on the first request made... and then it is shared
setting item sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier from store { now: '2024-02-06T14:30:52.852Z' }
store is now {
now: '2024-02-06T14:30:52.852Z',
'sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier': '"11dab5b81f0ab0b649754e0644b15a8298c7bc544455d66763f394622fe4026b957fcccfd8d5edbd7f18111a222dfe987e5fdcc297b293a3"'
}
getting item sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier from store { now: '2024-02-06T14:30:56.211Z' }Notice the different now.
The aditional times i get:
setting item sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier from store { now: '2024-02-06T14:30:56.211Z' }
store is now {
now: '2024-02-06T14:30:56.211Z',
'sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier': '"9c12a599c1c0e2879cb705837861d9f6d5cf08a2dbabf50ce851b09f500c9060b23e9bd3039a71ad52b27830be48d68961a162d3833c43c7"'
}
getting item sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier from store {
now: '2024-02-06T14:30:56.211Z',
'sb-wcrlwtvozfucqjwumnpc-auth-token-code-verifier': '"9c12a599c1c0e2879cb705837861d9f6d5cf08a2dbabf50ce851b09f500c9060b23e9bd3039a71ad52b27830be48d68961a162d3833c43c7"'
}So, the Store is not the same instance on the first request made... and then it is shared
But I'm not sure why that object would be created multiple times
And only the first time after running "npm run dev"
Spectacled bear
Found the issue :D. Will add it also on github
It seems in dev mode... Next clears Node.js cache on run, so every time there is a "compiling..." in the terminal (which happens per page render), it starts as a new app, losing any previous variable.
Supabase has a memory store that is basicaly lost the first time you go to
It seems in dev mode... Next clears Node.js cache on run, so every time there is a "compiling..." in the terminal (which happens per page render), it starts as a new app, losing any previous variable.
Supabase has a memory store that is basicaly lost the first time you go to
/auth/callbackAnswer
Spectacled bear
When you create your supabase client, add this to auth:
auth: {
flowType: "pkce",
autoRefreshToken: false,
detectSessionInUrl: true,
persistSession: true,
storage: memoryLocalStorageAdapter(store) <---- this part
}// utils/store.ts
const globalForStore = globalThis as unknown as {
supabaseStore: Record<string, string> | undefined;
};
export const store = globalForStore.supabaseStore ?? {
now: new Date().toISOString(),
};
if (process.env.NODE_ENV !== "production") globalForStore.supabaseStore = store;
/**
* Returns a localStorage-like object that stores the key-value pairs in
* memory.
*/
export function memoryLocalStorageAdapter(
store: { [key: string]: string } = {}
) {
return {
getItem: (key: string) => {
console.log("getting item", key, "from store", store);
return store[key] || null;
},
setItem: (key: string, data: string) => {
console.log("setting item", key, "from store", store);
store[key] = data;
console.log("store is now", store);
},
removeItem: (key: string) => {
console.log("deletting item", key, "from store", store);
delete store[key];
},
};
}Basically...it is similar on how you would add prisma, you need to share that singleton in dev mode