I created the MyAuthorizeController file and this is what it looks like
[Dependency(ReplaceServices = true)] [Route("connect/authorize")] [ApiExplorerSettings(IgnoreApi = true)] [ExposeServices(typeof(AuthorizeController))] public class MyAuthorizeController : AbpOpenIdDictControllerBase
But on running the AuthServer, I am getting this exception :
The type 'G1.health.AuthServer.MyAuthorizeController' is not assignable to service 'Volo.Abp.OpenIddict.Controllers.AuthorizeController'.
Hi, the user Id is coming as fine, but the Tenant Id is coming as NULL So when I call the
var user = await UserManager.GetUserAsync(principal);
method inside the using (CurrentTenant.Change(principal.FindTenantId())) block,
it returns the user value as null, whereas if I call the
var user = await UserManager.GetUserAsync(principal);
method outside that CurrentTenant.Change block, it returns the correct value of the user.
But even if I call the get user method outside the Change Tenant block, it will return to the logged out page of the angular application, and even in the application-configuration api call, the user details are coming fine, but there the roles list is empty.
And yes, here are the list of principals we are getting in the
var principal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;
"iss: https://test2dev.localhost:44322/" "exp: 1727250876" "iat: 1727250576" "oi_cl_dstn: {""oi_au_id"":[""access_token""],""preferred_username"":[""access_token"",""id_token""],""sub"":[""access_token""],""email"":[""access_token"",""id_token""],""oi_rsrc"":[""access_token""],""oi_scp"":[""access_token""]}" "sub: 3a0daa97-5fba-2079-563c-3e26309bdc81" "preferred_username: admin" "email: safwan@gmail.com" "AspNet.Identity.SecurityStamp: 6DCVHJYKEIHLAYOAR3SQBAPWS23CADJ5" "oi_scp: offline_access" "oi_scp: openid" "oi_scp: profile" "oi_scp: email" "oi_scp: phone" "oi_scp: AccountService" "oi_scp: IdentityService" "oi_scp: AdministrationService" "oi_scp: SaasService" "oi_scp: ProductService" "oi_scp: ClinicService" "oi_scp: AppointmentService" "oi_scp: FormsService" "oi_rsrc: AccountService" "oi_rsrc: IdentityService" "oi_rsrc: AdministrationService" "oi_rsrc: SaasService" "oi_rsrc: ProductService" "oi_rsrc: ClinicService" "oi_rsrc: AppointmentService" "oi_rsrc: FormsService" "oi_prst: Angular" "oi_reduri: http://test2dev.localhost:4200" "oi_cd_chlg: WuYkSCHygkcNN21XgdHesy-ipW6sguTwenSo-yuwiEQ" "oi_cd_chlg_meth: S256" "oi_nce: YXhXcThfRFBXa2ZtU21KWXhBUWhEd1Bkb0dXcEVzX1MyZXRUN0RMRnIwbC5D" "oi_crt_dt: Wed, 25 Sep 2024 07:49:36 GMT" "oi_exp_dt: Wed, 25 Sep 2024 07:54:36 GMT" "oi_au_id: 3a14ecaf-dae0-d535-4201-7197e6e3092e" "oi_tkn_id: 3a153a55-116d-c6bc-9bc4-a717fb205ede" "oi_tkn_typ: authorization_code"
I am also checking in the changes if you want to have a look
I added this file, and tried to debug,
in this line var user = await UserManager.GetUserAsync(principal);
I am getting the value of user as NULL
I tried to check how the value is coming, it's coming from the the UserManager file that we added, from that file
public override async Task<IdentityUser?> FindByIdAsync(string userId)
{
ThrowIfDisposed();
return await base.FindByIdAsync(userId);
}
From this method, it fetches the User, but when I debugged here, it's returning NULL from this method, so I replaced this code to the following code
public override async Task<IdentityUser?> FindByIdAsync(string userId)
{
ThrowIfDisposed();
return await _repository.FindByIdAsync(new Guid(userId));
}
Here the _repository is the G1.health.IdentityService.Users.IIdentityUserRepository interface which I have injected in the class. And by using that, it does return the user's details, but still in the
var user = await UserManager.GetUserAsync(principal)
line of the MyTokenController, it comes up as NULL
Sent you the file (test2dev.localhost.har)
I made the following changes in the healthAuthServerModule.cs file of AuthServer
context.Services.PostConfigure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.DynamicContributors.Clear();
options.DynamicContributors.RemoveAll(x => x == typeof(Volo.Abp.Identity.IdentityDynamicClaimsPrincipalContributor));
});
After adding this, when I click on the login button now, it does redirect to the angular application, but it will go there and keep reloading the same angular landing page (logged out page) again and again. I am sending the logs as well.
Shared you the logs after disabling the dynamic logs.
Shared the logs, please check.
Hi, I tried the changes you provided. I still couldn't hit the breakpoints. After clicking on login button for the first time, it would redirect to the landing page of the angular app (logged out screen) and again redirect to the login page, and for the next time onwards while clicking on the login button, it will just stay there on the login page. But one thing I observed is that now in the logs, I am not getting that User Not Found error, I am sharing the logs via email, can you check what could be wrong here.
Can you pull the changes now and build?
I'll again explain you the whole scenario what we are looking for :
What ABP does :
ABP has a host tenant, which has Tenant Id as NULL everywhere. Now let's say we create a role from the host called "app user". And it will be stored in the AbpRoles table where TenantId of the role will be NULL.
We then provide certain permissions to that role. And that information will be stored in the AbpPermissionGrants table, and there as well the TenantId will be NULL.
Now if we create a user in the host, that user will be created in the AbpUsers table and it will have TenantId as NULL. And then if we assign that "app user" role to that new user, that information will be stored in the AbpUserRoles table. Here, we will have UserId as Id from AbpUsers, RoleId as Id from AbpRoles and TenantId as NULL.
Now, wherever the user will login, it will have only those permissions granted to it which are related to the role he's assigned, and what permissions are granted to that user will be available in the "GrantedPolicies" section of the abp app configuration API call response under the "auth" section. Here we also have a section called CurrentUser, in which we will have the property called "roles", inside which we will have list of all the roles assigned to that user. And according to whatever permissions granted to that user, it will be able to perform the actions.
What we want :
Consider the whole ABP scenario explained above again.
Now let's, say I create a Tenant called "test". It will have a certain TenantId.
Now, let's say I create a user in this tenant, and for that the data will be stored in the AbpUsers table, with that same TenantId. We don't want this TenantId to be stored here in this AbpUsers table, instead we will store the TenantId and the Id of the User in the association table that we created, "user_tenant_association" table. So overall, the user will be added in the AbpUsers table with TenantId as NULL, even though it's been added from a tenant. But that user belongs to that Tenant, that information will be stored in our custom table, where the actual TenantId will be stored along with the Id of the user.
Everything fair and square till this point.
Now, in the ABP Scenario, we created a Role called "app user" right, we want to assign that role to this user that we created in the test tenant. This is what we are looking to achieve.
To make this happen, we will have to add the data in the AbpUserRoles table, as follow :
AbpUserRoles table columns with values
UserId : Id of the User from AbpUsers table RoleId : Id of the Role "app user" from AbpRoles table (WHICH HAS TENANT ID AS NULL) TenantId : The ACTUAL TenantId of the Tenant.
Now, keeping this scenario in mind, we want this user created in the test tenant, to have roles as "app user" and permissions granted to it as whatever permissions a user will have if it was created in host tenant with the exact same "app user" role assigned to it.
This is what we want to achieve.