如何提取 Cognito 生成的 JWT,并将其存储为 HTTPonly cookie 并与后续 API 请求一起使用(React)

Posted

技术标签:

【中文标题】如何提取 Cognito 生成的 JWT,并将其存储为 HTTPonly cookie 并与后续 API 请求一起使用(React)【英文标题】:How to extract a JWT generated by Cognito, and store as HTTPonly cookie and use with subsequent API requests (React) 【发布时间】:2022-01-17 04:57:45 【问题描述】:

我正在使用 cognito 进行用户身份验证。成功验证(用户电子邮件和密码)后,Cognito 会生成 id、访问和刷新令牌,我可以在我的 console.log 回复中看到这些令牌。

我的问题是,如何提取这些令牌并将它们存储为“全局范围变量”,以便在我的应用程序中的各种 React 组件中使用 API 调用(可能作为 HTTPOnly Cookie)?

(我愿意接受对我当前方法的任何建议“修复”,或者同样,对更有效的管理方法的建议): 我试过了..

将 JWT 令牌定义为 JWTutils.js 组件中的变量并将其导入到 login.js 中,我在其中分配来自 cognito 的响应的值。我的想法是,这将允许我在整个应用程序中使用令牌值。然而,这只是中断成功登录。因此,即使我输入了正确的详细信息,我的console.log 实际上也会显示onSuccess,但在我的浏览器呈现认知模式后立即显示Failure : Username or password are incorrect

从客户端处理和管理 JWT 的最佳方式是什么?

我的代码附在下面: 登录.js

import React from 'react'
import poolData from '../Userpool';
import  CognitoUser, AuthenticationDetails  from 'amazon-cognito-identity-js';
import  useState, useEffect  from 'react';
import  useHistory  from 'react-router-dom';
import JWT from '../utils/JWTutils';

const Login = () => 

    const[email,setEmail]=useState("");
    const[password,setPassword]=useState("");
    
    let isAuth = false;

    let history = useHistory();
    
    const onSubmit =(event)=>
        event.preventDefault();

        const user= new CognitoUser(
            Username: email,
            Pool: poolData,
         );

        const authDetails = new AuthenticationDetails(
            Username: email,
            Password : password,
         );

        console.log("authDetails", authDetails)
        console.log("user", user )

        user.authenticateUser(authDetails,
            onSuccess: (data)=>
                console.log("On Success: " , data)
                console.log("JWT", data.idToken.jwtToken)
                JWT=data.idToken.jwtToken
                isAuth =true;
                JWT = (data.idToken.jwtToken) // <----this is where the modal 'pops up' and the //application fails
                    history.push("/secure");
              ,
            onFailure:(err)=>
                alert("Failure : Username or password are incorrect")
                history.push("/")
             ,
            newPasswordRequired: (data)=>
                console.log("New Password Required: ", data)
            
          )
    

    return (
        <div>
            <br />
            <hr />
            <h2>Login</h2>
            <form onSubmit=onSubmit >
            <label htmlFor="email">Email</label>
            <br />
            <input type="email" value=email 
            onChange=(event)=>setEmail(event.target.value) />
            <br />
            <label htmlFor="password">Password</label>
            <br />
            <input type="password" value=password
            onChange=(event=>setPassword(event.target.value)) />
            <br />
             <button>Login</button>
            </form>
        </div>
    )
 


export default Login;

JWTutils.js

  const JWT =""
export default JWT;

【问题讨论】:

【参考方案1】:

按照您的方式,JWTconst,不能重新分配。这可能就是您目前的方法失败的原因。

您可以轻松地将 JWTUtils 转换为允许获取/设置令牌的简单“存储”:

// JWTUtils
let token;

export default 
  setToken: t => token = t,
  getToken: () => token,

然后在您的 success 处理程序中使用它:

onSuccess: (data) => 
  JWT.setToken(data.idToken.jwtToken)
  // ...whatever else you need to do...

任何其他需要它的东西都可以通过 getToken 访问它:

import JWT from '../JWTUtils';

const token = JWT.getToken();

if (token) 
  // do whatever you need to do

您可以扩展 JWTUtil 以将其存储在本地存储中,以便在页面重新加载等过程中保持不变。


注意:您可以const JWT = "" 更改为let JWT = "",但这将允许任何地方的任何代码更改其值,这是一个坏主意™,可能会导致难以解决的问题诊断。

通过定义良好的 API(getToken、setToken)发送它并保持变量本身的私有性,您可以强制执行有关如何访问它的规则、在它更改时设置调试断点、在不影响现有使用的情况下替换实际实现等.

【讨论】:

以上是关于如何提取 Cognito 生成的 JWT,并将其存储为 HTTPonly cookie 并与后续 API 请求一起使用(React)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Go 中验证来自 AWS Cognito 的 JWT 令牌?

在 Spring Security 中解码 AWS Cognito 生成的 JWT 时出错

如何验证从 Cognito 获得的 jwt 令牌

从 Cognito 收到 JWT Token 后如何存储?通过 Cognito 托管 UI 登录

AWS Cognito:将自定义声明/属性添加到 JWT 访问令牌

如何修改 AWS Cognito JWT Tokens,我们正在使用 NodeJS 技术问题