OAuth2 и OpenID Подключитесь к angular-oauth2-oidc. Почему JWT сохраняются в локальном хранилище, но (на самом деле) не используются?

Для проекта я использую эту библиотеку: angular-oauth2-oidc для поддержки в OAuth 2 и OpenId Connect (OIDC) в Angular.

У меня все настроено и все работает нормально.

Файл MainComponent:

export class MainComponent implements OnInit {

  constructor() {
    this.configureSSO();
  }

  configureSSO() {
    this.oAuthService.configure(authConfig);
    this.oAuthService.tokenValidationHandler = new JwksValidationHandler();

    this.oAuthService.loadDiscoveryDocumentAndTryLogin().then(() => {
      // the lib received the access_token as well as the id_token, if it was requested. 
      // If there is an id_token, the lib validated it.
      // DO STUFF WITH TOKEN HERE
    });
  }
}

Файл authConfig:

import {AuthConfig} from 'angular-oauth2-oidc';

export const authConfig: AuthConfig = { /...SOME CONFIG HERE .../ }

Файл AuthGuard:

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private oAuthService: OAuthService) {
  }

  canActivate(): boolean {
    if(this.oAuthService.hasValidIdToken()){
      return true;
    }
    return false;
  }
}

После успешного входа на сайт поставщиков OIDC я вижу, что access_token сохраняется в хранилище сеансов моего локального браузера:

введите описание изображения здесь

Все это работает отлично, НО, если я теперь перейду к изменению токена в хранилище сеансов, я все еще смогу попасть в свои защищенные маршруты. Хотя access_token был переделан. То же самое при изменении id_token.

-> AuthGuard по-прежнему позволяет мне переходить на мои защищенные маршруты.

Может ли кто-нибудь просветить меня, как это возможно?

Я не могу найти ничего о том, как это делается внутри, в документации angular-oauth2-oidc

Я совершенно уверен, что это НЕ ошибка реализации, а скорее то, что библиотека сохраняет токен где-то внутри и вместо этого использует неизмененный токен, так как все остальное работает, как ожидалось, отлично.

Но ПОЧЕМУ все равно сохранять токен в хранилище сеансов, если он (на самом деле) не используется?!?

Более:

Если я на самом деле удалю весь токен из хранилища, все заблокированные маршруты будут заблокированы - это хорошо :)! То же самое происходит, когда я изменяю время истечения срока действия (exp) внутри JWT на что-то до фактического времени. Итак, эти две проверки на самом деле работают нормально, но при изменении access_token или id_token AuthGuard по-прежнему получает действительный токен ... (может быть, изнутри библиотеки?!?)

Я думаю, что есть кое-что, чего я не понимаю в JWT в целом, и почему они даже сохраняются в локальном / сессионном хранилище, или почему их изменение не имеет никакого эффекта ...

Любые ответы приветствуются.


person DigitalJedi    schedule 12.04.2020    source источник


Ответы (1)


В базовом сценарии библиотека предполагает, что каждый бит JavaScript «хорошо работает» с хранилищем сеанса, эффективно рассматривая его как частное хранилище для библиотеки. Если вы хотите очистить логин, чтобы охранники маршрута могли его забрать, вам не следует вставлять в хранилище самостоятельно, а вместо этого вызывать logout в службе. Этот .

По сути, если вы удалите из sessionStorage (или localStorage, если вы его используете) материал, который «принадлежит» библиотеке, вы нарушите его.

Ваши охранники - это проблема приложения, и они должны иметь возможность доверять библиотеке (которая, в свою очередь, должна доверять хранилищу), чтобы определить, что произойдет, если библиотека сочтет пользователя «вошедшим в систему».

Сама библиотека обычно вообще не использует токены, если вы не укажете это. Наиболее распространенный случай - предоставить module config, чтобы убедиться, что access_token отправляется вместе с вашим API. Например.:

{ 
  provide: OAuthModuleConfig,
  useValue: {
    resourceServer: {
      allowedUrls: ['https://example.org/my-api'],
      sendAccessToken: true
    }
  }
}

Теперь, если вы хотите «защитить» от вмешательства другого кода в хранилище библиотеки, вы можете provide свою собственную реализацию OAuthStorage, например:

function storageFactory() {
  const privateStore = {};

  return {
    getItem(key) { return privateStore[key]; }
    removeItem(key) { delete privateStore[key]; }
    setItem(key, data) { privateStore[key] = data; }
  };
}
{ provide: OAuthStorage, useFactory: storageFactory }

Я использую аналогичный метод для предоставления localStorage вместо sessionStorage в моем образце репозитория.

person Jeroen    schedule 12.04.2020
comment
Спасибо за ответ! Я думаю, что я уже много читал о ваших комментариях на страницах github, я думаю :) У меня все еще есть один вопрос, который нужно спросить: Итак, если библиотека полагается на сеанс / локальное хранилище, почему она все еще сообщает hasValidIdToken () = == true, если фактически токен в хранилище больше не действителен (после его изменения вручную)? Думаю, это единственное, чего я не понимаю ... И да, я позвоню logout, когда действительно захочу удалить токен. Было больше любопытно просто узнать, почему библиотека все еще сообщает hasValidIdToken () == true даже в тех случаях, когда это больше не должно быть правдой. - person DigitalJedi; 13.04.2020
comment
Я предлагаю проверка исходного кода и, возможно, прохождение его с помощью отладчика для вашего конкретного сценария, чтобы понять, почему он по-прежнему возвращает true в вашем приложении при определенных обстоятельствах. Удачи! - person Jeroen; 13.04.2020
comment
Привет, @Jeroen, извини, что побеспокоил тебя. Как вы думаете, можете ли вы взглянуть на этот вопрос stackoverflow.com/questions/62588191/ - person eddy; 26.06.2020