IdentityServer3 за перенаправлением балансировщика нагрузки внешнему провайдеру для проверки подлинности Windows не работает

Я экспериментировал с IdentityServer 3, и поэтому он работал без проблем, пока я не развернул его за балансировкой нагрузки.

Я не могу использовать IdentityServer 4, потому что мне еще не разрешено использовать dotNet Core.

Я настроил свой IIS, чтобы разрешить аутентификацию Windows и анонимность, и вот что я до сих пор придумал:

Запускать:

public class Startup
{
    X509Certificate2 Cert = Certificate.Load();
    string baseURL = ConfigurationManager.AppSettings["IdServBaseURL"];

    public void Configuration(IAppBuilder app)
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Email("[email protected]", 
                new string[] { "[email protected]" }, 
                "smtp.company.com", 
                restrictedToMinimumLevel: LogEventLevel.Error)
            .CreateLogger();

        app.Use(async (context, next) =>
        {
            try
            {
                await next();
            }
            catch (Exception ex)
            {
                Log.Error(ex, "OWIN Exception");
            }
        });

        var factory = Factory.Configure("MyConnectionString");

        factory.UserService = new Registration<IUserService>(typeof(ExternalRegistrationUserService));

        var options = new IdentityServerOptions
        {
            SigningCertificate = Cert,
            RequireSsl = false,
            Factory = factory,
            AuthenticationOptions = new AuthenticationOptions
            {
                EnableLocalLogin = false,
                EnableSignOutPrompt = false,
                EnablePostSignOutAutoRedirect = true,
                PostSignOutAutoRedirectDelay = 0,
                IdentityProviders = ConfigureIdentityProviders
            },
            IssuerUri = baseURL,
            PublicOrigin = ((new Uri(baseURL))).GetLeftPart(UriPartial.Authority),
            SiteName = "My Id Server"
        };

        app.Map("/windows", ConfigureWindowsTokenProvider);

        app.UseIdentityServer(options);
    }

    private void ConfigureWindowsTokenProvider(IAppBuilder app)
    {
        app.Use(async (context, next) =>
        {
            try
            {
                await next();
            }
            catch (Exception ex)
            {
                Log.Error(ex, "OWIN Exception");
            }
        });

        app.UseWindowsAuthenticationService(new WindowsAuthenticationOptions
        {
            IdpReplyUrl = baseURL + "/was",
            SigningCertificate = Cert,
            EnableOAuth2Endpoint = true
        });
    }

    private void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
    {
        app.Use(async (context, next) =>
        {
            try
            {
                await next();
            }
            catch (Exception ex)
            {
                Log.Error(ex, "OWIN Exception");
            }
        });

        var wsFederation = new WsFederationAuthenticationOptions
        {
            AuthenticationType = "windows",
            Caption = "Windows",
            SignInAsAuthenticationType = signInAsType,

            MetadataAddress = baseURL + "/windows",
            Wtrealm = "urn:idsrv3"
        };
        app.UseWsFederationAuthentication(wsFederation);
    }
}

Фабрика:

public class Factory
{
    public static IdentityServerServiceFactory Configure(string connString)
    {
        var efConfig = new EntityFrameworkServiceOptions
        {
            ConnectionString = connString
        };

        var cleanup = new TokenCleanup(efConfig, 10);
        cleanup.Start();

        var factory = new IdentityServerServiceFactory();

        factory.RegisterConfigurationServices(efConfig);
        factory.RegisterOperationalServices(efConfig);

        factory.ConfigureClientStoreCache();
        factory.ConfigureScopeStoreCache();

        return factory;
    }
}

Служба временного пользователя:

public class ExternalRegistrationUserService : UserServiceBase
{
    public class CustomUser
    {
        public string Subject { get; set; }
        public string Provider { get; set; }
        public string ProviderID { get; set; }
        public List<Claim> Claims { get; set; }
    }

    public static List<CustomUser> Users = new List<CustomUser>();

    public override Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
    {
        var user = Users.SingleOrDefault(x => x.Provider == context.ExternalIdentity.Provider && x.ProviderID == context.ExternalIdentity.ProviderId);
        string name = "Unknown";
        if (user == null)
        {
            var nameClaim = context.ExternalIdentity.Claims.First(x => x.Type == Constants.ClaimTypes.Name);
            if (nameClaim != null) name = nameClaim.Value;

            user = new CustomUser
            {
                Subject = Guid.NewGuid().ToString(),
                Provider = context.ExternalIdentity.Provider,
                ProviderID = context.ExternalIdentity.ProviderId,
                Claims = new List<Claim> { new Claim(Constants.ClaimTypes.Name, name) }
            };
            Users.Add(user);
        }

        name = user.Claims.First(x => x.Type == Constants.ClaimTypes.Name).Value;
        context.AuthenticateResult = new AuthenticateResult(user.Subject, name, identityProvider: user.Provider);
        return Task.FromResult(0);
    }

    public override Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var user = Users.SingleOrDefault(x => x.Subject == context.Subject.GetSubjectId());
        if (user != null)
        {
            var resultClaims = new List<Claim>();
            resultClaims.AddRange(user.Claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)));

            context.IssuedClaims = resultClaims;
        }

        return Task.FromResult(0);
    }
}

Когда я пытаюсь использовать его с localhost или с любого сервера, не сбалансированного по нагрузке, он работает нормально, как вы можете видеть в этом журнале:

[Information] Adding OAuth2 endpoint
[Information] Configuration done.
[Information] Welcome page requested - rendering
[Information] Clearing tokens
[Information] Permissions page requested
[Information] User not authenticated, redirecting to login
[Information] Redirecting to login page
[Information] Login page requested
[Information] local login disabled for the client
[Information] only one provider for client
[Information] redirecting to provider URL: "https://myserver.com/IdSrv/external?provider=windows&signin=b0f68735e23333b30cac91da12cf300c"
[Information] External login requested for provider: "windows"
[Information] Triggering challenge for external identity provider
[Information] Start WS-Federation metadata request
[Information] Start WS-Federation request
[Information] User is anonymous. Triggering authentication
[Information] Start WS-Federation request
[Information] Sign-in request
[Information] Creating WS-Federation signin response
[Information] Callback invoked from external identity provider
[Information] external user provider: "windows", provider ID: "S-1-5-21-xxxxx-xxxxxxxx-xxxxxxxx-xxxxxxx"
[Information] External identity successfully validated by user service
[Information] Calling PostAuthenticateAsync on the user service
[Information] issuing primary signin cookie
[Information] redirecting to: https://myserver.com/IdSrv/permissions
[Information] Permissions page requested
[Information] Rendering permissions page
[Information] Clearing tokens
[Information] Start token request
[Information] Secret id found: "client1"
[Information] Client validation success
[Information] Start token request validation
[Information] Start client credentials token request validation
[Information] Client credentials token request validation success
[Information] Token request validation success  {
  "ClientId": "client1",
  "ClientName": "Clien1",
  "GrantType": "client_credentials",
  "Scopes": "myscope",
  "Raw": {
    "client_id": "client1",
    "client_secret": "******",
    "scope": "myscope",
    "grant_type": "client_credentials"
  }
}
[Information] Creating token response
[Information] Processing token request
[Information] End token request
[Information] Returning token response.
[Information] Clearing tokens

Но как только я развертываю на серверах с балансировкой нагрузки все, что использует поток client_credentials, кажется, работает нормально, но все, что пытается аутентифицировать пользователей, перестает работать. Он больше не аутентифицирует пользователей. Вот журнал ошибок:

[Information] Welcome page requested - rendering
[Information] Permissions page requested
[Information] User not authenticated, redirecting to login
[Information] Redirecting to login page
[Information] Login page requested
[Information] local login disabled for the client
[Information] only one provider for client
[Information] redirecting to provider URL: "https://mybalancedserver.com/Idsrv/external?provider=windows&signin=dbe3e00a7490584e1568471b9ed48948"
[Information] External login requested for provider: "windows"
[Information] Triggering challenge for external identity provider
[Error] OWIN Exception
System.InvalidOperationException: IDX10803: Unable to create to obtain configuration from: 'https://mybalancedserver.com/Idsrv/windows'. ---> System.IO.IOException: Unable to get document from: https://mybalancedserver.com/Idsrv/windows ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   --- End of inner exception stack trace ---
   at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
   at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
   --- 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 ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.<GetDocumentAsync>d__0.MoveNext()
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.<GetDocumentAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Protocols.WsFederationConfigurationRetriever.<GetAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.<GetConfigurationAsync>d__3.MoveNext()
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.<GetConfigurationAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.WsFederation.WsFederationAuthenticationHandler.<ApplyResponseChallengeAsync>d__c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<TeardownAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MDCR.IdentityServer.Startup.<>c.<<ConfigureIdentityProviders>b__4_0>d.MoveNext() in C:\Startup.cs:line 110

[Information] External login requested for provider: "windows"
[Information] Triggering challenge for external identity provider

[Error] OWIN Exception
System.InvalidOperationException: IDX10803: Unable to create to obtain configuration from: 'https://mybalancedserver.com/Idsrv/windows'.
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.<GetConfigurationAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.WsFederation.WsFederationAuthenticationHandler.<ApplyResponseChallengeAsync>d__c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<TeardownAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MDCR.IdentityServer.Startup.<>c.<<ConfigureIdentityProviders>b__4_0>d.MoveNext() in C:\Startup.cs:line 110

[Information] External login requested for provider: "windows"
[Information] Triggering challenge for external identity provider

[Error] OWIN Exception
System.InvalidOperationException: IDX10803: Unable to create to obtain configuration from: 'https://mybalancedserver.com/Idsrv/windows'.
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.<GetConfigurationAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.WsFederation.WsFederationAuthenticationHandler.<ApplyResponseChallengeAsync>d__c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<TeardownAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MDCR.IdentityServer.Startup.<>c.<<ConfigureIdentityProviders>b__4_0>d.MoveNext() in C:\Startup.cs:line 110

Вы когда-нибудь догадывались об этом? Было ли это из-за неправильной конфигурации баланса нагрузки?

Steve 19.04.2019 18:17

Нет, @ Стив, я этого не делал. Закончилась маршрутизация вокруг балансировщика, который был взломан, но, по крайней мере, он работал

CubanTurin 20.05.2019 20:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
273
0

Другие вопросы по теме