在 aws-amplify ui-react 中获取 aws cognito 令牌

问题描述 投票:0回答:3

我目前在 Next.js 前端和 NestJS 后端应用程序中工作,并使用 @aws-amplify/ui-react 设置登录组件:

就像文档中一样 https://docs.amplify.aws/lib/auth/getting-started/q/platform/js/#option-1-use-pre-built-ui-components

import { Amplify } from 'aws-amplify';
import { withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsExports from './aws-exports';
Amplify.configure(awsExports);

function App({ signOut, user }) {
  return (
    <>
      <h1>Hello {user.username}</h1>
      <button onClick={signOut}>Sign out</button>
    </>
  );
}

export default withAuthenticator(App);

问题是我如何获取 jwt 令牌并将其传递给 axios 标头?

    const response: any = await axios({
      method: method as Method,
      url: `http://localhost:3001/dev/${query}`,
      headers: {
        Authorization: `Bearer ${jwtToken}`,
        'Content-Type': 'application/json',
      },
      data,
    })

我尝试从本地存储获取令牌,但由于池 ID 和用户的原因,密钥发生了变化。

amazon-web-services next.js nestjs amazon-cognito
3个回答
0
投票

不知道 Next.js 的确切语法,但这就是我在 Angular (TypeScript) 中所做的。

ProfileComponent.ts

import { Component } from "@angular/core";
import { Auth } from "aws-amplify";
import { UserService } from "src/app/services/user.service";

@Component({
  selector: "app-profile",
  templateUrl: "./profile.component.html",
  styleUrls: ["./profile.component.sass"],
})
export class ProfileComponent {

  constructor(private userService: UserService) {

    Auth.currentSession().then((response) => {

      var idToken = response.getIdToken().getJwtToken();

      this.userService.getUserInfo(idToken).subscribe((response) => {
        console.log(response);
      });

    });
  }
}

用户服务.ts

export class UserService {

  constructor(private http: HttpClient) {}

  public getUserInfo(accessToken: string): Observable<Weather[]> {

    var headers_object = new HttpHeaders().set("Authorization", "Bearer" + accessToken);

    return this.http.get<Weather[]>(
      "https://xxxxx.execute-api.ap-south-1.amazonaws.com/prod/User",
      {
        headers: headers_object,
      }
    );
  }
}

0
投票

查看示例 PAM 应用程序。它使用 React 应用程序并使用 Cognito 对用户进行身份验证。这个应用程序不使用放大。它使用 React、Cloudscape Design System 和 AWS SDK 并向 API 网关端点发出请求:

正如您在此图中看到的,React 应用程序允许用户通过 Cognito 调用登录。此应用程序使用从 Cognito 返回的令牌。一旦您理解了这一点 - 您就可以将其应用到您的项目中。

按照本示例中的说明操作后,您将获得包含登录屏幕的完整应用程序:

登录后 - 您会看到该应用程序:

看这个例子中的代码:

反应代码在这里:

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/resources/clients/react/elros-pam

后端示例在这里:

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/usecases/pam_source_files


0
投票

这个问题可以通过创建全局上下文来解决,该上下文将当前令牌保持在其状态。

最终结果是像这样访问令牌:

示例.js

import { AuthenticatedSessionContext } from './AuthenticatedSessionContext';

export const Example = () => {
  const { session } = useContext(AuthenticatedSessionContext);
  const jwt = session.tokens.idToken.toString();

  // use the jwt in axios, etc.
};

这就是实现。

注意,引用的

AuthenticatedStatusContext
组件可在 https://stackoverflow.com/a/78375940

获取

AuthenticatedSession.js

import { createContext, useContext, useEffect, useState } from 'react';
import { fetchAuthSession } from 'aws-amplify/auth';  // https://docs.amplify.aws/javascript/build-a-backend/auth/manage-user-session/
import moment from 'moment';

import { AuthenticatedStatusContext } from './AuthenticatedStatusContext';


const getRefreshMilliseconds = (session) => {
  // refresh 1 minute before actual expiry
  const expiration = moment(session.credentials.expiration).subtract(1, 'minutes');
  return Math.max(0, expiration - moment());
};

const defaultForceRefresh = false;
const defaultSession = undefined;
const defaultRefreshMilliseconds = undefined;

export const AuthenticatedSessionContext = createContext();

export const AuthenticatedSession = (props) => {
  const { children } = props;

  const { isAuthenticated } = useContext(AuthenticatedStatusContext);

  const [forceRefresh, setForceRefresh] = useState(defaultForceRefresh);
  const [session, setSession] = useState(defaultSession);
  const [refreshMilliseconds, setRefreshMilliseconds] = useState(defaultRefreshMilliseconds);

  const refreshSession = () => (
    fetchAuthSession({forceRefresh})
    .then((_session) => {
      setForceRefresh(true); // force refresh just before actual expiry
      setSession(_session);
      setRefreshMilliseconds(getRefreshMilliseconds(_session));
    }).catch(console.error)
  );

  useEffect(() => {
    if (isAuthenticated && !session) {
      // initial session grab
      refreshSession();
    } else if (!isAuthenticated && session) {
      // clear session when not authenticated
      setForceRefresh(defaultForceRefresh);
      setSession(defaultSession);
      setRefreshMilliseconds(defaultRefreshMilliseconds);
    }
  }, [isAuthenticated, session]);

  useEffect(() => {
    // schedule next refresh
    if (refreshMilliseconds !== defaultRefreshMilliseconds) {
      const refreshTimeout = setTimeout(refreshSession, refreshMilliseconds);
      return () => clearTimeout(refreshTimeout);
    }
  }, [refreshMilliseconds]);

  return (
    <AuthenticatedSessionContext.Provider value={{session}}>
      {children}
    </AuthenticatedSessionContext.Provider>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.