Теперь я должен вызвать свой Api1, используя client_credential с внешним клиентом. Но он возвращает меня на странице входа.
Кажется, вы неправильно поняли сценарий. Ваше MVC-приложение является клиентом и является приложением-ресурсом, которое защищено Identity Server (в Config.cs
):
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
Я предполагаю, что в вашем приложении MVC есть контроллер API:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET: api/Values
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
И у вас есть конфигурация для защиты действий API с помощью AddJwtBearer
:
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000/";
options.RequireHttpsMetadata = false;
options.Audience = "api1";
});
Это означает, что любой запрос на доступ к действию Get
должен иметь заголовок носителя аутентификации с добавлением токена доступа, токен доступа выдается сервером идентификации (конечная точка http://localhost:5000/
), а аудитория - api1
.
Теперь ваш другой клиент может использовать поток учетных данных клиента для получения токена доступа для доступа к вашему веб-приложению:
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});
И назовите ваши защищенные действия:
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("http://localhost:64146/api/values");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
Таким образом, он не будет перенаправлять на страницу входа, поскольку учетные данные клиента фактически отправляют HTTP-запрос POST, чтобы получить токен доступа с учетными данными приложения. В этом сценарии нет страницы входа.