Identity Server 4 перенаправление входа в систему не работает только в chrome - PullRequest
0 голосов
/ 19 марта 2020

Я использую идентификационный сервер 4. Пусть он называется «auth-server», запущенный на. net core 3.1. после перенаправления на сервер авторизации выполняется angular проверка подлинности запроса приложения и предоставление учетных данных для отправки имени входа, которое не перенаправляется обратно в клиентское приложение. проблема только в браузере chrome (firefox & edge работает нормально) я вижу запрос перенаправления - URL запроса: http://localhost: 5000 / connect / authorize / callback? client_id = takbull- clientapp-dev & redirect_uri = http% 3A% 2F% 2Flocalhost% 3A4200% 2Fauth-обратный вызов% 2F & response_type = id_token% 20token & scope = openid% 20profile% 20email% 20takbull% 20takbull.api & state = d3010be0612245 5 5 5 5 5 5 5 5 8 5 5 6 6 8 8 68 5 6 5 8 8 8 6 5 8 8 8 6 5 8 8 8 6 6 8 8 8 6 8 8 8 8 8 8 8 8 8 8 8 5 5 6 6 8 8 8 8 8 5 5 8 8 8 8 8 6 5 6 8 8 8 8 8 8 5 5 8 8 85 6 6 8 8 8 8 5 6 8 8 6 8 8 5 6 8 8 6 6 8 8 6 6 8 8 8 6 6 8 8 6 6 8 8 8 6 6 8 8 8 6 6 8 8 8 6 6 8 8 8 6 6 8 8 8 6 6 8 8 для создания для 69 * вернуться на страницу входа Конгиг клиента:

 public static IEnumerable<Client> GetClients()
    {

        return new List<Client>(){
                new Client() {
                RequireConsent =false,
                RequireClientSecret = false,
                ClientId = "takbull-clientapp-dev",
                ClientName = "Takbull Client",
                AllowedGrantTypes = GrantTypes.ImplicitAndClientCredentials,
                AllowedScopes = new List<string>{IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Email,IdentityServerConstants.StandardScopes.Profile,"takbull","takbull.api" },
                // where to redirect to after login
                RedirectUris = new List<string>(){
                        "http://localhost:4200/auth-callback/",
                        "http://localhost:4200/silent-refresh.html",
                    },
                //TODO: Add Production URL
                // where to redirect to after logout
                PostLogoutRedirectUris =new List<string>() {
                       "http://localhost:4200"
                    },
                AllowedCorsOrigins = {"http://localhost:4200"},
                AllowAccessTokensViaBrowser = true,
                AccessTokenLifetime = 3600,
                AlwaysIncludeUserClaimsInIdToken = true
            },

        };
    }

Код входа:

 [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginInputModel model, string button)
    {
        // check if we are in the context of an authorization request
        var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

        // the user clicked the "cancel" button
        if (button != "login")
        {
            if (context != null)
            {
                // if the user cancels, send a result back into IdentityServer as if they 
                // denied the consent (even if this client does not require consent).
                // this will send back an access denied OIDC error response to the client.
                await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);

                // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                if (await _clientStore.IsPkceClientAsync(context.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
                }

                return Redirect(model.ReturnUrl);
            }
            else
            {
                // since we don't have a valid context, then we just go back to the home page
                return Redirect("~/");
            }
        }

        if (ModelState.IsValid)
        {
            // validate username/password against in-memory store
            var ValidResp = await _users.ValidateCredentials(model.Username, model.Password);
            if (ValidResp.LogInStatus == LogInStatus.Success)
            {
                var user = _users.FindByUsername(model.Username);
                //await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username));
                await _events.RaiseAsync(new UserLoginSuccessEvent(user.Email, user.UserId.ToString(), user.Email));

                // only set explicit expiration here if user chooses "remember me". 
                // otherwise we rely upon expiration configured in cookie middleware.
                AuthenticationProperties props = null;
                if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                {
                    props = new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTimeOffset.Now.Add(AccountOptions.RememberMeLoginDuration)
                    };
                };

                // issue authentication cookie with subject ID and username
                //await HttpContext.SignInAsync(user.SubjectId, user.Username, props);
                // issue authentication cookie with subject ID and username
                await HttpContext.SignInAsync(user.UserId.ToString(), user.FirstName + " " + user.LastName, props, _users.GetClaims(user).ToArray());

                if (context != null)
                {
                    if (await _clientStore.IsPkceClientAsync(context.ClientId))
                    {
                        // if the client is PKCE then we assume it's native, so this change in how to
                        // return the response is for better UX for the end user.
                        return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
                    }

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    return Redirect(model.ReturnUrl);
                }

                // request for a local page
                if (Url.IsLocalUrl(model.ReturnUrl))
                {
                    return Redirect(model.ReturnUrl);
                }
                else if (string.IsNullOrEmpty(model.ReturnUrl))
                {
                    return Redirect("~/");
                }
                else
                {
                    // user might have clicked on a malicious link - should be logged
                    throw new Exception("invalid return URL");
                }
            }

            await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, ValidResp.ResponseDescription));
            ModelState.AddModelError(string.Empty, ValidResp.ResponseDescription);
        }

        // something went wrong, show form with error
        var vm = await BuildLoginViewModelAsync(model);
        return View(vm);
    }

Ответы [ 2 ]

1 голос
/ 26 марта 2020

У меня была похожая проблема с IdentityServer4 на NET Core 2.2. Ваша проблема может быть связана с этими критическими изменениями в новых версиях браузеров, таких как Chrome или Firefox:

https://docs.microsoft.com/en-gb/dotnet/core/compatibility/3.0-3.1#http -browser-samesite-changes-воздействие-аутентификация

Для меня рабочим решением было отключить конфигурацию SameSite для файлов cookie. Такая возможность для. NET Core 2.2 описана здесь:

https://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1

(если ваше решение включено. NET Core 3.1, то в коде ниже вместо использования (SameSiteMode) (- 1) следует использовать SameSiteMode.Unspecified )

FIX: в Startup.cs файл в ConfigureServices метод, сразу после создания IdentityServerBuilder ...

var builder = services.AddIdentityServer(options =>
            {....});

... Я добавил следующее изменение конфигурации:

builder.Services.ConfigureExternalCookie(options => {
   options.Cookie.IsEssential = true;
      options.Cookie.SameSite = (SameSiteMode)(-1); //SameSiteMode.Unspecified in .NET Core 3.1
   });

builder.Services.ConfigureApplicationCookie(options => {
   options.Cookie.IsEssential = true;
      options.Cookie.SameSite = (SameSiteMode)(-1); //SameSiteMode.Unspecified in .NET Core 3.1
});
0 голосов
/ 19 апреля 2020

В Google Chrome будет отображаться консольное ограничение, и вашему серверу идентификации не удалось перенаправить в клиентское приложение для Chrome версии 80.

Повар ie, связанный с ресурсом, был установлен с SameSite = Нет, но без Безопасного. Он был заблокирован, так как Chrome теперь доставляет только куки с пометкой SameSite = None, если они также помечены как безопасные. Вы можете просмотреть файлы cookie в инструментах разработчика в разделе «Приложение»> «Хранилище»> «Файлы cookie» и просмотреть более подробную информацию по адресу https://www.chromestatus.com/feature/5633521622188032.

. Чтобы исправить это, необходимо внести изменения, указанные в приведенной ниже ссылке -

https://www.thinktecture.com/en/identity/samesite/prepare-your-identityserver/

ПРИМЕЧАНИЕ. Для. Net Core 2.2, установите SameSite = (SameSiteMode) (- 1), Для. Net Core 3.0 или выше, set SameSite = SameSiteMode.Unspecified

Кроме того, для Chrome 80 версии добавьте это дополнительное условие -

 if ( userAgent.Contains("Chrome/8"))
            {
                return true;
            }

Пожалуйста, примите этот ответ, если исправлена ​​ошибка для Chrome.

...