У меня есть проект IdentiyServer с этой конфигурацией:
public static class Config
{
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>
{
new ApiResource("api1", "My API 1"),
new ApiResource("api2", "My API 2"),
new ApiResource("api3", "My API 3"),
new ApiResource("api4", "My API 4")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials, // no interactive user, use the client id/secret for authentication
ClientSecrets = {new Secret("secret".Sha256())}, // secret for authentication
AllowedScopes = {"api1"} // scopes that client has access to
},
new Client
{
ClientId = "client-da-focus",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = {new Secret("secret-da-focus".Sha256())},
AllowedScopes = {"api2", "api3"}
},
new Client
{
ClientId = "client-da-carpark",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = {new Secret("secret-da-carpark".Sha256())},
AllowedScopes = {"api4"}
}
};
}
Вот запуск:
public class Startup
{
public IWebHostEnvironment Environment { get; }
public Startup(IWebHostEnvironment environment)
{
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
var builder = services.AddIdentityServer()
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients);
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
}
}
У меня есть другой проект API с контроллером Identity. Вот первый запуск:
publi c class Startup {publi c Startup (конфигурация IConfiguration) => Configuration = configuration;
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = Configuration["identity:discovery:document"];
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
ValidAudiences = new List<string>
{
"api1",
"api2",
"api3",
"api4"
}
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
И контроллер:
[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get() => new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
Теперь я предполагаю, что поскольку все четыре ValidAudience
добавлены и любой клиент, вызывающий API контроллера идентификации, получу и все в порядке.
Вместо этого я получаю 401 .
Мой третий проект, который является клиентом, настроен следующим образом:
App.cs:
public class App
{
private readonly IConfigurationRoot _config;
private readonly ILogger<App> _logger;
public App(IConfigurationRoot config, ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<App>();
_config = config;
}
public async Task Run()
{
var appConfig = _config.GetSection("identity").Get<Identity>();
// discover endpoints from metadata
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(appConfig.Discovery.Document);
if (disco.IsError)
{
_logger.LogError($"Discovery Error: {disco.Error}");
return;
}
// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = appConfig.Token.Request.ClientId,
ClientSecret = appConfig.Token.Request.ClientSecret,
Scope = appConfig.Token.Request.Scope
});
if (tokenResponse.IsError)
{
_logger.LogError($"Token Error: {tokenResponse.Error}");
return;
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n");
// call api
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync(appConfig.Api.Url);
if (!response.IsSuccessStatusCode)
{
_logger.LogWarning($"Api Response: {response.StatusCode}");
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
Console.WriteLine("\n");
}
Console.ReadLine();
}
}
У меня правильно настроены URL-адреса в настройках :
{
"identity": {
"discovery": {
"document": "https://localhost:44377"
},
"token": {
"request": {
"clientId": "client-da-focus",
"clientSecret": "secret-da-focus",
"scope": "api2"
}
},
"api": {
"url": "https://localhost:44380/identity"
}
},
...
}
Обратите внимание, что я собираюсь использовать только определенный API (# 2).
Когда App.cs пытается var disco = await client.GetDiscoveryDocumentAsync(appConfig.Discovery.Document);
, он просто остается там неопределенно долго. После отладки я заметил 401.
Почему сервер IdentityServer4 не авторизует вызов API?