- ABP Framework version: v6.0.0
- UI type: Angular / MVC
- DB provider: EF Core
- Tiered (MVC) or Identity Server Separated (Angular): no
I have two different abp projects. One is MVC, other is Angular. (Client is Angular oauth server is MVC project) i have created a new Application and scope to OpenIdDict in MVC Project. In Angular project I have opened Oauth external login in settings and entered that information to Angular project like this link . I have created a test username to both projects, when i run two projects and enter user-password in angular project gives error "Exception: Unable to get the email of external user!". How can i solve the problem? Thanks.
- Exception message and stack trace:
Exception: Unable to get the email of external user! Volo.Abp.Identity.ExternalLoginProviders.OAuth.OAuthExternalLoginProvider.MapClaimsToExternalLoginUserInfoAsync(IEnumerable<Claim> claims) Volo.Abp.Identity.ExternalLoginProviders.OAuth.OAuthExternalLoginProvider.GetUserInfoAsync(string userName, string plainPassword) Volo.Abp.Identity.ExternalLoginProviderWithPasswordBase.UpdateUserAsync(IdentityUser user, string providerName, string plainPassword) Volo.Abp.Identity.AspNetCore.AbpSignInManager.PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) Volo.Abp.Account.Public.Web.Pages.Account.LoginModel.OnPostAsync(string action) Volo.Abp.Account.Web.Pages.Account.OpenIddictSupportedLoginModel.OnPostAsync(string action) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+GenericTaskHandlerMethod.Convert<T>(object taskAsObject) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+GenericTaskHandlerMethod.Execute(object receiver, object[] arguments) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync() Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync() Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Builder.ApplicationBuilderAbpOpenIddictMiddlewareExtension+<>c__DisplayClass0_0+<<UseAbpOpenIddictValidation>b__0>d.MoveNext() Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Volo.Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
13 Answer(s)
-
0
hi
Unable to get the email of external user!
Try to debug the
MapClaimsToExternalLoginUserInfoAsync
method. share the values ofclaims
Configure<AbpIdentityOptions>(options => { options.ExternalLoginProviders.RemoveAll(x => x.Key == "OAuth"); options.ExternalLoginProviders.Add<MyOAuthExternalLoginProvider>(MyOAuthExternalLoginProvider.Name); }); public class MyOAuthExternalLoginProvider : OAuthExternalLoginProvider { public const string Name = "OAuth"; public ILogger<OAuthExternalLoginProvider> Logger { get; set; } protected OAuthExternalLoginManager OAuthExternalLoginManager { get; } protected ISettingProvider SettingProvider { get; } protected IFeatureChecker FeatureChecker { get; } protected AbpOAuthExternalLoginProviderOptions Options { get; } public MyOAuthExternalLoginProvider( IGuidGenerator guidGenerator, ICurrentTenant currentTenant, IdentityUserManager userManager, IIdentityUserRepository identityUserRepository, IOptions<IdentityOptions> identityOptions, OAuthExternalLoginManager oAuthExternalLoginManager, ISettingProvider settingProvider, IFeatureChecker featureChecker, IOptions<AbpOAuthExternalLoginProviderOptions> options) : base(guidGenerator, currentTenant, userManager, identityUserRepository, identityOptions, oAuthExternalLoginManager, settingProvider, featureChecker, options) { } protected override Task<ExternalLoginUserInfo> MapClaimsToExternalLoginUserInfoAsync(IEnumerable<Claim> claims) { var claimsArray = claims as Claim[] ?? claims.ToArray(); var email = claimsArray.FirstOrDefault(x => x.Type == Options.EmailClaimType); if(email == null) { throw new Exception("Unable to get the email of external user!"); } var userInfo = new ExternalLoginUserInfo(email.Value) { Name = claimsArray.FirstOrDefault(x => x.Type == Options.NameClaimType)?.Value, Surname = claimsArray.FirstOrDefault(x => x.Type == Options.SurnameClaimType)?.Value, EmailConfirmed = claimsArray.FirstOrDefault(x => x.Type == Options.EmailConfirmedClaimType)?.Value.To<bool>() ?? false, PhoneNumber = claimsArray.FirstOrDefault(x => x.Type == Options.PhoneNumberClaimType)?.Value, PhoneNumberConfirmed = claimsArray.FirstOrDefault(x => x.Type == Options.PhoneNumberConfirmedClaimType)?.Value.To<bool>() ?? false, ProviderKey = claimsArray.FirstOrDefault(x => x.Type == Options.ProviderKeyClaimType)?.Value }; return Task.FromResult(userInfo); } }
-
0
-
0
-
0
My OAuth server is an application that is an mvc application created from abp suite. I add Angular app's informations to open id dict which i add the picture to first message. So how can i add required claims to oauth (Web app that was created from suite) server ?
-
0
hi
Can you share a minimum project with me?
-
0
Hi,
I have created starter ASP.Net MVC project via suite and share with you on github.
-
0
hi
What are the steps to reproduce the problem on your shared project?
-
0
It's not as complicated as you think. I have different two ABP Projects. One is MVC other is Angular based.
- I created new Asp.Net MVC project from abp suite (OAuth server)
- I created another new Angular based abp project from abp suite. (Different client project )
- In the above first message i added a picture that's name is Openiddict Application Configuration (In mvc project add a new configuration for other abp angular client )
- In the above first message i added a picture that's name is Angular Project Client (In angular project add fill the OAuth Login Setting)
I did not do any extra action other than what I wrote above. Then when i login in Angular project it authenticates from OAuth server bu gets Exception: Unable to get the email of external user! namely my oauth server does not return the required claims.
-
0
Can you provide these two projects(MVC & angular)? I hope I can reproduce the problem locally and then fix it.
-
0
I shared two projects with you in github
-
0
Thanks, I will check it asap
-
0
-
0
Hi,
Thanks. I add these scopes to both client and server apps then it gets email address and login is successfull