- ABP Framework version: v3.2.0
- UI type: MVC
- Tiered (MVC) or Identity Server Seperated (Angular): no
- Exception message and stack trace:
Hello, I have following scenario: I have to build a custom registration page for a specific type of users. Anoynmous Users should register themselves. For this I implemented a method that checks if the user already exists and if yes it will invaldiate the object. I marked the Razor Page and the method with the AllowAnonymous attribute but I receive the error message below within the trace:
Volo.Abp.Authorization.AbpAuthorizationException HResult=0x80131500 Message=Authorization failed! Given policy has not granted. Source=Volo.Abp.Authorization StackTrace: at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.d__15.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Authorization.MethodInvocationAuthorizationService.d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Authorization.AuthorizationInterceptor.d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Authorization.AuthorizationInterceptor.d__2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.<InterceptAsync>d__3
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Castle.DynamicProxy.AsyncInterceptorBase.<ProceedAsynchronous>d__14
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.d__7.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Auditing.AuditingInterceptor.d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.<InterceptAsync>d__3
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Castle.DynamicProxy.AsyncInterceptorBase.<ProceedAsynchronous>d__14
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.d__7.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Validation.ValidationInterceptor.d__2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.<InterceptAsync>d__3
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Castle.DynamicProxy.AsyncInterceptorBase.<ProceedAsynchronous>d__14
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.d__7.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Volo.Abp.Uow.UnitOfWorkInterceptor.d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.<InterceptAsync>d__3
1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at ImmoRecommend.AsyncHelpers.<>c__DisplayClass1_0
1.<b__0>d.MoveNext() in C:\Users\abier\source\repos\ImmoRecommend\src\ImmoRecommend.Domain.Shared\AsyncHelpers.cs:line 57
<br> This exception was originally thrown at this call stack: [External Code] ImmoRecommend.AsyncHelpers.RunSync.AnonymousMethod__0(object) in AsyncHelpers.cs
* Steps to reproduce the issue:
[AllowAnonymous]
public class RegisterModel : ImmoRecommendPageModel
{
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
//Register
var recommender = await _recommenderAppManager.CreateAsync(RecommenderRegisterView);
return Page();
}
}
ModelState.IsValid will call the validation
public class RecommenderRegisterView : IValidatableObject
{
[Required]
[EmailAddress]
public string EMail { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[AllowAnonymous]
IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
{
//check if user already exists
var identityUserAppService = validationContext.GetRequiredService<IIdentityUserAppService>();
var existingIdentityUserDto = AsyncHelpers.RunSync<IdentityUserDto>(() => identityUserAppService.FindByEmailAsync(EMail));
`if (existingIdentityUserDto != null)`
`{`
`yield return new ValidationResult(`
`"E-Mail Adresse bereits vergeben",`
`new[] { "EMail" }`
`);`
`}`
`}`
`}`
The reason seems to be clear. IIdentityUserAppService as a build in class requires authorization.
In order to make it work I build my own IdentutyUserAppService and inherited from the original IdentityUserAppService and set the method to anonymous
/// <summary>
/// Replaces the IdentutyUSerAppService
/// </summary>
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IIdentityUserAppService), typeof(IdentityUserAppService), typeof(CustomIdentityUserAppService))]
public class CustomIdentityUserAppService : IdentityUserAppService
{
//...
//public CustomIdentityUserAppService(
// IdentityUserManager userManager,
// IIdentityUserRepository userRepository,
// IGuidGenerator guidGenerator
//) : base(
// userManager,
// userRepository,
// guidGenerator,
//{
//}
public CustomIdentityUserAppService(IdentityUserManager userManager, IIdentityUserRepository userRepository, IIdentityRoleRepository roleRepository, IOrganizationUnitRepository organizationUnitRepository,
IIdentityClaimTypeRepository identityClaimTypeRepository, IdentityTwoFactorManager identityTwoFactorManager) : base(userManager, userRepository, roleRepository, organizationUnitRepository, identityClaimTypeRepository, identityTwoFactorManager)
{
}
/// <summary>
/// Allow Anoynmous in the FindByEMailAsync method
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
[AllowAnonymous]
public override Task<IdentityUserDto> FindByEmailAsync(string email)
{
return base.FindByEmailAsync(email);
}}
This makes it work.
However, I don't like this kind of implementation, otherwise there is no reason to write a service of your own. Is there another way to set the access rights for IdentityUserAppService? I checked up the docs but cant find any proper solution here for me. Thanks in advance!
P.S: After years of absence I started developing in .NET again, Maybe I forgot some concepts behind
1 Answer(s)
-
0
hi
It is not good practice to use application services in
ValidatableObject.Validate
method.You can consider creating an anonymous application service and calling it in the
Register
page.