aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

ASP.Net Core 6 SignInManager PasswordSignInAsync throws provider null exception

Open khteh opened this issue 3 years ago • 5 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

SignInManager PasswordwordSignInAsync throws "Value cannot be null. (Parameter 'provider')" exception when I am unit-testing MVC Razor with ASP.Net Core 6 Identity.

var httpContextMock = new Mock<HttpContext>();
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
var httpContextMockObject = httpContextAccessorMock.Object;
IServiceCollection services = new ServiceCollection();
services.AddScoped(x => httpContextAccessorMock);
services.AddScoped(x => httpContextMockObject);
services.AddAuthentication();
services.AddScoped<SignInManager<MyUser>>();

What do I miss?

Expected Behavior

No error to build a unit test for Razor application.

Steps To Reproduce

No response

Exceptions (if any)

"Value cannot be null. (Parameter 'provider')"

.NET Version

6.0.9, 6.0.109

Anything else?

No response

khteh avatar Oct 09 '22 08:10 khteh

The service provider needs to be set on the HttpContext:

httpContextMock.Setup(x => x.RequestServices).Returns(() => sp.CreateScope());

Assuming you build the service provider at some point.

davidfowl avatar Oct 10 '22 03:10 davidfowl

System.ArgumentException : Invalid callback. Setup on method with return type 'IServiceProvider' cannot invoke callback with return type 'IServiceScope'.

khteh avatar Oct 10 '22 08:10 khteh

httpContextMock.Setup(x => x.RequestServices).Returns(() => sp.CreateScope().ServiceProvider);

davidfowl avatar Oct 10 '22 14:10 davidfowl

Now it crashes at:

at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.InitializeHandlerAsync()\n   
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)\n   
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)\n   
at Duende.IdentityServer.Hosting.FederatedSignOut.FederatedSignoutAuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme) in /_/src/IdentityServer/Hosting/FederatedSignOut/FederatedSignoutAuthenticationHandlerProvider.cs:line 33\n   
at Duende.IdentityServer.Services.DefaultUserSession.AuthenticateAsync() in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 137\n   
at Duende.IdentityServer.Services.DefaultUserSession.GetUserAsync() in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 204\n   
at Duende.IdentityServer.Services.DefaultUserSession.CreateSessionIdAsync(ClaimsPrincipal principal, AuthenticationProperties properties) in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 168\n   
at Duende.IdentityServer.Hosting.IdentityServerAuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties) in /_/src/IdentityServer/Hosting/IdentityServerAuthenticationService.cs:line 59\n   
at Microsoft.AspNetCore.Identity.SignInManager`1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable`1 additionalClaims)\n   
at Microsoft.AspNetCore.Identity.SignInManager`1.SignInOrTwoFactorAsync(TUser user, Boolean isPersistent, String loginProvider, Boolean bypassTwoFactor)\n   
at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(TUser user, String password, Boolean isPersistent, Boolean lockoutOnFailure)\n   
at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)\n   
at KyberlifeIAM.Infrastructure.Data.Repositories.UserRepository.SignIn(String username, String password, String remoteIP, Boolean rememberMe, Boolean logoutOnFailure) in /usr/src/kyberlife/KyberlifeIAM/src/KyberlifeIAM.Infrastructure/Data/Repositories/UserRepository.cs:line 216"

khteh avatar Oct 13 '22 07:10 khteh

Have you set up the HttpResponse on your mocked HttpContext?

https://github.com/dotnet/aspnetcore/blob/f96dce6889fe67aaed33f0c2b147b8b537358f1e/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs#L61

You're going to have to work through the code and set up your mock with the appropriate properties/services/method results that are expected at runtime.

Alternatively, look into another approach to testing with integration tests where you won't have to worry about setting up mocks (and thus implementation details) so specifically and precisely to make your tests work.

martincostello avatar Oct 13 '22 08:10 martincostello

Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!

ghost avatar Dec 13 '22 20:12 ghost