Перенаправление вызова .NET Core OIDC не работает с интерфейсом Angular

Я пытаюсь реализовать бэкэнд/бэкэнд токенов для шаблона внешнего интерфейса (мой интерфейс — Angular v18). Я хочу, чтобы мой интерфейс был тупым и не имел никаких знаний об обработке токенов. У меня есть веб-API ASP.NET Core 8, который настраивает конфигурацию OIDC следующим образом:

//... other code removed for brevity
builder.Services.AddAuthentication.AddOpenIdConnect(
    OpenIdConnectDefaults.AuthenticationScheme,
    opts =>
    {
        opts.Authority = builder.Configuration["Authority"];
        opts.ClientId = builder.Configuration["ClientId"];
        opts.ClientSecret = builder.Configuration["ClientSecret"];
        opts.CallbackPath = "/signin-oidc";
        opts.ResponseType = "code";
        opts.UsePkce = true;

        if (builder.Environment.IsDevelopment())
        {
            opts.RequireHttpsMetadata = false;
        }

        opts.GetClaimsFromUserInfoEndpoint = true;
        opts.ClaimActions.MapAll();

    });

С помощью следующего промежуточного программного обеспечения, которое проверяет наличие определенного файла cookie, который, если его нет, инициирует запрос:

app.Use(
async (context, next) =>
{
    if (!context.Request.Cookies.ContainsKey(AuthConstants.CookieSessionKey))
    {
        await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
    }
    else
    {
        await next.Invoke(context);
    }
});

Весь процесс работает, если я вызываю конечную точку в своем API непосредственно из браузера, но НЕ, если я пытаюсь вызвать ее из приложения Angular, например:

this.http.get<UserSession>("https://localhost:7030/.well-known/bff-getsessioninfo")
    .subscribe(resp => {
        console.info(resp);
    })

Вместо этого серверная часть возвращает 200, и Angular пытается десериализовать ответ, но ему это не удается, поскольку это HTML-код страницы входа в IdP.

Синтаксическая ошибка: неожиданный токен '<', " <!DOCTYPE "... недопустимый JSON в JSON.parse

Мой ожидаемый поток:

  1. Фронтенд пытается получить информацию о сеансе пользователя
  2. Серверная часть видит неаутентифицированный запрос из-за отсутствия файла cookie сеанса.
  3. Бэкэнд запускает задачу OIDC
  4. Перенаправление к IdP для входа в систему
  5. Перенаправление в мой бэкэнд с токенами доступа
  6. Отправьте информацию о сеансе пользователя обратно в мой угловой интерфейс с набором файлов cookie.

Почему он не перенаправляется правильно при вызове из Angular?

Это ожидаемый результат: когда вы используете http.get, это встроенная функция, которая не будет перенаправляться, вам нужно проанализировать результат, а затем перенаправить на страницу, обычно мы не будем делать это внутри метода http.get, мы проверим это, когда пользователь впервые получит доступ к любой странице, которая не столкнется с этой ошибкой, внутри метода http.get.

Brando Zhang 31.07.2024 09:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, чтобы узнать, вошел ли пользователь в систему или нет, вам нужно выполнить HTTP-запрос GET, который ответит кодом состояния 200, если пользователь аутентифицирован или 30x не аутентифицирован.

Это не идеально, и если вы используете Angular HttpClient, вы не сможете узнать, произошло перенаправление или нет. Поскольку браузер следует за перенаправлением под капотом, и когда он достигает Angular, ответом является 200 перенаправленной страницы. Итак, вам придется сделать несколько хаков , чтобы это узнать. Вместо того, чтобы определить, произошло ли перенаправление или нет.

Лучшим сценарием было бы иметь правильный API на внутренней стороне, который возвращает код состояния 200 или 401/403 в зависимости от того, аутентифицирован ли пользователь или нет. OpenID Connect действительно определяет конечную точку UserInfo в своих спецификациях для этой цели. Поэтому, если ваш провайдер OpenID Connect соответствует спецификации, он должен предоставить эту конечную точку.

В любом случае, мы все знаем, что мир далек от идеала. Так что, если вы не можете это изменить, вы можете использовать один из этих хаков или новый API выборки

При этом вы можете указать браузеру не следовать перенаправлениям при выполнении HTTP-запроса из вашего кода. Затем вы можете узнать, остановлен ли запрос из-за отсутствия перенаправлений (пользователь не аутентифицирован) или все прошло хорошо (пользователь аутентифицирован).

Вот пример кода:

from(
  fetch('https://mock.httpstatus.io/302', { redirect: 'manual' }),
).subscribe((response) => {
  if (response.ok) {
    console.info('All went good. User is authenticated')
    return
  }
  if (!response.ok && response.type === 'opaqueredirect') {
    console.info(
      'A redirect was replied. User is probably not authenticated',
    )
    return
  }
  console.info('Something weird happened')
})

Имейте в виду, что если вы используете рендеринг на стороне сервера (SSR) или предварительный рендеринг/генерацию статического сайта (SSG), вам также необходимо, чтобы fetch был доступен в Node.js. Чтобы запустить тот же код на сервере.

Экспериментальная поддержка fetch в Node.js LTS была добавлена ​​в версии 16, но ее необходимо включить с помощью флага CLI. Начиная с версии 18, флаг CLI не требуется. В v21 всё стабильно. Поэтому, когда v22 станет LTS, это будет первый Node.js LTS, в котором этот API также будет стабильным. Вы также можете использовать полифил , если у вас нет версии Node.js, поддерживающей fetch.

Angular позволяет использовать скрытую выборку для HttpClient API. Однако еще не вся мощь fetch достигла поверхности HttpClient API.

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