Недавно они выпустили библиотеку аутентификации Microsoft для JS. Я сам писал свои собственные httpIinterceptors, службу аутентификации и поток обработки. Это действительно работало!
Пока нация огня не напала.
Нет, просто прикалываюсь. Это работает, пока мне не нужно динамически загружать конфигурацию для MSAL. Ветка с проблемами на github началась здесь. В частности, мы обсудим, как получить вашу конфигурацию с сервера/API для загрузки вашего углового SPA.
Давайте углубимся в детали.
В этом потоке предлагается решение об использовании APP INITIALIZER для координации получения вашей конфигурации с использованием API. В какой-то момент документация MSAL указывает вам на использование конфигурации, как показано ниже, для внедрения в поставщиков APP MODULE.
providers: [
MsalService,
{
provide: APP_INITIALIZER,
useFactory: initConfiguration,
deps: [ConfigService],
multi: true
}, {
provide: MSAL_CONFIG,
useValue: getConfig()
}, {
provide: MSAL_Angular_CONFIG,
useValue: getAngularConfig()
},
]
Если вы знакомы с настройками наших провайдеров в Angular, по сути, здесь происходит то, что функция useFactory и функция useValue вызываются одновременно. Итак, теперь вы должны координировать свои действия, чтобы в этом примере функция initConfiguration() вызывалась до getConfig() и getAngularConfig().
Вы можете делать некоторые причудливые трюки с наблюдаемыми/обещаниями и ждать, пока initConfiguration() скоординирует это. Его сложно писать и читать, особенно если вы не гуру в RXJS или у вас мало опыта в промисах.
Итак, давайте перейдем к реальному решению.
Перейдите к файлу main.ts в приложении. Это файл, который отвечает за загрузку вашего углового приложения в AppModule. Это будет выглядеть примерно так.
platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err));
Давайте обновим это, чтобы внедрить сюда наших пользовательских провайдеров.
platformBrowserDynamic([
{
provide: MSAL_CONFIG,
useValue: getConfig()
}, {
provide: MSAL_Angular_CONFIG,
useValue: getAngularConfig()
},
]).bootstrapModule(AppModule)
.catch(err => console.error(err));
Все, что вам нужно знать о платформе BrowserDynamic, это то, что вы можете установить своих собственных поставщиков до загрузки приложения.
Для этого примера давайте просто предположим, что мы будем собирать clientId, Authority и protectedResourceMap с нашего сервера для загрузки нашего приложения.
В нашем случае мы будем использовать 1 вызов API для получения всех трех этих свойств. Поскольку мы вызываем getConfig() и getAngularConfig(), нам нужно использовать некоторые приемы, чтобы этот единый API давал ответы на 2 разные функции. Давайте начнем здесь.
Насколько я знаю, мы не можем использовать угловой DI, потому что это все до того, как все это будет настроено. Мы сделаем наш http-клиент, как указано выше. Я использую RXJS pipe share(), чтобы поделиться ответом, возвращаемым с сервера. Я также преобразовываю наблюдаемое в обещание, потому что мне не нужно, чтобы наблюдаемое было открытым все время.
function MSALConfigFactory(): Configuration { return { auth: { clientId: clientId, authority: authority, validateAuthority: false, redirectUri: window.location.origin + ‘/’, postLogoutRedirectUri: window.location.origin + ‘/’, navigateToLoginRequestUrl: true, }, cache: { cacheLocation: “localStorage”, storeAuthStateInCookie: isIE, // set to true for IE 11 }, }; } function MSALAngularConfigFactory(): MsalAngularConfiguration { return { popUp: !isIE, consentScopes: ["scopes"], unprotectedResources: ["https://www.microsoft.com/en-us/"], protectedResourceMap, extraQueryParameters: {} }; }
Эта часть довольно проста, мы загрузили наши свойства конфигурации как для MSAL Config, так и для Angular Config. Далее, давайте используем наше обещание.
promise.then((x: any) => { clientId = x.auth.clientId authority = x.auth.authority protectedResourceMap = x.protectedResourceMap platformBrowserDynamic([ {provide: MSAL_CONFIG,useFactory: MSALConfigFactory,}, {provide: MSAL_CONFIG_ANGULAR,useFactory: MSALAngularConfigFactory,} ]) .bootstrapModule(AppModule) .catch(err => console.error(err)); }
Буя! Мы готовы. Мы ждем обещание вернуться, а затем загружаем наше приложение. В этом примере я загрузил только пару свойств из файла конфигурации, однако вы можете загрузить весь json, если хотите.
В какой-то момент в теме упоминается это решение, но его очень легко не заметить, если ваше решение построено на использовании APPINITIALIZER. Я обнаружил, что эти решения не работают для меня, библиотека MSAL пыталась загрузиться до того, как моя конфигурация возвращается с сервера.
Первый ответ на решение использует синхронный вызов с использованием XMLHttpRequest. Если вы попытаетесь использовать это решение, в журнале консоли браузера вы увидите предупреждения о том, что эти синхронные вызовы устарели.
В дополнение к этому вы можете не увидеть проблем на своем локальном компьютере, НО, если у пользователя когда-либо будет медленное подключение к Интернету, это приведет к тому, что ваше приложение перейдет в неисправимое состояние приложения из-за ошибок MSAL js.