You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native应用:后端存储AWS Cognito用户令牌与信息的实现问询

我来帮你拆解这个方案的具体实现步骤,分前端(React Native)和后端两部分来说,这样你能一步步落地:

整体流程对齐

先再明确下你要的代理模式:

  • 请求链路:React Native 前端 → 你的后端API → AWS Cognito
  • 响应链路:AWS Cognito → 你的后端API → React Native 前端
    核心是让后端作为中间层,全权代理Cognito的认证交互,同时把令牌和用户信息落地到自己的数据库里,方便后续业务调用。
后端实现步骤(以Node.js/Express为例,可适配其他后端栈)

1. 配置AWS SDK连接Cognito

首先安装AWS SDK,然后初始化Cognito服务客户端:

const AWS = require('aws-sdk');
// 生产环境建议用IAM角色(比如ECS/EKS执行角色、Lambda角色),不要硬编码密钥
AWS.config.update({
  region: '你的Cognito区域(如us-east-1)',
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
});

const cognitoISP = new AWS.CognitoIdentityServiceProvider();

2. 编写代理Cognito认证的API端点

以登录接口为例,前端把用户名密码传给后端,后端调用Cognito接口完成认证,拿到令牌和用户信息后存入自有的数据库:

app.post('/api/auth/login', async (req, res) => {
  const { username, password } = req.body;
  const cognitoParams = {
    AuthFlow: 'USER_PASSWORD_AUTH',
    ClientId: '你的Cognito App Client ID',
    AuthParameters: {
      USERNAME: username,
      PASSWORD: password
    }
  };

  try {
    // 调用Cognito完成登录
    const authResult = await cognitoISP.initiateAuth(cognitoParams).promise();
    const { IdToken, AccessToken, RefreshToken, ExpiresIn } = authResult.AuthenticationResult;

    // 获取用户详细属性
    const userDetails = await cognitoISP.getUser({ AccessToken }).promise();
    
    // 把令牌和用户信息存入你的数据库(示例用Sequelize ORM,可换成你用的数据库工具)
    await UserModel.upsert({
      username: userDetails.Username,
      id_token: IdToken, // 建议加密存储
      access_token: AccessToken, // 建议加密存储
      refresh_token: RefreshToken, // 建议加密存储
      user_attributes: userDetails.UserAttributes,
      token_expires_at: new Date(Date.now() + ExpiresIn * 1000)
    });

    // 返回给前端必要信息(比如只返回IdToken和用户属性,避免暴露过多敏感内容)
    res.json({
      success: true,
      idToken: IdToken,
      user: userDetails.UserAttributes.reduce((acc, attr) => {
        acc[attr.Name] = attr.Value;
        return acc;
      }, {})
    });
  } catch (error) {
    // 把Cognito的错误转化为友好提示返回给前端
    res.status(401).json({
      success: false,
      message: error.message.includes('UserNotFoundException') ? '用户不存在' : '用户名或密码错误'
    });
  }
});

3. 实现令牌刷新逻辑

当前端的Access Token过期时,调用后端的刷新接口,后端用Refresh Token向Cognito换取新令牌,更新数据库后返回给前端:

app.post('/api/auth/refresh', async (req, res) => {
  const { refreshToken } = req.body;
  const cognitoParams = {
    AuthFlow: 'REFRESH_TOKEN_AUTH',
    ClientId: '你的Cognito App Client ID',
    AuthParameters: { REFRESH_TOKEN: refreshToken }
  };

  try {
    const authResult = await cognitoISP.initiateAuth(cognitoParams).promise();
    const newIdToken = authResult.AuthenticationResult.IdToken;
    const newAccessToken = authResult.AuthenticationResult.AccessToken;

    // 更新数据库中的令牌信息
    await UserModel.update(
      {
        id_token: newIdToken,
        access_token: newAccessToken,
        token_expires_at: new Date(Date.now() + authResult.AuthenticationResult.ExpiresIn * 1000)
      },
      { where: { refresh_token: refreshToken } }
    );

    res.json({ success: true, idToken: newIdToken, accessToken: newAccessToken });
  } catch (error) {
    res.status(401).json({ success: false, message: '刷新令牌无效,请重新登录' });
  }
});
React Native前端实现步骤

1. 调用后端认证接口,存储令牌

不要直接调用Cognito SDK,所有认证请求都走自己的后端:

import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';

// 登录函数
export const login = async (username, password) => {
  try {
    const response = await axios.post('/api/auth/login', { username, password });
    // 把令牌和用户信息存在本地(建议用MMKV替代AsyncStorage,性能更好)
    await AsyncStorage.setItem('idToken', response.data.idToken);
    await AsyncStorage.setItem('userInfo', JSON.stringify(response.data.user));
    return response.data;
  } catch (error) {
    throw new Error(error.response.data.message);
  }
};

2. 用令牌请求后端业务接口

后续请求用户相关数据时,带上Id Token,后端会验证令牌有效性:

// 获取用户个人信息
export const getUserProfile = async () => {
  const idToken = await AsyncStorage.getItem('idToken');
  try {
    const response = await axios.get('/api/user/profile', {
      headers: { Authorization: `Bearer ${idToken}` }
    });
    return response.data;
  } catch (error) {
    // 处理令牌过期,自动刷新后重试
    if (error.response.status === 401) {
      const refreshToken = await AsyncStorage.getItem('refreshToken');
      const refreshRes = await axios.post('/api/auth/refresh', { refreshToken });
      await AsyncStorage.setItem('idToken', refreshRes.data.idToken);
      // 重新请求接口
      return getUserProfile();
    }
    throw error;
  }
};

3. 注销逻辑

前端调用后端注销接口,后端通知Cognito登出并清理数据库中的令牌:

// 后端注销接口
app.post('/api/auth/logout', async (req, res) => {
  const { accessToken } = req.body;
  try {
    // 通知Cognito全局登出
    await cognitoISP.globalSignOut({ AccessToken: accessToken }).promise();
    // 清理数据库中的令牌
    await UserModel.update(
      { id_token: null, access_token: null, refresh_token: null },
      { where: { access_token: accessToken } }
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ success: false, message: '注销失败' });
  }
});

// 前端注销函数
export const logout = async () => {
  const accessToken = await AsyncStorage.getItem('accessToken');
  await axios.post('/api/auth/logout', { accessToken });
  // 清理本地存储
  await AsyncStorage.multiRemove(['idToken', 'accessToken', 'refreshToken', 'userInfo']);
};
关键注意事项
  • 安全优先:
    • 后端与Cognito、前端与后端的通信必须用HTTPS;
    • 数据库中存储的令牌要加密,不要明文存储;
    • 后端要验证令牌的有效性(可以调用Cognito的getUser接口,或者直接验证JWT签名);
  • 性能优化:
    • 可以缓存Cognito返回的用户信息,减少重复调用Cognito API的次数;
    • 合理设置令牌过期时间(Cognito默认Access Token有效期1小时,Refresh Token30天);
  • 错误处理:
    • 针对Cognito的不同错误码(如UserNotFoundException、NotAuthorizedException)返回友好提示;
    • 前端要处理令牌过期、网络异常等场景,给用户清晰的操作指引。

内容的提问来源于stack exchange,提问作者sejn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:11:00