使用 Amazon Cognito 进行 Expo 身份验证无法在 Web 上运行

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

我已经按照 Expo 的指南设置了一个基本登录页面,该页面从我已经设置的 AWS Cognito 用户池中登录用户。这个基本登录页面似乎适用于我的 iPhone 上的 Expo Go 登录和注销功能,但在我的桌面上的浏览器上无法正常工作。我已将问题归结为“useAuthRequest”函数在从 AWS Cognito 打开托管登录页面后立即返回“dismiss”类型的响应。即使用户输入正确的凭据并登录,他们也只会看到一个新的弹出窗口,打开 expo 应用程序的主页。

这是网络上的(行为不当)登录流程:

Phase 1: 首先,单击蓝色登录按钮后,用户会看到 AWS Cognito 托管的 UI。

Phase 2: 输入正确的凭据后,弹出页面将继续向我们显示主页的副本。这不应该发生。通常,一旦用户输入凭证,托管的 UI 弹出窗口就会关闭,并且我们应该有一个“成功”的 AuthSession 响应,我们可以在其中将来自 AWS 的授权代码交换为 authToken,所有这些都在 useEffect 中触发。正如第 2 阶段的图像所示,我们do从 AWS Cognito 获取带有“code”和“state”参数的重定向,但交换并未发生。这是因为从用户打开 AWS 托管 UI 的那一刻起,“useAuthRequest”中的“response”输出就设置为 response.type = 'dismiss'。通常,响应类型应该是“成功”,我们可以从所述响应中获取代码并进行代币交换(这在 Expo Go 上运行良好,但在网络上则不行)。

我非常有信心这不是需要在 AWS Cognito 端修复的问题,因为我们从 Cognito 获得了正确的授权代码 - 我们只是不触发令牌交换,因为 useAuthRequest 响应被设置为“关闭”。

我想了解为什么使用“useAuthRequest”登录在网络上失败,但仍在 Expo Go 上工作。此外,该项目不使用任何 AWS Amplify。此外,虽然我不确定这对身份验证行为有何影响,但该项目使用了 Expo Router。

我将在下面提供我的代码:它实际上是 Expo 指南的一对一复制品,减去注销功能,并用 Typescript 编写:

import {
  AccessTokenRequestConfig,
  ResponseType,
  TokenResponse,
  exchangeCodeAsync,
  makeRedirectUri,
  revokeAsync,
  useAuthRequest,
} from "expo-auth-session";
import React from "react";
import { StyleSheet, Button, Alert } from "react-native";

const clientId = process.env.EXPO_PUBLIC_COGNITO_CLIENT_ID!;
const userPoolUrl = process.env.EXPO_PUBLIC_COGNITO_USER_POOL!;
const redirectUri = makeRedirectUri();

export default function App() {
  const [authTokens, setAuthTokens] = React.useState<TokenResponse | null>(
    null
  );
  const discoveryDocument = React.useMemo(
    () => ({
      authorizationEndpoint: userPoolUrl + "/oauth2/authorize",
      tokenEndpoint: userPoolUrl + "/oauth2/token",
      revocationEndpoint: userPoolUrl + "/oauth2/revoke",
    }),
    []
  );

  const [request, response, promptAsync] = useAuthRequest(
    {
      clientId,
      responseType: ResponseType.Code,
      redirectUri,
      usePKCE: true,
    },
    discoveryDocument
  );

  React.useEffect(() => {
    const exchangeFn = async (exchangeTokenReq: AccessTokenRequestConfig) => {
      try {
        const exchangeTokenResponse = await exchangeCodeAsync(
          exchangeTokenReq,
          discoveryDocument
        );
        setAuthTokens(exchangeTokenResponse);
      } catch (error) {
        console.error(error);
      }
    };
    if (response) {
      console.log("response type: " + response.type); // Web: response.type is always 'dismiss'
      if (response.type === "error") {
        Alert.alert(
          "Authentication error",
          response.params.error_description || "something went wrong"
        );
        return;
      }
      if (response.type === "success" && request?.codeVerifier) {
        exchangeFn({
          clientId,
          code: response.params.code,
          redirectUri,
          extraParams: {
            code_verifier: request.codeVerifier,
          },
        });
      }
    }
  }, [discoveryDocument, request, response]);

  console.log("authTokens: " + JSON.stringify(authTokens));

  return authTokens ? (
    <Button title="Logout" />
  ) : (
    <Button disabled={!request} title="Login" onPress={() => promptAsync()} />
  );
}
expo amazon-cognito expo-auth-session
1个回答
0
投票

我也面临着类似的确保处理与认知连接的通信,它可以在expo go上工作,但在构建之后不起作用,这使得调试变得困难。

© www.soinside.com 2019 - 2024. All rights reserved.