SolidJS SPA中调用Auth.federatedSignIn后无法捕获auth事件的问题咨询
解决方案
1. 捕获signIn/signUp事件的代码组织方式
第三方登录跳转回应用后,Amplify需要手动处理认证响应才能触发Hub的auth事件,结合SolidJS的生命周期,按以下步骤调整:
步骤1:全局注册Hub监听
在应用根组件的onMount中注册Hub监听,确保监听在Amplify配置完成后立即生效,同时在组件卸载时移除监听:
import { onMount } from 'solid-js'; import { Amplify } from '@aws-amplify/core'; import { Auth, Hub } from '@aws-amplify/auth'; import awsconfig from './aws-exports'; // 初始化Amplify配置 Amplify.configure(awsconfig); const App = () => { onMount(() => { // 注册auth事件监听 const authUnsubscribe = Hub.listen('auth', ({ payload }) => { const { event, data } = payload; switch (event) { case 'signIn': console.log('登录成功:', data); // 执行登录后的业务逻辑 break; case 'signUp': console.log('注册成功:', data); // 执行注册后的业务逻辑 break; case 'signOut': console.log('登出成功'); break; default: break; } }); // 组件卸载时取消监听 return () => authUnsubscribe(); }); // 路由、页面内容等 return <div>你的应用内容</div>; }; export default App;
步骤2:在回调页面处理认证响应
在第三方登录返回的回调页面(/account/external)中,调用Auth.handleAuthResponse()处理授权码,完成会话初始化,此时Hub会触发signIn事件:
import { onMount } from 'solid-js'; import { Auth } from '@aws-amplify/auth'; const ExternalCallback = () => { onMount(async () => { try { // 处理第三方登录返回的URL参数 await Auth.handleAuthResponse(window.location.href); // 处理完成后跳转至目标页面(如用户中心) window.location.href = '/dashboard'; } catch (err) { console.error('认证响应处理失败:', err); // 处理错误逻辑,如跳转至登录页 window.location.href = '/login'; } }); return <div>正在处理登录,请稍候...</div>; }; export default ExternalCallback;
关键配置注意
确保aws-exports.js中的OAuth配置正确指向回调页面:
export default { // 其他Amplify配置 oauth: { domain: '你的Cognito域名.auth.区域.amazoncognito.com', scope: ['email', 'openid', 'profile'], redirectSignIn: 'https://你的域名/account/external', redirectSignOut: 'https://你的域名/', responseType: 'code', urlOpener: (url, redirectUrl) => window.open(url, '_blank') } };
注:原页面因跳转至第三方认证页会处于后台,无法捕获新标签页的认证事件,回调页处理完成后跳转的新页面会触发Hub的
signIn事件。
2. 关联登录发起数据与CognitoUser的实现方式
Amplify的Auth.federatedSignIn不支持直接传递自定义数据到Hub事件,但可以通过本地临时存储的方式实现关联:
步骤1:登录发起时存储自定义数据
在调用federatedSignIn前,将需要关联的数据存入sessionStorage(会话结束自动清除,比localStorage更安全):
import { Auth, CognitoHostedUIIdentityProvider } from '@aws-amplify/auth'; const SignUp = () => { const handleGoogleLogin = async () => { // 存储需要关联的已有用户ID等数据 sessionStorage.setItem('authAssocData', JSON.stringify({ existingUserId: '用户ID' })); await Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google }); }; return <button onClick={handleGoogleLogin}>绑定Google账号</button>; }; export default SignUp;
步骤2:在Hub事件中读取并关联数据
在Hub的signIn事件监听中,读取临时存储的数据,完成关联后删除:
Hub.listen('auth', ({ payload }) => { if (payload.event === 'signIn') { const assocDataStr = sessionStorage.getItem('authAssocData'); if (assocDataStr) { const assocData = JSON.parse(assocDataStr); // 关联Cognito用户与已有用户数据,比如调用后端API完成绑定 console.log('绑定用户:', payload.data.username, assocData.existingUserId); // 用完后清除临时数据 sessionStorage.removeItem('authAssocData'); } } });
注:避免在本地存储中存放敏感数据,若需更高安全性,可结合后端生成的临时令牌替代明文数据。
内容的提问来源于stack exchange,提问作者Kapelianovych
相关产品推荐
相关产品推荐

