Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Prologh
Copy link
Contributor

@Prologh Prologh commented Feb 11, 2024

Add missing TimeProvider registration

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Summary of the changes (Less than 80 chars)

Add missing TimeProvider registration

AddSignInManager() method on IdentityBuilder adds dependencies that use TimeProvider but does not register an implementation for it within service collection. That results in InvalidOperationException being thrown on application startup for invalid service descriptor, because of missing TimeProvider implementation.

Fixes #53938

I haven't been able to locate unit tests that would cover specifically that identity builder methods. Any guidance for that would be welcomed if there is a need to add test coverage for the change.

@ghost ghost added the area-identity Includes: Identity and providers label Feb 11, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Feb 11, 2024
@martincostello
Copy link
Member

I haven't been able to locate unit tests that would cover specifically that identity builder methods. Any guidance for that would be welcomed if there is a need to add test coverage for the change.

Looks like the existing tests live in the IdentityBuilderTest class, like this one:

[Fact]
public void EnsureDefaultServices()
{
var services = new ServiceCollection()
.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
services.AddLogging()
.AddIdentity<PocoUser, PocoRole>()
.AddUserStore<NoopUserStore>()
.AddRoleStore<NoopRoleStore>();
var provider = services.BuildServiceProvider();
var userValidator = provider.GetRequiredService<IUserValidator<PocoUser>>() as UserValidator<PocoUser>;
Assert.NotNull(userValidator);
var pwdValidator = provider.GetRequiredService<IPasswordValidator<PocoUser>>() as PasswordValidator<PocoUser>;
Assert.NotNull(pwdValidator);
var hasher = provider.GetRequiredService<IPasswordHasher<PocoUser>>() as PasswordHasher<PocoUser>;
Assert.NotNull(hasher);
Assert.IsType<RoleManager<PocoRole>>(provider.GetRequiredService<RoleManager<PocoRole>>());
Assert.IsType<UserManager<PocoUser>>(provider.GetRequiredService<UserManager<PocoUser>>());
}

@Prologh
Copy link
Contributor Author

Prologh commented Feb 11, 2024

Thanks for pointing me in the right direction. I've added a new test method since EnsureDefaultServices() uses AddIdentity() which inside calls AddAuthentication() which in turn actually registers TimeProvider (see here). So, to test it out I have to use AddIdentityCore() which skips the additional services, but nevertheless should end up with resolvable dependencies. Let me know if it is too much.

Also, on a side note, I've noticed in the test class a rather often usage of Assert.NotNull() with a result of GetRequiredService() from service provider. This could be considered a code smell, since GetRequiredService() will throw when service in question is not found. Obviously this is out of scope of this PR or related issue. Just nitpicking 😏

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 21, 2024
@Prologh
Copy link
Contributor Author

Prologh commented Feb 21, 2024

/azp run

Copy link

Commenter does not have sufficient privileges for PR 53946 in repo dotnet/aspnetcore

@Prologh
Copy link
Contributor Author

Prologh commented Feb 21, 2024

@martincostello Anything more I should do?

@martincostello
Copy link
Member

If you close and re-open the PR, that will make the CI re-run.

@Prologh Prologh closed this Feb 21, 2024
@Prologh Prologh reopened this Feb 21, 2024
@dotnet-policy-service dotnet-policy-service bot added this to the 9.0-preview2 milestone Feb 21, 2024
@martincostello martincostello removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 21, 2024
Copy link
Member

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the bug report and the PR @Prologh!

Ideally, the SecurityStamValidator shouldn't need a TimeProvider registered with DI. It just needs to use it if it's available. The typical way to do this is to add a constructor to the service that doesn't take a TimeProvider (or makes it optional) and add logic to fall back to TimeProvider.System if it's not provided. This is basically what SecurityStampValidator does.

Can we do something like the following for PostConfigureSecurityStampValidatorOptions?

        public PostConfigureSecurityStampValidatorOptions(TimeProvider? timeProvider = null)
        {
            // We could assign this to "timeProvider ?? TimeProvider.System", but 
            // SecurityStampValidator already has system clock fallback logic.
            TimeProvider = timeProvider;
        }

        private TimeProvider? TimeProvider { get; }

It looks like we also need the same fix in AddIdentity<TUser, TRole> which has its own copy of PostConfigureSecurityStampValidatorOptions does not call AddSignInManager or AddSignInManagerDeps.

We'll have to remove Assert.NotNull(provider.GetService<TimeProvider>()); from the tests, but everything else should still work.

@Prologh
Copy link
Contributor Author

Prologh commented Feb 23, 2024

Sure. I made TimeProvider optional in both versions of PostConfigureSecurityStampValidatorOptions. I've also removed the assert for TimeProvider from test case.

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Mar 2, 2024
@mkArtakMSFT mkArtakMSFT removed this from the 9.0-preview2 milestone Mar 4, 2024
@Prologh Prologh closed this Apr 6, 2024
@Prologh Prologh reopened this Apr 6, 2024
@dotnet-policy-service dotnet-policy-service bot added this to the 9.0-preview4 milestone Apr 6, 2024
@mkArtakMSFT mkArtakMSFT removed this from the 9.0-preview4 milestone Apr 17, 2024
Copy link
Member

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@halter73
Copy link
Member

/azp run

@dotnet-policy-service dotnet-policy-service bot removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Apr 17, 2024
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@halter73 halter73 enabled auto-merge (squash) April 17, 2024 17:02
@halter73 halter73 merged commit 96134fc into dotnet:main Apr 17, 2024
@dotnet-policy-service dotnet-policy-service bot added this to the 9.0-preview4 milestone Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-identity Includes: Identity and providers community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing TimeProvider implementation for Identity
4 participants