- ABP Framework version: v5.3.3
- UI Type: Angular
- Database System: EF Core (SQL Server, Oracle, MySQL, PostgreSQL, etc..)
- Tiered (for MVC) or Auth Server Separated (for Angular): no
- Exception message and full stack trace: No exception message
- Steps to reproduce the issue:
- I want only external login to be enabled and all other login methods to be disabled in my Abp project. How can I achieve this?
- If the external login is successful, and the user is coming to my system for the first time, I want to perform some checks and custom updates. How can I achieve this? I couldn't determine if I need to implement coding similar to the this solution provided after my research.
Note : External login provider is an another Abp project
8 Answer(s)
-
0
You can check this: https://docs.abp.io/en/commercial/latest/modules/account#local-login
2.
You can override the login and register page, for example:
[ExposeServices(typeof(LoginModel))] public class MyLoginModel : LoginModel { protected virtual async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info) { var user = await base.CreateExternalUserAsync(info); //.. first login } }
[ExposeServices(typeof(RegisterModel))] public class MyRegisterModel : RegisterModel { protected virtual async Task<IdentityUser> RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress) { var user = await base.RegisterExternalUserAsync(externalLoginInfo, emailAddress); //.. first login } }
-
0
Hi, After a successful login from an external login provider, I want to manually check whether the user exists in my system and then when I find the appropriate user, log them into my system (especially for tenant users)
-
0
Hi,
You can try
[ExposeServices(typeof(LoginModel))] public class MyLoginModel : LoginModel { protected virtual async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info) { var email = loginInfo.Principal.FindFirstValue(AbpClaimTypes.Email) ?? loginInfo.Principal.FindFirstValue(ClaimTypes.Email); var user = await UserManager.FindByEmailAsync(email); // just a demo, You can check if the user exists using any way if(user == null) { user = await base.CreateExternalUserAsync(info); } } }
[ExposeServices(typeof(RegisterModel))] public class MyRegisterModel : RegisterModel { protected virtual async Task<IdentityUser> RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress) { var email = loginInfo.Principal.FindFirstValue(AbpClaimTypes.Email) ?? loginInfo.Principal.FindFirstValue(ClaimTypes.Email); var user = await UserManager.FindByEmailAsync(email); // just a demo, You can check if the user exists using any way if(user == null) { user = await base.RegisterExternalUserAsync(externalLoginInfo, emailAddress); } //.. first login } }
-
0
Hi Liangshiwei,
Thank you for your response, I appreciate your answer and I understand it very well. However, it seems like a workaround solution. I want to override the place where the decision to trigger this method is made. Even if I override the CreateExternalUserAsync method, it will still attempt to find the user every time and not be able to find it
-
0
it will still attempt to find the user every time and not be able to find it
Sorry, I didn't get it.
-
0
Hi liangshiwei, If I write the example code exactly as below, it creates a user in the AbpUsers table. If I log in again with the same user through an external provider, this time the CreateExternalUserAsync method is not triggered. Your suggestion works and is effective, but it means that the method (CreateExternalUserAsync) will always check whether the user exists before being called
[ExposeServices(typeof(LoginModel))] public class MyLoginModel : LoginModel { protected virtual async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info) { var user = await base.CreateExternalUserAsync(info); } }
adding external Login provider :
private void ConfigureExternalProviders(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddAuthentication() .AddOpenIdConnect("oidc", options => { options.Authority = "https://localhost:44366/"; options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); ; options.ResponseType = OpenIdConnectResponseType.CodeIdToken; options.ClientId = "Client1"; options.ClientSecret = "mysecret"; options.UsePkce = true; options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Add("role"); options.Scope.Add("email"); options.Scope.Add("phone"); options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); } );
-
0
HI,
Ok, you can try override the
OnGetExternalLoginCallbackAsync
method[ExposeServices(typeof(LoginModel))] public class MyLoginModel : LoginModel { [UnitOfWork] public override async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null) { if (remoteError != null) { Logger.LogWarning($"External login callback error: {remoteError}"); return RedirectToPage("./Login"); } await IdentityOptions.SetAsync(); var loginInfo = await SignInManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { Logger.LogWarning("External login info is not available"); return RedirectToPage("./Login"); } IsLinkLogin = await VerifyLinkTokenAsync(); var result = await SignInManager.ExternalLoginSignInAsync( loginInfo.LoginProvider, loginInfo.ProviderKey, isPersistent: true, bypassTwoFactor: true ); if (!result.Succeeded) { await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Action = "Login" + result }); } if (result.IsLockedOut) { Logger.LogWarning($"Cannot proceed because user is locked out!"); return RedirectToPage("./LockedOut", new { returnUrl = ReturnUrl, returnUrlHash = ReturnUrlHash }); } if (result.IsNotAllowed) { Logger.LogWarning($"External login callback error: User is Not Allowed!"); var user = await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey); if (user.IsActive) { await StoreConfirmUser(user); return RedirectToPage("./ConfirmUser", new { returnUrl = ReturnUrl, returnUrlHash = ReturnUrlHash }); } return RedirectToPage("./Login"); } if (result.Succeeded) { var user = await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey); if (IsLinkLogin) { using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(user))) { await IdentityLinkUserAppService.LinkAsync(new LinkUserInput { UserId = LinkUserId.Value, TenantId = LinkTenantId, Token = LinkToken }); await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentityProSecurityLogActionConsts.LinkUser, UserName = user.UserName, ExtraProperties = { { IdentityProSecurityLogActionConsts.LinkTargetTenantId, LinkTenantId }, { IdentityProSecurityLogActionConsts.LinkTargetUserId, LinkUserId } } }); using (CurrentTenant.Change(LinkTenantId)) { var targetUser = await UserManager.GetByIdAsync(LinkUserId.Value); using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(targetUser))) { await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentityProSecurityLogActionConsts.LinkUser, UserName = targetUser.UserName, ExtraProperties = { { IdentityProSecurityLogActionConsts.LinkTargetTenantId, targetUser.TenantId }, { IdentityProSecurityLogActionConsts.LinkTargetUserId, targetUser.Id } } }); } } } } await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Action = result.ToIdentitySecurityLogAction(), UserName = user.UserName }); return RedirectSafely(returnUrl, returnUrlHash); } var email = loginInfo.Principal.FindFirstValue(AbpClaimTypes.Email); if (email.IsNullOrWhiteSpace()) { return RedirectToPage("./Register", new { IsExternalLogin = true, ExternalLoginAuthSchema = loginInfo.LoginProvider, ReturnUrl = returnUrl }); } //-------- this is the source code, you can change it.------------ var externalUser = await UserManager.FindByEmailAsync(email); if (externalUser == null) { externalUser = await CreateExternalUserAsync(loginInfo); } else { if (await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey) == null) { CheckIdentityErrors(await UserManager.AddLoginAsync(externalUser, loginInfo)); } } if (await HasRequiredIdentitySettings()) { Logger.LogWarning($"New external user is created but confirmation is required!"); await StoreConfirmUser(externalUser); return RedirectToPage("./ConfirmUser", new { returnUrl = ReturnUrl, returnUrlHash = ReturnUrlHash }); } await SignInManager.SignInAsync(externalUser, false); if (IsLinkLogin) { using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(externalUser))) { await IdentityLinkUserAppService.LinkAsync(new LinkUserInput { UserId = LinkUserId.Value, TenantId = LinkTenantId, Token = LinkToken }); await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentityProSecurityLogActionConsts.LinkUser, UserName = externalUser.UserName, ExtraProperties = { { IdentityProSecurityLogActionConsts.LinkTargetTenantId, LinkTenantId }, { IdentityProSecurityLogActionConsts.LinkTargetUserId, LinkUserId } } }); using (CurrentTenant.Change(LinkTenantId)) { var targetUser = await UserManager.GetByIdAsync(LinkUserId.Value); using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(targetUser))) { await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentityProSecurityLogActionConsts.LinkUser, UserName = targetUser.UserName, ExtraProperties = { { IdentityProSecurityLogActionConsts.LinkTargetTenantId, targetUser.TenantId }, { IdentityProSecurityLogActionConsts.LinkTargetUserId, targetUser.Id } } }); } } } } await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext { Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Action = result.ToIdentitySecurityLogAction(), UserName = externalUser.Name }); return RedirectSafely(returnUrl, returnUrlHash); } }
-
0
Hi liangshiwei, Thanks for your support!