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

Intermitted login issue even though the IdP logins were successful #437

Closed
razmy-hathy opened this issue Jan 14, 2022 · 15 comments
Closed

Comments

@razmy-hathy
Copy link

I observed some strange behaviour and not sure this is because there are some configuration needs to be done in owin middleware parameter section in the Startup.Auth.cs file. Please find below for the scenarios for further details.

I logged in to the application via the IdP and closed the browser without logging out from the application and from the Idp. I reopened the browser and tried to login again, but I was unable to login back to the application even though the browser was redirected from the IdP after a successful login with previous session acquired by the user. In this case, the user should be able to login without an issue.

To debug the application, I examined the owin openid connect intercept method (SecurityTokenValidated) and I checked the value for the “context.AuthenticationTicket.Identity.IsAuthenticated” variable. The value of the variable was true; however, in the controller the “User.Identity.IsAuthenticated” variable was false. This the issue causing the user not to login into the application.
Second scenario, I tried to login to the application with two browser instances in a same machine. One with incognito mode and another one with normal mode. I was able to login into only to one browser and was not able to login to the other browser although the IdP login was successful as I explained in the previous scenario.

However, the users can login into the application only after the IIS server restart. I have given below the code for OpenIdConnect configuration and the controller class. Please help me to find the issue.

Startup.Auth.cs

public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(ApplicationSignInManager.Create);
app.CreatePerOwinContext(ApplicationRoleManager.Create);

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Passive,
                // Sets the ClientId, authority, RedirectUri as obtained from web.config
                ClientId = clientId,
                Authority = authority,
                RedirectUri = redirectUri,
                PostLogoutRedirectUri = redirectUri,
                Scope = OpenIdConnectScope.OpenIdProfile,
                ClientSecret = clientSecret,
                UsePkce = true,
                SaveTokens = true,
                RedeemCode = true,
                // ResponseType is set to request the code id_token - which contains basic information about the signed-in user
                ResponseType = OpenIdConnectResponseType.Code,
                // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application
                // To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name
                // To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter
                TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true
                },

                // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    // Fired when authenticated faild
                    AuthenticationFailed = (context) =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("/Error/AuthErrorPage/?errormessage=" + context.Exception.Message);
                        return Task.FromResult(0);
                    },

                    SecurityTokenValidated = (context) =>
                    {
                        var identity = context.AuthenticationTicket.Identity;
                        string externalUserId = identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                        Claim emailClaim = identity.FindFirst("preferred_username");
                        // Remove the name identity to insert user id to it.
                        Claim nameIdentifier = identity.FindFirst(ClaimTypes.NameIdentifier);
                        identity.RemoveClaim(nameIdentifier);
                        if (emailClaim != null)
                        {
                            AppUser user = service.GetUserByEmail(emailClaim.Value);
                            externalUserId = user.ExternalUserId;
                        }
                        List<string> userRoles = service.GetUserRolesNames(externalUserId);
                        var appUser = service.GetUserByUserEXternalId(externalUserId);
                        if (appeUser == null)
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/Error/AuthErrorPage/?errormessage=" + "User does not exist in database");
                            return Task.FromResult(0);
                        }
                        var claims = new List<Claim>();
                        foreach (var role in userRoles)
                        {
                            claims.Add(new Claim(ClaimTypes.Role, role));
                        }
                        claims.Add(new Claim(ClaimTypes.Name, appUser.UserName));
                        claims.Add(new Claim(ClaimTypes.NameIdentifier, appUser.Id.ToString()));
                        identity.AddClaims(claims);

                        return Task.FromResult(0);
                    }
                }
            }
        );
    }

Controller

public class AuthController : Controller
{
       // GET: OpenIdConnectHome
       public ActionResult Index()
       {
          if (!User.Identity.IsAuthenticated){
              return View();
          } else {
             return RedirectToAction("Index", "Home");
          }
       }

    /// <summary>
    /// Send an OpenID Connect sign-in request.
    /// Alternatively, you can just decorate the SignIn method with the [Authorize] attribute
    /// </summary>
    public void SignIn()
    {
        if (!User.Identity.IsAuthenticated)
        {
            HttpContext.GetOwinContext().Authentication.Challenge(
                new AuthenticationProperties { RedirectUri = "/" },
                OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }
    }

    [Authorize]
    /// <summary>
    /// Send an OpenID Connect sign-out request.
    /// </summary>
    public ActionResult SignOut()
    {
        HttpContext.GetOwinContext().Authentication.SignOut(
                    CookieAuthenticationDefaults.AuthenticationType);
        return View();
    }

}
@razmy-hathy razmy-hathy changed the title Intermitted login issue even though the IdP is successful Intermitted login issue even though the IdP logins were successful Jan 14, 2022
@Tratcher
Copy link
Member

However, the users can login into the application only after the IIS server restart.

This is concerning, none of the server components are stateful, a restart shouldn't have changed anything. All of the login state is stored in cookies on the client.

There are some debugging steps you can try:

  1. Enable server logs and check for any errors: https://github.com/aspnet/AspNetKatana/wiki/Debugging#logging
  2. Run the server with the debugger attached and check for any first chance exceptions during the login.
  3. Capture a decrypted fiddler trace and share it privately (see the e-mail in my profile). We'd want to ensure the cookies are all flowing as expected.

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 17, 2022

@Tratcher
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config is this the location that I should include the log configuration for owin as given in the step 2

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 18, 2022

When I log for the first time to the application, I always get the below error message.

[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) +8036958
System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) +165

[IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) +305
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) +167

[WebException: The underlying connection was closed: An unexpected error occurred on a send.]
System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) +762
System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) +81

[HttpRequestException: An error occurred while sending the request.]
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.IdentityModel.Protocols.d__8.MoveNext() +702

[IOException: IDX20804: Unable to retrieve document from: '[PII is hidden]'.]
Microsoft.IdentityModel.Protocols.d__8.MoveNext() +1169
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.IdentityModel.Protocols.OpenIdConnect.d__3.MoveNext() +391
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.IdentityModel.Protocols.d__24.MoveNext() +865

[InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden]'.]
Microsoft.IdentityModel.Protocols.d__24.MoveNext() +1570
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.OpenIdConnect.d__10.MoveNext() +618
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.Infrastructure.d__40.MoveNext() +349
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.Infrastructure.d__39.MoveNext() +447
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.Infrastructure.d__34.MoveNext() +196
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.Infrastructure.d__5.MoveNext() +929
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__7.MoveNext() +197
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Security.Infrastructure.d__5.MoveNext() +735
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.AspNet.Identity.Owin.d__5.MoveNext() +439
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.AspNet.Identity.Owin.d__5.MoveNext() +439
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.AspNet.Identity.Owin.d__5.MoveNext() +439
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.AspNet.Identity.Owin.d__5.MoveNext() +439
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__7.MoveNext() +197
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__12.MoveNext() +192
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +118
System.Web.<>c__DisplayClass11_0.b__0() +41
System.Web.AsyncEventExecutionStep.InvokeEndHandler(IAsyncResult ar) +163
System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +115

However, after refreshing the browser , I can able to view the IdP login screen.

@Tratcher
Copy link
Member

Oh, interesting, it's failing to download your OIDC metadata on the first request. Is your server behind a proxy or something?

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 19, 2022 via email

@Tratcher
Copy link
Member

Sorry, I meant do outbound requests also go through an HTTP proxy? What's failing here is an outbound request for a resource.

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 19, 2022 via email

@Tratcher
Copy link
Member

Since this is an outbound networking failure you can try enabling the logs for the networking stack:
https://docs.microsoft.com/en-us/dotnet/framework/network-programming/how-to-configure-network-tracing

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 20, 2022 via email

@Tratcher
Copy link
Member

I would have expected that to go in the web.config, not the machine.config.

If this is an urgent issue you'll need to contact https://support.microsoft.com/. Github is not a great channel for debugging complex issues.

@razmy-hathy
Copy link
Author

razmy-hathy commented Jan 28, 2022 via email

@Tratcher
Copy link
Member

Tratcher commented Jan 31, 2022

Here are some key logs:

System.Net.Http Verbose: 0 : [40552] Entering
HttpClient#37489757::SendAsync(HttpRequestMessage#64828693: Method: GET,
RequestUri: '
http://169.254.169.254/metadata/instance/compute?format=json&api-version=2017-12-01',
Version: 1.1, Content: <null>, Headers:
{
  Metadata: True
})
System.Net Verbose: 0 : [40552] Entering
HttpWebRequest#10104599::HttpWebRequest(
http://169.254.169.254/metadata/instance/compute?format=json&api-version=2017-12-01#951510431
)
System.Net Information: 0 : [40552] RAS supported: True
System.Net Verbose: 0 : [40552] Entering
HttpWebRequest#10104599::HttpWebRequest(uri: '
http://169.254.169.254/metadata/instance/compute?format=json&api-version=2017-12-01',
connectionGroupName: '33711845')
System.Net.Http Information: 0 : [40552] Associating
HttpRequestMessage#64828693 with HttpWebRequest#10104599
System.Net Verbose: 0 : [27464] Entering
HttpWebRequest#10104599::BeginGetResponse()
System.Net.Http Verbose: 0 : [40552] Exiting
HttpClientHandler#33711845::SendAsync() -> Task`1#51288387
System.Net Verbose: 0 : [27464] Entering
ServicePoint#35320229::ServicePoint(169.254.169.254:80)
System.Net.Http Verbose: 0 : [40552] Exiting
HttpClient#37489757::SendAsync() -> Task`1#51288387
System.Net Information: 0 : [27464] Associating HttpWebRequest#10104599
with ServicePoint#35320229
System.Net Information: 0 : [27464] Associating Connection#17653682 with
HttpWebRequest#10104599
System.Net.Sockets Verbose: 0 : [27464] Entering
Socket#42194754::Socket(AddressFamily#2)
System.Net.Sockets Verbose: 0 : [27464] Exiting Socket#42194754::Socket()
System.Net.Sockets Verbose: 0 : [27464] Entering
Socket#15688314::Socket(AddressFamily#23)
System.Net.Sockets Verbose: 0 : [27464] Exiting Socket#15688314::Socket()
System.Net.Sockets Verbose: 0 : [27464] Entering
DNS::TryInternalResolve(169.254.169.254)
System.Net.Sockets Verbose: 0 : [27464] Entering
Socket#42194754::BeginConnectEx()
System.Net.Sockets Verbose: 0 : [27464] Entering
Socket#42194754::InternalBind(0.0.0.0:0#0)
System.Net.Sockets Verbose: 0 : [27464] Exiting
Socket#42194754::InternalBind()
System.Net.Sockets Verbose: 0 : [27464] Exiting
Socket#42194754::BeginConnectEx() -> ConnectOverlappedAsyncResult#52307948
System.Net Verbose: 0 : [27464] Exiting
HttpWebRequest#10104599::BeginGetResponse() -> ContextAwareResult#40535505
System.Net.Sockets Verbose: 0 : [30232] Entering
Socket#42194754::EndConnect(ConnectOverlappedAsyncResult#52307948)
System.Net.Sockets Verbose: 0 : [30232] Entering
Socket#42194754::InternalEndConnect(ConnectOverlappedAsyncResult#52307948)
System.Net.Sockets Error: 0 : [30232]
Socket#42194754::UpdateStatusAfterSocketError() - NetworkUnreachable
System.Net.Sockets Error: 0 : [30232] Exception in
Socket#42194754::InternalEndConnect - A socket operation was attempted to
an unreachable network 169.254.169.254:80.
System.Net.Sockets Verbose: 0 : [30232] Entering Socket#42194754::Dispose()
System.Net.Sockets Verbose: 0 : [30232] Entering Socket#15688314::Dispose()
System.Net Error: 0 : [30232] Exception in HttpWebRequest#10104599:: -
Unable to connect to the remote server.
[30232] Entering HttpWebRequest#10104599::EndGetResponse()
System.Net Error: 0 : [30232] Exception in
HttpWebRequest#10104599::EndGetResponse - Unable to connect to the remote
server.
System.Net.Http Error: 0 : [30232] Exception in
HttpClientHandler#33711845::SendAsync - Unable to connect to the remote
server.
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
System.Net.Http Error: 0 : [30232] HttpClient#37489757::SendAsync() - An
error occurred while sending HttpRequestMessage#64828693.
System.Net.Http.HttpRequestException: An error occurred while sending the
request. ---> System.Net.WebException: Unable to connect to the remote
server ---> System.Net.Sockets.SocketException: A socket operation was
attempted to an unreachable network 169.254.169.254:80
   at System.Net.Sockets.Socket.InternalEndConnect(IAsyncResult asyncResult)
   at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
Socket s4, Socket s6, Socket& socket, IPAddress& address,
ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
System.Net Verbose: 0 : [30232] Entering HttpWebRequest#10104599::Abort()
System.Net Error: 0 : [30232] Exception in HttpWebRequest#10104599:: - The
request was aborted: The request was canceled..
System.Net Verbose: 0 : [30232] Exiting HttpWebRequest#10104599::Abort()
System.Net.Sockets.SocketException: A socket operation was
attempted to an unreachable network 169.254.169.254:80

169.254.169.254 is not a valid address on most networks, it's a default address assigned when the DHCP server can't be contacted. Why is that being given as your metadata address / Authority?
https://dfarq.homeip.net/what-is-a-169-ip-address/

@pergardebrink
Copy link

169.254.169.254 is not a valid address on most networks, it's a default address assigned when the DHCP server can't be contacted. Why is that being given as your metadata address / Authority?
https://dfarq.homeip.net/what-is-a-169-ip-address/

That looks like the Azure Instance Metadata Service call. Maybe just some telemetry code that is part of the application?
https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux

@razmy-hathy
Copy link
Author

localhost-working-har.txt
localhost-not wokrin-har.txt

I have attached two http archive take during the testing for the below scenario.
I tried to login to the application with two browser
instances in the same machine. One with incognito mode and another one with
normal mode. I was able to login into only one browser and was not able to
login to the other browser although the IdP login was successful as I
explained in the previous scenario. If you could help me on this issue that
would be greatly appreciated.

@razmy-hathy
Copy link
Author

razmy-hathy commented Feb 9, 2022

Thanks guys for your support in this issue. I figured out the fix for the issue by of going through the comment given in the #381 by @Tratcher and also the following link suggested https://github.com/aspnet/AspNetKatana/wiki/System.Web-response-cookie-integration-issues#workarounds
Below is the code fix for the problem.

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
AuthenticationMode = AuthenticationMode.Active,
CookieName = ".Net." + CookieAuthenticationDefaults.AuthenticationType,
ExpireTimeSpan = TimeSpan.FromMinutes(5),
CookieManager = new SystemWebCookieManager()
});
I fix the issue by including CookieManager = new SystemWebCookieManager() statement . However, I used the other parameters for other configurations.

@ghost ghost locked as resolved and limited conversation to collaborators Mar 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants