如何提取由 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)

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

我的问题是,如何提取这些标记并将它们存储为 'global scope variable' 以便在我的各种 React 组件中使用 API 调用(可能作为 HTTPOnly Cookie)申请?

(我对 'fixes' 对我当前方法的任何建议持开放态度,或者同样地,对更有效的管理方法提出建议): 我试过的..

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

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

我的代码附在下面: Login.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;

按照您的说法,JWT 是一个 const,无法重新分配。这可能就是您当前的方法失败的原因。

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

// 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) 发送它并使变量本身保持私有,您可以强制执行关于如何访问它的规则,在它发生变化时设置调试断点,交换实际实现不影响现有使用等