如何在JS中用AWS Amplify实现OAuth获取Cognito访问令牌?
解决方案步骤
1. 配置现有Cognito用户池的OAuth设置
登录AWS控制台,找到你的Cognito用户池:
- 进入应用集成标签,找到已有React应用对应的应用客户端
- 点击编辑,在OAuth 2.0部分:
- 添加新应用的回调URL(比如本地开发用
http://localhost:3000/callback,生产环境用https://your-new-app.com/callback) - 添加新应用的退出URL(比如
http://localhost:3000/signout或https://your-new-app.com/signout) - 勾选必要的授权范围,至少包含
openid,按需添加email、profile等 - 确保勾选授权码授权(Authorization Code Grant),这是最安全的OAuth流程
- 添加新应用的回调URL(比如本地开发用
2. 为新应用创建Cognito应用客户端
在同一用户池的应用集成标签下:
- 点击创建应用客户端,输入客户端名称(比如
new-oauth-client) - SPA应用取消勾选生成客户端密钥,服务器端应用可保留
- 重复步骤1的OAuth配置(回调URL、退出URL、授权范围、授权类型)
- 创建后记录客户端ID,后续配置会用到
3. 在新应用中实现OAuth认证流程
提供两种主流实现方式:
方式一:使用AWS Amplify(与现有技术栈一致,推荐)
- 安装依赖:
npm install aws-amplify @aws-amplify/ui-react
- 创建
aws-exports.js配置文件:
const awsmobile = { "aws_project_region": "你的Cognito区域(如us-east-1)", "aws_cognito_region": "你的Cognito区域", "aws_user_pools_id": "你的用户池ID", "aws_user_pools_web_client_id": "新应用的客户端ID", "oauth": { "domain": "你的Cognito域名(如xxx.auth.us-east-1.amazoncognito.com)", "scope": ["openid", "email", "profile"], "redirectSignIn": "http://localhost:3000/callback", "redirectSignOut": "http://localhost:3000/signout", "responseType": "code" } }; export default awsmobile;
- 在入口文件(如
index.js)初始化Amplify:
import { Amplify } from "aws-amplify"; import awsmobile from "./aws-exports"; Amplify.configure(awsmobile);
- 实现登录组件并获取访问令牌:
import { Authenticator, useAuthenticator } from "@aws-amplify/ui-react"; import "@aws-amplify/ui-react/styles.css"; const NewAppAuth = () => { const { user, signOut } = useAuthenticator((context) => [context.user]); const getAccessToken = async () => { const session = await user?.getSession(); if (session) { const accessToken = session.getAccessToken().getJwtToken(); console.log("访问令牌:", accessToken); // 可将令牌用于后续API请求等场景 } }; return ( <Authenticator> <div className="App"> <p>Hey {user?.username}, 已通过OAuth登录!</p> <button onClick={getAccessToken}>获取访问令牌</button> <button onClick={signOut}>退出登录</button> </div> </Authenticator> ); }; export default NewAppAuth;
方式二:手动实现OAuth授权码流程(无需Amplify场景)
- 构造授权URL,引导用户跳转至Cognito认证页:
const cognitoDomain = "xxx.auth.us-east-1.amazoncognito.com"; const clientId = "你的新应用客户端ID"; const redirectUri = "http://localhost:3000/callback"; const scope = "openid+email+profile"; const authUrl = `${cognitoDomain}/oauth2/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`; const handleLogin = () => { window.location.href = authUrl; };
- 在回调页面(
/callback)处理授权码,交换访问令牌:
import { useEffect } from "react"; const CallbackPage = () => { useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get("code"); if (code) { fetch(`${cognitoDomain}/oauth2/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: clientId, code: code, redirect_uri: redirectUri }) }) .then(res => res.json()) .then(data => { const accessToken = data.access_token; console.log("访问令牌:", accessToken); localStorage.setItem("access_token", accessToken); window.location.href = "/"; }) .catch(err => console.error("令牌交换失败:", err)); } }, []); return <div>正在处理登录...</div>; }; export default CallbackPage;
4. 验证访问令牌有效性
可通过Cognito的用户信息端点验证令牌:
const validateToken = async (token) => { const response = await fetch(`${cognitoDomain}/oauth2/userInfo`, { headers: { "Authorization": `Bearer ${token}` } }); if (response.ok) { const userInfo = await response.json(); console.log("令牌有效,用户信息:", userInfo); return true; } return false; };
内容的提问来源于stack exchange,提问作者Apurup Kumar
相关产品推荐
相关产品推荐

