Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WindowsIdentity.RunImpersonatedAsync sending wrong credentials #63136

Closed
daniilzaonegin opened this issue Dec 26, 2021 · 8 comments
Closed

WindowsIdentity.RunImpersonatedAsync sending wrong credentials #63136

daniilzaonegin opened this issue Dec 26, 2021 · 8 comments

Comments

@daniilzaonegin
Copy link

Description

Hi!

This issue is the continuation of issue #58033.

I've made a sample project to reproduce the error https://github.com/daniilzaonegin/ImpersonationTest.
WindowsIdentity.RunImpersonatedAsync reuses the credentials of previous api call.

            var result = await WindowsIdentity.RunImpersonatedAsync(windowsIdentity.AccessToken,
                async () =>
                {
                    HttpClient? client =
                        _clientFactory.CreateClient(ServiceConsts.ImpersonateClientName); 
                    var result = await client.GetAsync("http://localhost:5246/api/User");

                    return await result.Content.ReadAsStringAsync();
                });

Reproduction Steps

To reproduce. Clone and run https://github.com/daniilzaonegin/ImpersonationTest:

  1. Call GET http://localhost:5086/api/UserRightsDelegating under windows account (1) -> user login name;
  2. Call GET http://localhost:5086/api/UserRightsDelegating under ANOTHER windows account (2) -> (1) user login name, not second.

If you disable connection pooling, when adding HttpClient (PooledConnectionLifetime = TimeSpan.Zero), then everything works as expected:

builder.Services.AddHttpClient(ServiceConsts.ImpersonateClientName)
    .ConfigurePrimaryHttpMessageHandler(_ =>
        new SocketsHttpHandler()
        {
            UseProxy = false,
            Credentials = CredentialCache.DefaultCredentials,
            PreAuthenticate = false,
            PooledConnectionLifetime = TimeSpan.Zero
        });

Expected behavior

WindowsIdentity.RunImpersonatedAsync should use credentials of the user, that is calling api right now, not the credentials of a previous api call.

Actual behavior

WindowsIdentity.RunImpersonatedAsync reuses the credentials of a previous api call.

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Net.Http untriaged New issue has not been triaged by the area owner labels Dec 26, 2021
@ghost
Copy link

ghost commented Dec 26, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Hi!

This issue is the continuation of issue #58033.

I've made a sample project to reproduce the error https://github.com/daniilzaonegin/ImpersonationTest.
WindowsIdentity.RunImpersonatedAsync reuses the credentials of previous api call.

            var result = await WindowsIdentity.RunImpersonatedAsync(windowsIdentity.AccessToken,
                async () =>
                {
                    HttpClient? client =
                        _clientFactory.CreateClient(ServiceConsts.ImpersonateClientName); 
                    var result = await client.GetAsync("http://localhost:5246/api/User");

                    return await result.Content.ReadAsStringAsync();
                });

Reproduction Steps

To reproduce. Clone and run https://github.com/daniilzaonegin/ImpersonationTest:

  1. Call GET http://localhost:5086/api/UserRightsDelegating under windows account (1) -> user login name;
  2. Call GET http://localhost:5086/api/UserRightsDelegating under ANOTHER windows account (2) -> (1) user login name, not second.

If you disable connection pooling, when adding HttpClient (PooledConnectionLifetime = TimeSpan.Zero), then everything works as expected:

builder.Services.AddHttpClient(ServiceConsts.ImpersonateClientName)
    .ConfigurePrimaryHttpMessageHandler(_ =>
        new SocketsHttpHandler()
        {
            UseProxy = false,
            Credentials = CredentialCache.DefaultCredentials,
            PreAuthenticate = false,
            PooledConnectionLifetime = TimeSpan.Zero
        });

Expected behavior

WindowsIdentity.RunImpersonatedAsync should use credentials of the user, that is calling api right now, not the credentials of a previous api call.

Actual behavior

WindowsIdentity.RunImpersonatedAsync reuses the credentials of a previous api call.

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: daniilzaonegin
Assignees: -
Labels:

area-System.Net.Http, untriaged

Milestone: -

@geoffkizer
Copy link
Contributor

@wfurt can you take a look?

@wfurt
Copy link
Member

wfurt commented Dec 28, 2021

sure. I'm not sure how Kestrel and factory plays into this but having specific example should be sufficient to see what is going on.

@wfurt
Copy link
Member

wfurt commented Dec 31, 2021

I could not get the demo working. It is failing with

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
         at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResul

This is not my area and perhaps @Tratcher would have some insight.

I modified it to use Negotiate scheme:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-6.0&tabs=visual-studio

With that I can access the UserRightsDelegating url and based on the user I pass in I get

curl -v --negotiate -u test:* http://localhost:5086/api/UserRightsDelegating
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Fri, 31 Dec 2021 21:41:33 GMT
< Server: Kestrel
< Transfer-Encoding: chunked
<
WOKNA10\test* Closing connection 0

or

curl -v --negotiate -u test1:* http://localhost:5086/api/UserRightsDelegating

< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Fri, 31 Dec 2021 21:42:17 GMT
< Server: Kestrel
< Transfer-Encoding: chunked
<
WOKNA10\test1* Closing connection 0

e.g. the response content does respect the used user for first service. (I did not change the timeout)

@ghost
Copy link

ghost commented Dec 31, 2021

This issue has been marked needs more info since it may be missing important information. Please refer to our contribution guidelines for tips on how to report issues effectively.

@daniilzaonegin
Copy link
Author

daniilzaonegin commented Jan 2, 2022

@wfurt, this solution works only on IIS/IIS Express. I had an issue on IIS and posted same code that is used in our application. So when you run it from visual studio 2022 on IIS Express, there will be no errors.

@ghost ghost added needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration and removed needs more info labels Jan 2, 2022
@daniilzaonegin
Copy link
Author

daniilzaonegin commented Jan 2, 2022

I tested it with curl, it really respects the credential change. I think you can close the issue, everything works as expected.
The problem was, that before I tested it with Postman and there's an issue there (by default it doesn't close the connection and reuses the credentials).
https://community.postman.com/t/postman-ntlm-authentication-with-different-users-credentials/2452

@wfurt
Copy link
Member

wfurt commented Jan 4, 2022

Good to know. I have no experience with Postman. I tried it, but eventually fall-back to tools I'm familiar with.

@wfurt wfurt closed this as completed Jan 4, 2022
@karelz karelz added this to the 7.0.0 milestone Jan 4, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 3, 2022
@karelz karelz removed needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration untriaged New issue has not been triaged by the area owner labels Oct 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants