【发布时间】:2021-11-23 11:54:44
【问题描述】:
我的 ASP.NET Core (.NET5) 项目带有 API 控制器。我想使用 Identity Server 保护我的 API。我的目标是让一些客户能够访问基于client_id 和client_secret 的API,并在此基础上定义他们可以调用的API。为此,我在 Startup.cs 中添加了以下代码
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(
IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = apiSettings.Authority;
options.ApiName = apiSettings.ApiName;
options.ApiSecret = apiSettings.ApiSecret;
});
}
所以,我在每个控制器中添加了[Authorize] 属性。现在,我想使用 HttpClient 从控制台应用程序或 Web 应用程序调用此 API。
private static async Task<string> GetAccessToken()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
// We want the response to be JSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
// Build up the data to POST.
List<KeyValuePair<string, string>> postData =
new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("scope", "myscope"));
postData.Add(new KeyValuePair<string, string>("client_id", clientId));
postData.Add(new KeyValuePair<string, string>("client_secret",
clientSecret));
FormUrlEncodedContent content = new FormUrlEncodedContent(postData);
// Post to the Server and parse the response.
HttpResponseMessage response = await
client.PostAsync("/api/v1/Test", content);
string jsonString = await response.Content.ReadAsStringAsync();
object responseData = JsonConvert.DeserializeObject(jsonString);
// return the Access Token.
return ((dynamic)responseData).data;
}
}
调用总是返回 401Unauthorized。使用client_id 和client_secret 调用API 的正确方法是什么? scope 是必需的吗?
更新
为了澄清,我认为是机器对机器的场景。因此,没有用户参与。当HttpClient调用API时,它必须通过认证。在机器对机器的场景中,我想检查请求是否具有特定的范围,例如 api_read、api_write、api_full 和基于调用是否可以访问某个函数。
例如,在 Blazor 中,我创建了一个函数来传递 scope,但不传递 clinet_id 和 client_secret。
public class MyAuthorizationMessageHandler :
AuthorizationMessageHandler
{
public MyAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigation, IConfiguration configuration) :
base(provider, navigation)
{
string apiEndpoint = configuration["Api:EndpointsUrl"];
string apiScope = configuration["Api:Scope"];
ConfigureHandler(authorizedUrls: new[] { apiEndpoint },
scopes: new[] { apiScope });
}
}
【问题讨论】:
-
您从哪里获得客户端 ID 和客户端密码?那些是在 IdentityServer 的数据库中注册的吗?日志对 IdentityServer 应用程序上的 401 有什么说明?此外,据我记得,您不能只在任何地方添加 client_id 和 client_secret,而且您的请求甚至没有身份验证类型(指定客户端凭据)。您应该改用 IdentityServer 客户端库。
标签: c# asp.net-core identityserver4