使用 MSAL React 调用 API

Calling an API with MSAL React

我正在尝试使用 Azure AD 保护 API 并从 React SPA 调用它,但我 运行 遇到了 401 未授权错误。我不太确定我做错了什么。

里面appsettings.json

"AzureAD": {
    "Instance": "https://login.microsoft.com",
    "Domain": "<MyAdDomain>",
    "TenantId": "<MyTenantId>",
    "ClientId": "<MyApiAppId>",
    "Scope": "<MyApiScope>"
  }

然后 StartUp.cs

            var tenantId = $"{Configuration["AzureAD:TenantId"]}";
            var authority = $"{Configuration["AzureAD:Instance"]}/{tenantId}";

            var audience = new List<string>
            {
                $"{Configuration["AzureAD:ClientId"]}",
                $"{Configuration["AzureAD:Scope"]}"
            };

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.Authority = authority;
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidAudiences = audience,
                        ValidIssuers = new List<string>
                        {
                            $"https://sts.windows.net/{tenantId}",
                            $"https://sts.windows.net/{tenantId}/v2.0",
                        }
                    };
                });

同时,在我的 React 应用程序中,我使用具有以下配置的 MsalProvider 对其进行保护:

authConfig.ts

export const msalConfig: Configuration = {
  auth: {
    clientId: "<MyClientApiId>",
    authority:
      "https://login.microsoftonline.com/<MyTenantId>",
    redirectUri: "/",
  },
  cache: {
    cacheLocation: "sessionStorage",
    storeAuthStateInCookie: false,
  },
// other code

App.tsx

const msalInstance = new PublicClientApplication(msalConfig);

function App() {
  return (
    <MsalProvider instance={msalInstance}>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/dealer/:accountNumber" element={<DealerContainer />} />
        </Routes>
      </BrowserRouter>
    </MsalProvider>
  );

然后在里面 HomePage.tsx:

  const getCompanies = useCallback(async () => {
    if (isAuthenticated) {
      const silentRequest: SsoSilentRequest = {
        scopes: ["<MyApiScope>"],
        loginHint: instance.getActiveAccount()?.username,
      };

      const token = await instance.ssoSilent(silentRequest);
      const companies = await getCompaniesAsync(token);

      setCompaniesList(companies);
      setFullCompaniesList(companies);
    }
  }, [instance, isAuthenticated]);

关于我在这里做错了什么的任何见解?谢谢!

从 Tiny Wang 的评论中获得了一些见解,我最终浏览了一些其他文档并进行了一些 Postman 测试

里面 HomePage.tsx:

 const getCompanies = useCallback(async () => {
    if (isAuthenticated) {
      const account = instance.getAllAccounts()[0];

      const silentRequest = {
        scopes: ["api://<MyApiAppId>/access_user_data"],
        account: account,
      };

      const token: AuthenticationResult = await instance.acquireTokenSilent(
        silentRequest
      );
      const companies = await getCompaniesAsync(token.accessToken);
      // rest of the code here
  "AzureAd": {
    "Instance": "https://login.microsoft.com",
    "Domain": "<MyDomain>",
    "TenantId": "<MyTenantId>",
    "ClientId": "api://<MyApiAppId>",
    "Audience": "<MyFrontEndAppId>",
    "Scope": "api://<MyApiAppId>/access_user_data"
  },

出于某种原因,ClientId 正在请求 URI 而不仅仅是 ID。