提问人:Simon Painter 提问时间:11/3/2023 最后编辑:TylerHSimon Painter 更新时间:11/8/2023 访问量:27
ASP.NET Core 6 和 ReactJS Azure 身份验证集成
ASP.NET Core 6 & ReactJS Azure Authentication Integration
问:
我正在尝试获得一个 ReactJS 网站,以便能够与围绕我们庄园设置的 Web API 进行通信。我们使用 Azure 集成 SSO,我希望能够使用它,以便用户可以使用 React 前端登录,然后使用该登录从我们的 Web API 请求数据。我一直在尝试让它工作,但我无法在 ASP.NET Core 6 控制器操作中获取用户详细信息,但它似乎既不存在于 User 对象中,也不存在于 Request 的“access_token”属性中。
我们在 React 前端使用“@azure/msal-react”对用户进行身份验证。它在那里工作正常 - 用户能够通过 SSO 登录并被 React 应用程序识别。
使用 MSAL,我调用 MsGraph 来获取用户的详细信息:
instance.acquireTokenSilent({
...loginRequest,
account: accounts[0]
}).then((response) => {
callMsGraph(response.accessToken).then(r => {
const gData: GraphData = {
givenName: r.givenName,
surname: r.surname,
userPrincipalName: r.userPrincipalName,
id: r.id,
accessToken: response.accessToken,
authToken: r.authToken
};
props.setGraphData(gData);
});
得到 后,我这样调用我们的 Web API:accessToken
export async function getAvailableSites(accessToken: string) {
const url = `${process.env.REACT_APP_baseurl}/Controller/Action`;
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers
};
const result = await fetch(url, options);
const jsonData = await result.json();
return jsonData;
}
我在 ASP.NET 中配置了身份验证,如下所示:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddJwtBearer("Bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
};
})
.AddMicrosoftIdentityWebApp(AzureADConfig)
.EnableTokenAcquisitionToCallDownstreamApi(graphApiScopes)
.AddMicrosoftGraph(Configuration.GetSection("GraphAPI"))
.AddInMemoryTokenCaches();
services.AddCors(o =>
{
o.AddPolicy("AllowReactJSPolicy", p =>
{
p.WithOrigins("*");
});
});
控制器操作标记为“Authorize”,但 access_token 属性中没有任何内容:
[Authorize]
public async Task<JsonResult> Action()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
}
该对象也是空的。User
我可以获取原始的“授权”HTTP标头,并像这样从中获取数据:
if (!string.IsNullOrWhiteSpace(token))
{
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(token);
}
但大多数数据都是加密的。无论如何 - 肯定有一种比 HTTP 标头的原始处理更好的处理方法,不是吗?
我真的需要知道用户是谁,因为它是我稍后执行的方法之一的必要参数。我还想确保用户得到了适当的验证,并且 ASP.NET Core 不只是让每个请求都通过。
如果没有使用SSO的能力,React.js实际上对我们毫无用处。
答:
我们现在有一个 reactjs 客户端应用程序 + asp.net 核心 webapi 后端应用程序。因此,我们需要将访问令牌传递给 api,然后我们可以获得安全的 API 数据响应,对吧?顺便说一句,我们已经在 react 应用程序中成功调用了图形 api,我们现在只想让 api 控制器获取我们从图形 API 获得的用户配置文件。
因此,首先我们需要知道,访问令牌不包含包含用户数据的声明,在这种方案中,我们用于调用自己的 webapi 的访问令牌与我们用于调用 Graph API 的访问令牌不同。最重要的区别是 .例如,图形 api 的范围可能看起来像,但自定义 webapi 的范围可能看起来像 。scope
User.Read.All
api://app_id/api_permission_name
我们首先要做的,就是改变api项目中的配置,首先我们需要改变的是我们应该使用代替。我们这里有一个教程来指导我们如何公开 API 以使用它来保护你的 Web API,以及如何生成正确的访问令牌来调用此 API。我们这里也有官方示例,几天前我也进行了测试,这是我测试中 api 项目内部配置的摘要。AddMicrosoftIdentityWebApi
AddMicrosoftIdentityWebApp
在 API 中设置配置后,现在可以生成一个访问令牌,其范围已公开并分配给身份验证应用。现在我们已经能够将 api 和客户端 app 连接起来,这样我们就可以在请求体中传递用户数据,如果我们不想通过请求传递数据,我们也可以在 api 项目内部调用 graph api,但是,我们可以在 api 项目内使用 on-behalf-of flow 来使用访问令牌生成新的访问令牌来调用图形 API。
这是我的代码片段。
StringValues authorizationToken;
HttpContext.Request.Headers.TryGetValue("Authorization", out authorizationToken);
var token = authorizationToken.ToString().Replace("Bearer ","");
var scopes = new[] { "User.Read.All" };
var tenantId = "xxxx";
var clientId = "xxxx";
var clientSecret = "xxxx";
var onBehalfOfCredential = new OnBehalfOfCredential(tenantId, clientId, clientSecret, token);
var tokenRequestContext = new TokenRequestContext(scopes);
var token2 = onBehalfOfCredential.GetTokenAsync(tokenRequestContext, new CancellationToken()).Result.Token;
var graphClient = new GraphServiceClient(onBehalfOfCredential, scopes);
var user = await graphClient.Users.GetAsync();
评论