Использование MSAL v0.1.3 с Aurelia для аутентификации

Я нашел всевозможные примеры использования MSAL и даже примеры использования MSAL с приложениями SPA (обычно Angular или React), но я изо всех сил пытаюсь заставить это работать с Aurelia.

Я сделал следующее, чтобы убедиться, что библиотека действительно работает должным образом.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test Page</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/0.1.3/js/msal.min.js"></script>
    <style>
        .hidden {
            visibility: hidden;
        }
    </style>
  </head>
  <body>
      <div id="username"></div>
      <div id="token"></div>
      <button id="login" onclick="loginPopup()">Log In</button>
      <button id="logout" class="hidden">Log Out</button>
    <script>
        var authClient = new Msal.UserAgentApplication("my v2 endpoint client id",null);

       function loginPopup(){
           authClient.loginPopup(["openid","user.readbasic.all"])
           .then(token => {
               authClient.acquireTokenSilent(["user.readbasic.all"])
               .then(accessToken => {
                updateUI(token);
            },
            error => {
                authClient.acquireTokenPopup(["user.readbasic.all"])
                .then(accessToken => {
                    updateUI(token);
                },
                error => {
                    console.log("Token Error: " + error)
                })
            })

        },
        error =>{
            console.log("Login error " + error)
        })
    }

    function updateUI(token){
        var loginbutton = document.getElementById("login");
        loginbutton.className = "hidden";

        let usernamediv = document.getElementById("username");
        let tokendiv = document.getElementById("token");

        usernamediv.innerText = authClient.getUser().name;
        tokendiv.innerText = token;
    }
   </script>
  </body>
</html>

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

Теперь я пытаюсь добавить это в свое приложение Aurelia следующим образом:

main.js

export async function configure(aurelia){
   aurelia.use
    .standardConfiguration()
    .developmentLogging();

   let msClient = new Msal.UserAgentApplication('my v2 endpoint client id",null);
   aurelia.use.instance("AuthService",msClient);

   await aurelia.start();

   if(msClient.getUser()) {
        await aurelia.setRoot(PLATFORM.moduleName("app"));
   else
        await aurelia.setRoot(PLATFORM.moduleName("login/login"));

login.js

export class Login {
   static inject = [Aurelia, "AuthService"]
   constructor(aurelia, auth){
        this.authService = auth
        this.app = aurelia
   }

   activate(){
        //Also tried this code in constructor
        this.authService.loginPopup(["openid","user.readbasic.all"])
         .then(token => {
             this.app.setRoot(PLATFORM.moduleName("app"))
         });
   }  
}

Однако с этим кодом приложение загружается и переходит на страницу входа, которая открывает всплывающее окно входа. Однако, как только пользователь вводит / выбирает имя и пароль, всплывающий экран не исчезает. Кажется, что приложение (за всплывающим окном) перезагружается и переходит к модели просмотра app.js, но всплывающее окно остается на экране и, похоже, просит пользователя ввести / выбрать имя пользователя.

Я также пробовал использовать loginRedirect вместо loginPopup с аналогичным результатом: приложение постоянно перенаправляется на страницу входа даже после аутентификации.

Я предполагаю, что это связано с тем, как MSAL пытается реагировать на приложение, и с тем, как Аурелия пытается справиться с навигацией и т. Д., Но я не могу понять, где что-то идет не так.

Любая помощь будет принята с благодарностью!


person RHarris    schedule 17.01.2018    source источник
comment
Это очень специфическая проблема, которая зависит от поведения MSAL. Похоже, маршрутизатор в основном делает то, что должен. Давайте подключимся, и вы сможете показать мне поведение вживую, и мы посмотрим, сможем ли мы его исправить.   -  person Matthew James Davis    schedule 19.01.2018


Ответы (1)


Используйте обратный вызов жизненного цикла attached()

Вроде все работает, но всплывающее окно никуда не девается. Трудно понять, почему, не видя код в действии, но первое, что вы захотите попробовать, это переместить соответствующий код в обратный вызов attached(), который вызывается после связывания представления и модели представления и добавления их в DOM.

НЕ возвращайте обещание входа в activate()

Если вы вернули обещание входа в activate(), активация не будет завершена, пока обещание не будет выполнено. Однако app.setRoot() также вызывается, когда обещание разрешается, что означает, что вы начнете новую навигацию до того, как завершится первая. Это плохо.

activate() {
  // THIS WOULD BREAK
  return this.authService.loginPopup(["openid","user.readbasic.all"])
    .then(token => {
      this.app.setRoot(PLATFORM.moduleName("app"))
    });
}

Используйте обратный вызов жизненного цикла detatched()

Если это не сработает, следующее, что нужно сделать, это проверить, правильно ли authService.loginPopup() входит в систему и разрешается. Если это так, вы всегда можете продолжить и вручную удалить всплывающее окно из DOM в случае, если библиотека не очищалась после себя. Вы должны сделать этот обратный вызов detatched() жизненного цикла.

person Matthew James Davis    schedule 22.01.2018
comment
Поговорив с Мэттом, мы смогли добиться, чтобы это работало: 1) с помощью connected (), а не activate (), и 2) с помощью MSAL loginRedirect (), а не loginPopup (). - person RHarris; 22.01.2018