programing

Azure AD에서 VueJS 앱을 인증하려면 어떻게 해야 합니까?

randomtip 2022. 9. 1. 22:42
반응형

Azure AD에서 VueJS 앱을 인증하려면 어떻게 해야 합니까?

VueJS 2.x 프레임워크를 사용하여 앱을 셋업하고 있는데 Azure Active Directory 서비스를 통해 사용자를 인증해야 합니다.서비스에 필요한 "로그인 정보"(Auth 및 Token URL)가 이미 있습니다.

지금까지 VueJ에서의 셋업을 나타내는 기사는 1건뿐이지만, 서드파티 서비스(Auth0)에 의존하고 있기 때문에 프로세스에 불필요한 컨볼루션(convolution)이 추가되어 있습니다.

인증을 쉽게 수행할 수 있는 VueJs npm 모듈이 없는 경우 어떻게 해야 합니까?아니면 Adal JS와 같이 Vue 이외의 라이브러리에 의존해야 합니까?

어떤 제안이든 도움이 될 것입니다.

이 문제를 해결하기 위해 저는 ADAL JS에 의지했습니다.여기에서는 Vue + Vue-Router 샘플 어플리케이션을 제공하고 있습니다만, 아래에 중요한 내용을 기재합니다.

당신의 소포 안에.json:

"dependencies": {
    "adal-angular": "^1.0.15",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
},

ADAL JS 라이브러리의 기본 래퍼 모듈:

import AuthenticationContext from 'adal-angular/lib/adal.js'

const config = {
  tenant: 'your aad tenant',
  clientId: 'your aad application client id',
  redirectUri: 'base uri for this application',
  cacheLocation: 'localStorage'
};

export default {
  authenticationContext: null,
  /**
   * @return {Promise}
   */
  initialize() {
    this.authenticationContext = new AuthenticationContext(config);

    return new Promise((resolve, reject) => {
      if (this.authenticationContext.isCallback(window.location.hash) || window.self !== window.top) {
        // redirect to the location specified in the url params.
        this.authenticationContext.handleWindowCallback();
      }
      else {
        // try pull the user out of local storage
        let user = this.authenticationContext.getCachedUser();

        if (user) {
          resolve();
        }
        else {
          // no user at all - go sign in.
          this.signIn();
        }
      }
    });
  },
  /**
   * @return {Promise.<String>} A promise that resolves to an ADAL token for resource access
   */
  acquireToken() {
    return new Promise((resolve, reject) => {
      this.authenticationContext.acquireToken('<azure active directory resource id>', (error, token) => {
        if (error || !token) {
          return reject(error);
        } else {
          return resolve(token);
        }
      });
    });
  },
  /**
   * Issue an interactive authentication request for the current user and the api resource.
   */
  acquireTokenRedirect() {
    this.authenticationContext.acquireTokenRedirect('<azure active directory resource id>');
  },
  /**
   * @return {Boolean} Indicates if there is a valid, non-expired access token present in localStorage.
   */
  isAuthenticated() {
    // getCachedToken will only return a valid, non-expired token.
    if (this.authenticationContext.getCachedToken(config.clientId)) { return true; }
    return false;
  },
  /**
   * @return An ADAL user profile object.
   */
  getUserProfile() {
    return this.authenticationContext.getCachedUser().profile;
  },
  signIn() {
    this.authenticationContext.login();
  },
  signOut() {
    this.authenticationContext.logOut();
  }
}

앱의 엔트리 포인트(vue-cli를 사용한 경우 main.js):

import Vue from 'vue'
import App from './App'
import router from './router'
import authentication from './authentication'

// Init adal authentication - then create Vue app.
authentication.initialize().then(_ => {
  /* eslint-disable no-new */
  new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
  });
});

Vue 라우터 구성의 경우:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import authentication from '../authentication'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta: {
        requiresAuthentication: true
      }
    }
  ]
})

// Global route guard
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuthentication)) {
    // this route requires auth, check if logged in
    if (authentication.isAuthenticated()) {
      // only proceed if authenticated.
      next();
    } else {
      authentication.signIn();
    }
  } else {
    next();
  }
});

export default router;

Vue 컴포넌트:

import authentication from './authentication'
...
computed: {
  isAuthenticated() {
    return authentication.isAuthenticated();
  }
},
methods: {
  logOut() {
    authentication.signOut();
  }
}

요청 헤더에 액세스 토큰 추가

한 vue-resource http요격의 아래이고,이지만 어떤 방법을 할 것이다.

Vue.http.interceptors.push(function (request, next) {
  auth.acquireToken().then(token => {
    // Set default request headers for every request
    request.headers.set('Content-Type', 'application/json');
    request.headers.set('Ocp-Apim-Subscription-Key', 'api key');
    request.headers.set('Authorization', 'Bearer ' + token)
    // continue to next interceptor
    next();
  });
});

바라건대 이 약간의 시간:)누군가를 절약한다.

Disclaimer:이 플러그의 나는 작가이다.

npm을 통해vue-adal을 사용하세요:

npm install vue-adal

Basic의 경우 사용

import Adal from 'vue-adal'
Vue.use(Adal, {
// This config gets passed along to Adal, so all settings available to adal can be used here.
  config: {
    // 'common' (multi-tenant gateway) or Azure AD Tenant ID
    tenant: '<guid>',

    // Application ID
    clientId: '<guid>',

    // Host URI
    redirectUri: '<host addr>',

    cacheLocation: 'localStorage'
  },

  // Set this to true for authentication on startup
  requireAuthOnInitialize: true,

  // Pass a vue-router object in to add route hooks with authentication and role checking
  router: router
})
```

중요:너무 커서 해시도 사용하지 않'history를 라우터에 모드를 설정하는 확인하세요!이것은 serverside에 영향을 미칠 것이다.

new Router({
  mode: 'history', // Required for Adal library
  ... // Rest of router init
})

에는 사용을 위해 npm에 github에 더 많은 지시 및 설명서 샘플+ 있다.

나는 도서관 뷰 앱에 대한 보안을 도와 주는 것이 분명하지 않아요.하지만, 우리는 쉽게 인증을 위한 Adal.js을 끼칠 수 있습니다.

나는:당신의 참고를 위한 단순한 데모를 썼다.

Index.html:

<html>
<head>
  <script src="https://unpkg.com/vue"></script>
  <script src="node_modules\adal-angular\lib\adal.js"></script>
  <script src="config.js"></script>
  <script>
    var authContext = new AuthenticationContext(config);

    function login() {
      authContext.login();
    }

    function init(configOptions) {
    if (configOptions) {
      // redirect and logout_redirect are set to current location by default
      var existingHash = window.location.hash;
      var pathDefault = window.location.href;
      if (existingHash) {
        pathDefault = pathDefault.replace(existingHash, "");
      }
      configOptions.redirectUri = configOptions.redirectUri || pathDefault;
      configOptions.postLogoutRedirectUri =
      configOptions.postLogoutRedirectUri || pathDefault;

      // create instance with given config
    } else {
      throw new Error("You must set configOptions, when calling init");
    }

    // loginresource is used to set authenticated status
    updateDataFromCache(authContext.config.loginResource);
    }

    var _oauthData = {
      isAuthenticated: false,
      userName: "",
      loginError: "",
      profile: ""
    };
    var updateDataFromCache = function(resource) {
      // only cache lookup here to not interrupt with events
      var token = authContext.getCachedToken(resource);
      _oauthData.isAuthenticated = token !== null && token.length > 0;
      var user = authContext.getCachedUser() || { userName: "" };
      _oauthData.userName = user.userName;
      _oauthData.profile = user.profile;
      _oauthData.loginError = authContext.getLoginError();
    };

    function saveTokenFromHash() {
      var hash = window.location.hash;
      var requestInfo = authContext.getRequestInfo(hash);
      if (authContext.isCallback(hash)) {
        // callback can come from login or iframe request

        var requestInfo = authContext.getRequestInfo(hash);
        authContext.saveTokenFromHash(requestInfo);
        window.location.hash = "";

        if (requestInfo.requestType !== authContext.REQUEST_TYPE.LOGIN) {
          authContext.callback = window.parent.AuthenticationContext().callback;
        }
      }
    }

    function isAuthenticate() {
      return _oauthData.isAuthenticated;
    }

    saveTokenFromHash();

    init(config);
  </script>
</head>

<body>
<div id="app">
  <p v-if="_oauthData.isAuthenticated">Hello {{ oauthData.userName }}</p>
  <button onclick="login()" v-else>Login</button>
</div>

<script>
  var app = new Vue({
    el: "#app",
    data: {
      oauthData: _oauthData
    }
  });
</script>
</body>
</html>

config.js:

var config = {
  tenant: 'xxx.onmicrosoft.com',
  clientId: '',
  redirectUri: '',
  cacheLocation: 'localStorage'
};

당신은 아달 자바 스크립트 사용할 수 있다.하지만 난 너 보안 이 해결책을 더 연구하는 것을 제안하면 라인에 PKCE을 사용하는 것입니다 새로운 보안 권고, 화면을 보https://oauth.net/2/grant-types/implicit/).것 같아 보이지 않아나는 그것에 대한adal 자바 스크립트 문서 찾지 못 했다.

이 힘든 기억에 제가 이-hopfully 이 누군가에게 일부 시간을 절약할 수 있는 게시물이 있습니다..

문제는 vue.js 앱을 azure-ad로 인증할 뿐만 아니라 사용자가 속한 Security Group도 취득해야 한다는 것이었습니다.

이것을 실현하기 위해서, 다음과 같이 했습니다.

위의 vue-adal 샘플 앱을 사용했습니다(https://github.com/survirtual/vue-adal) - sample folder에서 찾을 수 있습니다).

하지만 내가 필요한 방식으로 작동시키기 위해 몇 가지 변화를 주어야만 했다.후하기 위해 net 를 사용했기 에서 변경해야 한다는 입니다.main.js 것,,,, 음 this음 this this this this this this this this.

const graphApiBase = `https://graph.windows.net`
const graphApiResource = '00000002-0000-0000-c000-000000000000'

다음과 같이 입력합니다.

const graphApiBase = `https://graph.microsoft.com/v1.0`
const graphApiResource = '00000003-0000-0000-c000-000000000000'

또한 return url 컴포넌트 내에서 사용자가 속한 Security Group을 취득하기 위해 Axios 쿼리를 변경해야 했기 때문에 (홈에서) 이를 변경했습니다.vue 파일):

async getUserInfo () {
    let res = await this.$graphApi.get(`me`, {
        params: {
            'api-version': 1.6
    }
})

다음과 같이 입력합니다.

async getUserInfo () {
    let res = await this.$graphApi.post(`/me/getMemberGroups`, {
        securityEnabledOnly: true
    })
    console.log(res)
    return res.data
}

그리고 API에서 받은 데이터에는 사용자가 속한 보안 그룹이 포함되어 있습니다.

언급URL : https://stackoverflow.com/questions/44437634/how-do-you-authenticate-a-vuejs-app-with-azure-ad

반응형