I’m currently exploring the new AI-related features in ABP based on the following documentation pages:
https://abp.io/docs/10.0/framework/infrastructure/artificial-intelligence
https://abp.io/docs/10.0/modules/ai-management
I understand that these AI modules are currently in preview, and that’s perfectly fine for our use case.
I have a few concrete questions:
Is there anything specific we need to do or enable in order to start using and testing these AI modules in a real (but controlled) project?
Are there any important current limitations or “known gaps” we should be aware of when adopting the preview (e.g. missing scenarios, not-yet-implemented providers, configuration restrictions)?
What is the current roadmap for these AI modules?
Are there specific milestones or upcoming features you can already share (for example around agent support, orchestration, management UI, etc.)?
Do you expect significant breaking changes in the APIs/configuration as the modules evolve, or do you aim to keep the current abstractions relatively stable?
We have a concrete customer scenario:
The customer wants us to build AI agents using ABP-based application.
At the same time, the customer is building their own API endpoint so they can host and manage AI agents themselves.
Our application should act as a client to that external AI/agent API.
In this context, we would like to know:
Can we configure a custom chat client that calls this external API endpoint using the ConfigureChatClient configuration?
If yes:
What is the recommended way to plug such a custom chat client into the AI infrastructure / AI Management module so that it behaves similarly to the built-in providers?
Do you have a minimal example (or guidance) for implementing a custom chat client that forwards requests to an arbitrary HTTP endpoint?
Our goal is to leverage the ABP AI abstractions (for consistency and future maintainability), while letting the actual AI/agent logic run in the customer’s own API.
example deleted
private void ConfigureAuditing() { Configure<AbpAuditingOptions>(options => { options.IsEnabledForAnonymousUsers = false;
options.EntityHistorySelectors.Add(
new NamedTypeSelector(
"MySelectorName",
type =>
{
return type == typeof(Project) || type == typeof(Configuration);
}
)
);
});
}
Currently am trying to add an external login, using Azure Active Directory. The purpose of this external login, is to be used by administrators only.
As described in the community blog post, I did the following... Note the CustomOpenIdConnectEvents class...
private void ConfigureExternalProviders(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication()
//Omitted other third party configurations
.AddOpenIdConnect("AzureOpenId", "Sign in with Microsoft", options =>
{
options.Authority = $"https://login.microsoftonline.com/{configuration["AzureAd:TenantId"]}/v2.0/";
options.ClientId = configuration["AzureAd:ClientId"];
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.CallbackPath = configuration["AzureAd:CallbackPath"];
options.ClientSecret = configuration["AzureAd:ClientSecret"];
options.RequireHttpsMetadata = false;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("email");
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.SignInScheme = IdentityConstants.ExternalScheme;
options.EventsType = typeof(CustomOpenIdConnectEvents);
});
}
And here is the CustomOpenIdConnectEvents class:
{
[UnitOfWork]
public override async Task TokenValidated(TokenValidatedContext context)
{
await base.TokenValidated(context);
var userManager = context.HttpContext.RequestServices.GetRequiredService<IdentityUserManager>();
var userEmail = context.Principal.FindFirstValue(ClaimTypes.Email);
var currentUser = await userManager.FindByEmailAsync(userEmail);
if (currentUser != null)
{
var adminRoleName = "admin"; // Replace with your admin role name
var isInRole = await userManager.IsInRoleAsync(currentUser, adminRoleName);
if (!isInRole)
{
await userManager.AddToRoleAsync(currentUser, adminRoleName);
var identity = context.Principal.Identity as ClaimsIdentity;
identity?.AddClaim(new Claim(identity.RoleClaimType, adminRoleName));
}
}
}
}
The code itself is working. However with the following issues:
var currentUser = await userManager.GetUserAsync(context.Principal);Concrete: How can I make sure users are automatically administrator? Preferably the registration form should be skipped.
We're running a project, where a client is calling our ABP api. All happy flows are working as aspected.
Client details:
For any given reason tokens might expire. In this case, our client should get a HTTP status 401. This is not the case, it is getting a http status 302 found, whish is redirecting to a error page (= 401).
As you can see in the request, the client is sending a X-Requested-With attribute. This is a recommended solution, but not working. Reference 1 (axios Github) Reference 2 (ABP support)
For cookie authentication, there is a workaround. Reference 1 (ABP Github)
private void ConfigureRedirectStrategy(ServiceConfigurationContext context)
{
// Without this, api calls without "X-Requested-With: XMLHttpRequest"
// are redirected to identity server login page.
// We want to return 401:Unauthorized instead of redirecting
context.Services.ConfigureApplicationCookie(options =>
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return System.Threading.Tasks.Task.CompletedTask;
});
}
As said, this will not work since the client is using Axios for requests.
Concrete question(s): Do you have any ideas how to solve thie issue (status 302 has to be a status 401)? MVC should work properly, so i guess we still have to use the "X-Requested-With: XMLHttpRequest attribute". But why is it not working?
Thanks in advance,
Request
Host: {url}
Connection: keep-alive
sec-ch-ua: "Brave";v="111", "Not(A:Brand";v="8", "Chromium";v="111"
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
Authorization: Bearer ...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36
sec-ch-ua-platform: "Windows"
Sec-GPC: 1
Origin: {url}
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: {url}
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,nl;q=0.8
Response
Content-Length: 0
Date: Tue, 04 Apr 2023 09:50:10 GMT
Server: Kestrel
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: {url}
Access-Control-Expose-Headers: _AbpErrorFormat
Cache-Control: no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: /Error?httpStatusCode=401
Pragma: no-cache
Set-Cookie: ARRAffinity=...
Set-Cookie: ARRAffinitySameSite=...
Vary: Origin
WWW-Authenticate: Bearer error="invalid_token", error_description="The signing key associated to the specified token was not found.", error_uri="https://documentation.openiddict.com/errors/ID2090"
Request-Context: appId=...
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN```
After reading the migration guide... https://docs.abp.io/en/abp/latest/Migration-Guides/OpenIddict-Step-by-Step
Context We have multiple customers. Some of our customers have multiple clients (Administration => Identity Server => Clients) connecting to them. Therefor it is hard for us to test if the clients keep working. We don't have much influence on it.
So my question is.. Are there significant changes that occur, after the migration, that our customers need to report to their clients? Think about endpoint changes. Is there any difference in how tokens are handled?
As far as we know, all clients follow the openid / oauth2 specs. We did not implement custom code on the ABP side.
Another (small) functional question: Can created ABP users use their own password after the migration?
Thanks in advance,
Application '/LM/W3SVC/2/ROOT' with physical root 'D:\Domains\abp_beheer\httpdocs\' has exited from Program.Main with exit code = '1'. First 30KB characters of captured stdout and stderr logs:
[14:14:52 INF] Starting web host.
[14:14:53 FTL] Host terminated unexpectedly!
Volo.Abp.AbpInitializationException: An error occurred during ConfigureServicesAsync phase of the module Volo.Abp.OpenIddict.AbpOpenIddictAspNetCoreModule, Volo.Abp.OpenIddict.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null. See the inner exception for details.
---> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied.
at Internal.Cryptography.Pal.StorePal.FromSystemStore(String storeName, StoreLocation storeLocation, OpenFlags openFlags)
at System.Security.Cryptography.X509Certificates.X509Store.Open(OpenFlags flags)
at Microsoft.Extensions.DependencyInjection.OpenIddictServerBuilder.AddDevelopmentEncryptionCertificate(X500DistinguishedName subject)
at Microsoft.Extensions.DependencyInjection.OpenIddictServerBuilder.AddDevelopmentEncryptionCertificate()
at Volo.Abp.OpenIddict.AbpOpenIddictAspNetCoreModule.<>c__DisplayClass1_0.<AddOpenIddictServer>b__0(OpenIddictServerBuilder builder)
at Microsoft.Extensions.DependencyInjection.OpenIddictServerExtensions.AddServer(OpenIddictBuilder builder, Action`1 configuration)
at Volo.Abp.OpenIddict.AbpOpenIddictAspNetCoreModule.AddOpenIddictServer(IServiceCollection services)
at Volo.Abp.OpenIddict.AbpOpenIddictAspNetCoreModule.ConfigureServices(ServiceConfigurationContext context)
at Volo.Abp.Modularity.AbpModule.ConfigureServicesAsync(ServiceConfigurationContext context)
at Volo.Abp.AbpApplicationBase.ConfigureServicesAsync()
--- End of inner exception stack trace ---
at Volo.Abp.AbpApplicationBase.ConfigureServicesAsync()
at Volo.Abp.AbpApplicationFactory.CreateAsync[TStartupModule](IServiceCollection services, Action`1 optionsAction)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionApplicationExtensions.AddApplicationAsync[TStartupModule](IServiceCollection services, Action`1 optionsAction)
at Microsoft.Extensions.DependencyInjection.WebApplicationBuilderExtensions.AddApplicationAsync[TStartupModule](WebApplicationBuilder builder, Action`1 optionsAction)
at ABP_Beheer.Web.Program.Main(String[] args) in D:\BUILD02_Agent3\_work\730\s\src\ABP_Beheer.Web\Program.cs:line 36
We haven't had this issue with ABP in combination with Identity server. What am i doing wrong, in context of OpenIddict?
Thanks in advance.