Как добавить клиентов Duende для связи m2m с ASP.NET Core по умолчанию с шаблоном Angular и токеном запроса из C#
В проекте, который был запущен с использованием шаблона из Visual Studio ASP.NET Core с Angular с новейшей версией шаблона, появилось новое требование для связи со службой Windows.
В веб-проекте все работает нормально. Сервис должен вызывать API и данные POST, поэтому, конечно, ему необходимо войти в систему перед фактической публикацией данных. Это означает, что он должен запросить токен перед отправкой данных.
Проблема в том, что какие бы изменения ни вносились в проект или конфигурацию, Postman получает только ответ: "Аутентификация не удалась". Конфигурация проекта производилась в соответствии с Документацией и некоторыми другими туториалами.
Это не работает и в новых проектах.
Program.cs это:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// see https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();
app.MapFallbackToFile("index.html"); ;
app.Run();
Config.cs это:
using Duende.IdentityServer.Models;
namespace Project1
{
public class Config
{
public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("scope1"),
new ApiScope("scope2"),
new ApiScope("api1"),
};
public static IEnumerable<Client> Clients =>
new Client[]
{
// m2m client credentials flow client
new Client
{
ClientId = "postman",
ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedScopes = { "api1" }
},
// m2m client credentials flow client
new Client
{
ClientId = "m2m.client",
ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedScopes = { "scope1" }
},
// interactive client using code flow + pkce
new Client
{
ClientId = "interactive",
ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { "https://localhost:44300/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:44300/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:44300/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "scope2" }
},
};
}
}
Ответ в Почтальоне:
Duende.IdentityServer.Events.DefaultEventService[0]
{
"ClientId": "postman",
"Category": "Authentication",
"Name": "Client Authentication Failure",
"EventType": "Failure",
"Id": 1011,
"Message": "Unknown client",
"ActivityId": "0HMK7CLQNRGOT:00000002",
"TimeStamp": "2022-08-26T13:19:26Z",
"ProcessId": 30948,
"LocalIpAddress": "127.0.0.1:7229",
"RemoteIpAddress": "127.0.0.1"
}
fail: Duende.IdentityServer.Validation.ClientSecretValidator[0]
No client with id 'postman' found. aborting
Конфигурация почтальона:
Почтальон получает ответ на:
Что ясно показывает, что область «api1» не добавлена. Что-то девинетно не работает.
Независимо от того, какие изменения внесены, это похоже на то, что клиенты в конфигурации не загружаются, потому что загружены клиенты в базе данных.
Единственная разница между нашим проектом Program.cs и документацией ( https://docs.duendesoftware.com/identityserver/v5/quickstarts/5_aspnetid/ ) заключается в том, что там вызывается builder.Services.AddIdentityServer() с .AddAspNetIdentity(); но это нельзя изменить в шаблоне Angular, поскольку при входе в браузер возникает следующая ошибка:
System.InvalidOperationException: служба для типа «Duende.IdentityServer.Stores.ISigningCredentialStore» не зарегистрирована.
Каково решение для связи с другими типами клиентов, когда используется шаблон проекта Angular, и как можно запросить токен у С#, то есть делать то, что делает Почтальон?