【发布时间】:2021-10-20 17:08:28
【问题描述】:
我会尽量简短地解释它。我的问题?尝试从 C# 代码(控制台应用程序)获取令牌时,我得到一个无效令牌。
场景 1(来自前端应用程序):
- 用户在 React 应用中输入他/她的凭据。
- 调用https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize端点。
- 已检索到令牌 ID(到目前为止一切顺利)
- 当经过身份验证的用户向私有 Web API 的任何端点发出请求时,会再次调用以下端点:https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token,并附加步骤 3 中的令牌 ID。
- 检索到新的 JWT 令牌
- 此 JWT 令牌附加到向 Web API 发出的请求的标头中
- 响应返回到 React 应用程序。
这是我们在 React 应用程序和 Web API 之间进行交互时使用的常规流程。这是来自 MS docs
的可视化流程现在,出现了一个新场景:
场景 2(尝试从 c# 代码执行/模拟相同的操作):
我正在尝试从 C# 代码将 JWT 令牌附加到标头,为此我正在使用 MSAL.NET。官方doc
对于我的测试,我使用的是控制台应用程序:
private static async Task RunAsync()
{
string clientId = "client Id of the application that I have registered using azure app registration in Azure B2C";
string clientSecret = "client secret of the application that I have registered using azure app registration in Azure B2C";
string instance = "https://login.microsoftonline.com/{0}/";
string tenantId = "Tenant Id that I can see when I open the application that I have registered using azure app registration in Azure B2C";
string webAppUri = "web app domain";
// For Web applications that use OpenID Connect Authorization Code flow, use IConfidentialClientApplication
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.WithLegacyCacheCompatibility(false)
.Build();
// For confidential clients, this value should use a format similar to {Application ID URI}/.default.
// https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon#requesting-tokens
string[] scopes = new string[] { $"{webAppUri}/.default" };
AuthenticationResult result = null;
try
{
result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Token acquired");
Console.WriteLine($"{result.AccessToken}");
Console.ResetColor();
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
// Invalid scope. The scope has to be of the form "https://resourceurl/.default"
// Mitigation: change the scope to be as expected
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Scope provided is not supported");
Console.ResetColor();
}
if (result != null)
{
var httpClient = new HttpClient();
var apiCaller = new ProtectedApiCallHelper(httpClient);
string webApiUrl = "http://localhost:12345/mycustomwebapi/list";
var defaultRequetHeaders = httpClient.DefaultRequestHeaders;
if (defaultRequetHeaders.Accept == null || !defaultRequetHeaders.Accept.Any(m => m.MediaType == "application/json"))
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
defaultRequetHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await httpClient.GetAsync(webApiUrl);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
var jsonResult = JsonConvert.DeserializeObject<List<JObject>>(json);
}
else
{
Console.WriteLine($"Failed to call the Web Api: {response.StatusCode}");
string content = await response.Content.ReadAsStringAsync();
}
Console.ResetColor();
}
}
上述代码的问题是我得到了一个格式正确的 JWT 令牌并将其附加到标头。但是在调用自定义/安全网络 API 时,我收到 401 Unauthorized response。
所以,我对此有不同的想法:
- 我不太确定我是否缺少此 C# 代码中的步骤与场景 1 中的步骤。
- 或者,如果我需要在 Azure 中为已在 Azure AD 中注册的 Web api 配置任何特殊访问/权限。
- 我应该尝试在 C# 中执行相同的步骤吗?首先调用:https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize 端点和https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token 以获取有效的 JWT 令牌?
另外一件事是,当比较来自 C# 的 JWT 令牌 (https://jwt.io) 与在前端应用中获得的令牌时,会有一些不同的属性。
【问题讨论】:
-
所以您试图代表用户从后端调用 api? docs.microsoft.com/en-us/azure/active-directory/develop/…
-
阅读这篇文章,我会说这就是我正在寻找的用例。感谢分享
标签: c# azure .net-core azure-active-directory