认证成功后Supabase Session仍为Null/Undefined问题求助
问题分析与解决方案
为什么会出现null?
- 服务器端的Supabase客户端不会自动持久化会话。
signInWithPassword返回的data里确实包含用户和会话信息,但这些信息并没有自动绑定到当前的Supabase客户端实例上。所以后续调用getUser()时,客户端找不到有效的会话,自然返回null。 onAuthStateChange触发的INITIAL_SESSION是客户端初始化时的状态,此时还没有手动设置会话,所以session值为null是正常的。
修复代码的两种方式
方式1:直接使用登录返回的结果
既然signInWithPassword已经返回了用户和会话信息,没必要再调用getUser(),直接用返回的data即可:
app.post("/login", async(req, res) => { const {data, error} = await supabase.auth.signInWithPassword({ email: req.body.email, password: req.body.password }) if (error) { console.log(error); res.status(401).send("Email/password combination is wrong."); return; } // 直接使用返回的用户信息 console.log(data.user); // 如果需要会话信息也直接用data.session console.log(data.session); res.status(202).send("Login successful."); })
方式2:手动设置会话(适用于后续请求需要认证的场景)
如果你的服务器需要在后续接口中使用Supabase的认证功能,需要把登录得到的会话手动绑定到客户端,同时建议把会话存在Cookie中(服务器端常用做法):
app.post("/login", async(req, res) => { const {data, error} = await supabase.auth.signInWithPassword({ email: req.body.email, password: req.body.password }) if (error) { console.log(error); res.status(401).send("Email/password combination is wrong."); return; } // 手动将会话设置到Supabase客户端 await supabase.auth.setSession({ access_token: data.session.access_token, refresh_token: data.session.refresh_token }) // 现在调用getUser就能拿到用户了 const { data: { user } } = await supabase.auth.getUser(); console.log(user); // 将会话存入Cookie,后续请求自动携带 res.cookie('supabase-access-token', data.session.access_token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: 1000 * 60 * 60 * 24 // 1天有效期 }); res.cookie('supabase-refresh-token', data.session.refresh_token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: 1000 * 60 * 60 * 24 * 7 // 7天有效期 }); res.status(202).send("Login successful."); })
后续接口中,需要从Cookie取出token,恢复会话:
app.get("/profile", async(req, res) => { const accessToken = req.cookies['supabase-access-token']; const refreshToken = req.cookies['supabase-refresh-token']; if (!accessToken || !refreshToken) { return res.status(401).send("Unauthorized"); } // 恢复会话 const { error } = await supabase.auth.setSession({ access_token: accessToken, refresh_token: refreshToken }); if (error) { return res.status(401).send("Invalid session"); } // 现在可以正常获取用户信息 const { data: { user } } = await supabase.auth.getUser(); res.json(user); })
关于Supabase会话机制的说明
- Supabase的会话由
access_token(短期JWT,用于接口认证)和refresh_token(长期令牌,用于刷新access_token)组成。 - 浏览器端SDK会自动将会话存储在
localStorage中,并自动处理令牌刷新,所以调用getUser()能直接拿到用户。 - 服务器端SDK是无状态的,没有自动持久化会话的能力。所有会话管理都需要手动完成:登录后存储会话,后续请求恢复会话,过期时用refresh_token刷新。
内容的提问来源于stack exchange,提问作者Ansh
相关产品推荐
相关产品推荐

