REACT 应用程序调用安全的 Azure WEBAPI 服务 - 无用户
REACT application to call secure Azure WEBAPI Service - NO USERS
我创建了一个简单的 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 的评论和文档中的这一页:
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", redirected: false, status: 400, ok:错误的, …}
body: (...)
body已使用:错误
headers: Headers {}
好的:假的
重定向:错误
状态:400
statusText: "错误请求"
类型:“cors”
url: "https://login.microsoftonline.com/.../oauth2/token"
原型:响应
也许还有另一种方法可以启动 REACT 应用程序,从而不检查 CORS?有什么想法吗?
再次感谢。
你可以参考这个,它使用客户端凭证流(即你想要的客户端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;
};
所以,目前没有一种安全的方式来做我想做的事。基本问题是您无法在浏览器中使用来自 JavaScript 的客户端凭据授予类型。
但是,我认为我有一个很好的解决方法可以帮助其他人。我确信它不适用于大多数应用程序。而且我相信 OAUTH 正在研究解决方案,因此在不久的将来可能不需要。如果添加了更好的解决方案,我会很乐意将其标记为正确答案。感谢您的帮助。
我的应用程序基本上是一个自动化的 dashboard/billboard,用户输入为零。它提取安全数据并显示它。 REACT 应用程序仅在墙上的本地 PC 上没有输入。 PC 打开时运行脚本。
该脚本使用像 python 这样的 http 服务器启动构建的 REACT 应用程序。
例如:“python -m http.server 8000”
脚本随后会以 kiosk 模式打开浏览器,因此您在屏幕上看到的唯一内容就是应用程序。
到目前为止,这与我之前的完全一样。
解决方法:
我创建了一个名为 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 错误。您将必须允许来自用于启动应用程序的本地主机和端口的调用。您应该选择 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 可以用于许多类似的场景。
我创建了一个简单的 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 的评论和文档中的这一页: 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", redirected: false, status: 400, ok:错误的, …} body: (...) body已使用:错误 headers: Headers {} 好的:假的 重定向:错误 状态:400 statusText: "错误请求" 类型:“cors” url: "https://login.microsoftonline.com/.../oauth2/token" 原型:响应
也许还有另一种方法可以启动 REACT 应用程序,从而不检查 CORS?有什么想法吗?
再次感谢。
你可以参考这个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;
};
所以,目前没有一种安全的方式来做我想做的事。基本问题是您无法在浏览器中使用来自 JavaScript 的客户端凭据授予类型。
但是,我认为我有一个很好的解决方法可以帮助其他人。我确信它不适用于大多数应用程序。而且我相信 OAUTH 正在研究解决方案,因此在不久的将来可能不需要。如果添加了更好的解决方案,我会很乐意将其标记为正确答案。感谢您的帮助。
我的应用程序基本上是一个自动化的 dashboard/billboard,用户输入为零。它提取安全数据并显示它。 REACT 应用程序仅在墙上的本地 PC 上没有输入。 PC 打开时运行脚本。
该脚本使用像 python 这样的 http 服务器启动构建的 REACT 应用程序。 例如:“python -m http.server 8000”
脚本随后会以 kiosk 模式打开浏览器,因此您在屏幕上看到的唯一内容就是应用程序。
到目前为止,这与我之前的完全一样。
解决方法: 我创建了一个名为 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 错误。您将必须允许来自用于启动应用程序的本地主机和端口的调用。您应该选择 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 可以用于许多类似的场景。