REACT 应用程序调用安全的 Azure WEBAPI 服务 - 没有用户

Posted

技术标签:

【中文标题】REACT 应用程序调用安全的 Azure WEBAPI 服务 - 没有用户【英文标题】:REACT application to call secure Azure WEBAPI Service - NO USERS 【发布时间】:2021-05-17 04:21:18 【问题描述】:

我创建了一个简单的 REACT 应用程序,它只能在连接到我们网络上的大屏幕的本地 PC 上运行。仅供内部使用!它就像一个广告牌或仪表板。用户交互为零。屏幕不是触摸屏,也没有连接键盘和鼠标。因此没有用户可以登录。

REACT 应用程序已构建,然后部署到 PC 上的文件夹中。全部自动化。初始部署包括所有当前数据。然后在 Windows 启动时执行类似这样的命令: “python -m http.server 3000”(只是示例...)

应用程序具有随应用程序一起部署的初始数据,但是,我希望它也能够调用安全的 Azure WebAPI 服务以每隔几分钟获取更新的统计信息。非常小的数据。主要是整数值。我只是想提供一些实时更新。

我的 REACT 应用程序可以正常工作(如果 WEBAPI 不安全)或个别调用允许匿名。但是,我们的业务规则要求所有端点都是安全的。

此应用在本地运行,但 API 是 Azure 应用服务。

我已将 Azure AD 中的 REACT 应用程序设置为注册应用程序,并将其配置为有权调用 WEBAPI 服务。

我有许多控制台应用程序,它们的设置和工作方式与这个 REACT 应用程序基本相同。对于 C# 守护程序应用程序,有一个 MSAL 包可以轻松完成。

我正在尝试学习 REACT,而不是将其构建为另一个 WPF 或 UWP 应用程序,我想尝试使用 REACT。

所以,我知道我需要一个访问令牌。我正在考虑客户端 ID 和 Secret,就像我在用 C# 编写的 C# 守护程序客户端中所做的那样。

我找不到任何在没有用户登录的情况下执行此操作的 REACT 或 Angular 示例。请记住,PC 没有输入设备。仅显示。同样,我的应用没有用户。它调用安全 API 来获取数据。就是这样。

感谢您的帮助。

使用 Joy Wang 的 cmets 和文档中的这个页面: Service-to-Service Access Token Request

这是我的新代码:

const adalConfig = 
  tenant: '...',
  clientId: '...',
  clientSecret: '...',
  authority: 'https://login.microsoftonline.com/tenant/oauth2/token',
  endpoints: 
    apiResourceId: 'api://bbbbbb-...',
  ,
;

function getAccessToken() 
  var requestParams = 
    grant_type: 'client_credentials',
    client_id: adalConfig.clientId,
    client_secret: adalConfig.clientSecret,
    resource: adalConfig.endpoints.apiResourceId
  ;

  // Make a request to the token issuing endpoint.
  fetch(adalConfig.authority,
    
      method: 'POST',
      headers:  'Content-Type': 'application/json' ,
      body: JSON.stringify( requestParams )
    ).then(response => 
      if (response.status >= 200 && response.status < 300) 
        console.log(response);
        console.log(response.json());
       else 
        console.log('Somthing happened wrong');
        console.log(response);
      
    ).catch(err => err);

当我调用上面的函数时,我得到以下响应:

响应 type: "cors", url: "https://login.microsoftonline.com/.../oauth2/token", 重定向: false, status: 400, ok: false, … 身体: (...) 身体使用:假 标头:标头 好的:假的 重定向:假 状态:400 statusText:“错误请求” 类型:“cors” 网址:“https://login.microsoftonline.com/.../oauth2/token” 原型:响应

也许还有另一种方法可以启动 REACT 应用程序,以便不检查 CORS?有什么想法吗?

再次感谢。

【问题讨论】:

如果可以参考这个answer,我也觉得不可能。 @Tiny-wa 我有 C# 守护程序客户端一直在执行此操作。我很确定 javascript 客户端也可以。 API 文档提到使用客户端密码,但没有示例。 一个守护程序客户端它应该没有 UI,我认为您应该考虑:1.您是否使用正确的方法和技术来解决问题?:2.您应该阅读更多有关 OAuth 的信息以及它具有的不同流量。你可以用 javascript 编写你的守护进程,但我没有看到将 UI 框架作为 ReactJS 的意义。 @DavidNoreña 感谢您提供帮助。也许您不明白“守护程序客户端”这个术语是如何使用的。我想做的不是唯一的。这是微软的解释。 docs.microsoft.com/en-us/azure/active-directory/develop/… 我确信我可以更好地解释它,但归根结底,我有一个调用 API 的网络应用程序。 Web 应用程序没有用户登录,但我需要访问和请求安全数据。我需要一个令牌。 是的,但请记住与 Identity 相关的 microsoft 文档当他们说:Daemon Web App 时,他们指的是 ASP.NET CORE FULL 应用程序,当他们使用术语单页应用程序时,即反应或任何其他 UI 框架都会发挥作用。对于守护进程通信,您必须使用客户端凭据流保护机密,这也是我说我不明白为什么使用 ReactJS 的原因。 【参考方案1】:

所以,目前没有一种安全的方式来做我想做的事。基本问题是您不能在浏览器中使用来自 JavaScript 的客户端凭据授予类型。

但是,我认为我有一个很好的解决方法可以帮助其他人。我确信它不适用于大多数应用程序。而且我相信 OAUTH 正在研究解决方案,因此在不久的将来可能不需要。如果添加了更好的解决方案,我很乐意将其标记为正确答案。感谢您的帮助。

我的应用基本上是一个用户输入为零的自动化仪表板/广告牌。它提取安全数据并显示它。 REACT 应用程序仅在没有输入的墙壁上的本地 PC 上。开启 PC 时运行脚本。

脚本使用 python 之类的 http 服务器启动构建的 REACT 应用程序。 例如:“python -m http.server 8000”

该脚本随后以信息亭模式打开浏览器,因此您在屏幕上看到的唯一内容就是应用程序。

到目前为止,这和我之前的完全一样。

解决方法: 我创建了一个名为 GetToken 的命令行实用程序。在脚本启动 REACT 应用程序之前,它会像这样调用此实用程序:“gettoken --client Dashboard --file token.json” 此实用程序调用客户端凭据授予类型以获取令牌。 然后它将该令牌与其他构建的 REACT 文件一起保存到本地 json 文件中。例如:\public\data\token.json

在我的 REACT 应用程序中,它只是加载令牌并使用它。

const t = await fetch('./data/token.json').then(r => r.json());
this.setState( token: t.token );

然后我将其添加到我的 api 调用中,如下所示:

const fetchOptions = 
  method: 'GET',
  headers: 
    "Authorization": `Bearer $this.state.token`,
    "Content-Type": "application/json"
  
;
const newSlides = await fetch(this.state.baseUrl + '/api/Dashboard/GetSlides', fetchOptions).then(response => response.json());

重要提示:这仅适用于您还能够更新 API 的情况。如果你不能,那么你仍然会得到 CORS 错误。您必须允许来自用于启动应用程序的 localhost 和端口的调用。您应该选择 3000、4200 或 8000 以外的值。

我在我的 API startup.cs 中添加了以下内容:

public void ConfigureServices(IServiceCollection services) 
  ...

  var origins = Configuration.GetSection("AppSettings:AllowedOrigins").Value.Split(",");
  services.AddCors(o => o.AddPolicy(specificOriginsPolicy, builder => 
    builder.WithOrigins(origins)
      .AllowAnyMethod()
      .AllowAnyHeader()
      .AllowCredentials()
      .SetIsOriginAllowed((host) => true);
  ));

  ...


public void Configure(IApplicationBuilder app) 
  ...
  app.UseCors(specificOriginsPolicy);
  ...

我仍在完善此解决方案,但到目前为止效果很好。我可以将该实用程序变成一个后台服务,它会定期更新令牌。或者我可以将实用程序转换为 Shell,然后使用它而不是脚本。不管怎样,你明白了。

课程: 我知道我可以将其作为 UWP 或 WPF 应用程序来完成并避免所有这些问题,但主要目标是学习 REACT。 我学到了很多。我会再做一次。令人震惊的是,我的 REACT 应用程序现在已经完成了这么少的代码。我相信 REACT 可以用于许多类似的场景。

【讨论】:

【参考方案2】:

您可以参考这个sample,它使用客户端凭据流(即您想要的客户端ID和秘密)来获取访问令牌,只需将resource更改为您想要获取令牌的那个,示例获取 Microsoft Graph 的令牌。

auth.getAccessToken = function () 
  var deferred = Q.defer();

  // These are the parameters necessary for the OAuth 2.0 Client Credentials Grant Flow.
  // For more information, see Service to Service Calls Using Client Credentials (https://msdn.microsoft.com/library/azure/dn645543.aspx).
  var requestParams = 
    grant_type: 'client_credentials',
    client_id: config.clientId,
    client_secret: config.clientSecret,
    resource: 'https://graph.microsoft.com'
  ;

  // Make a request to the token issuing endpoint.
  request.post( url: config.tokenEndpoint, form: requestParams , function (err, response, body) 
    var parsedBody = JSON.parse(body);
    console.log(parsedBody);
    if (err) 
      deferred.reject(err);
     else if (parsedBody.error) 
      deferred.reject(parsedBody.error_description);
     else 
      // If successful, return the access token.
      deferred.resolve(parsedBody.access_token);
    
  );

  return deferred.promise;
;

【讨论】:

谢谢。这有帮助。我相信我更接近解决方案。我会更新我的问题。 Joy,如果您有更多建议,我在上面添加了更多详细信息。谢谢。 @BobbyOrtiz 不是反应专家,这有帮助吗? ***.com/questions/43462367/…

以上是关于REACT 应用程序调用安全的 Azure WEBAPI 服务 - 没有用户的主要内容,如果未能解决你的问题,请参考以下文章

在没有用户登录屏幕的情况下从Javascript调用安全的REST API

如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序

Azure api 请求被中止:无法创建 SSL/TLS 安全通道。 http客户端在调用一些web api时

从 React 调用受 Azure AD 保护的 API

在 azure 上部署 React Web 应用程序的权限被拒绝

访问我的 React Web 应用程序的 Azure SQL 数据库