다음을 통해 공유


자습서: 노드/Express.js 웹앱에서 Microsoft Graph API 호출

적용 대상: 직원 테넌트에 다음 내용이 적용되었음을 나타내는 흰색 확인 표시 기호가 있는 녹색 원입니다. 다음 콘텐츠가 외부 테넌트에 적용되었음을 나타내는 흰색 확인 표시 기호가 있는 Workforce 테넌트 녹색 원입니다. 외부 테넌트(자세한 정보)

이 자습서에서는 Node/Express.js 웹앱에서 Microsoft Graph API를 호출합니다. 사용자가 로그인하면 앱은 Microsoft Graph API를 호출하는 액세스 토큰을 획득합니다.

이 자습서는 3부로 구성된 자습서 시리즈의 3부입니다.

이 자습서에서는 다음을 수행합니다.

  • 액세스 토큰을 획득하도록 노드/Express.js 웹앱 업데이트
  • 액세스 토큰을 사용하여 Microsoft Graph API를 호출합니다.

필수 구성 요소

UI 구성 요소 추가

  1. 코드 편집기에서 views/index.hbs 파일을 연 다음 다음 코드 조각을 사용하여 보기 사용자 프로필 링크를 추가합니다.

    <a href="/users/profile">View user profile</a>
    

    업데이트를 수행한 후 views/index.hbs 파일은 다음 파일과 유사하게 표시됩니다.

       <h1>{{title}}</h1>
        {{#if isAuthenticated }}
        <p>Hi {{username}}!</p>
        <a href="/users/id">View ID token claims</a>
        <br>
        <a href="/users/profile">View user profile</a>
        <br>
        <br>
        <a href="/auth/signout">Sign out</a>
        {{else}}
        <p>Welcome to {{title}}</p>
        <a href="/auth/signin">Sign in</a>
        {{/if}}
    
  2. views/profile.hbs 파일을 만든 다음, 다음 코드를 추가합니다.

    <h1>Microsoft Graph API</h1>
    <h3>/me endpoint response</h3>
    <table>
        <tbody>
            {{#each profile}}
            <tr>
                <td>{{@key}}</td>
                <td>{{this}}</td>
            </tr>
            {{/each}}
        </tbody>
    </table>
    <br>
    <a href="/">Go back</a>
    
    • 이 페이지에는 Microsoft Graph API에서 반환하는 사용자의 프로필 세부 정보가 표시됩니다.

액세스 토큰 획득

코드 편집기에서 인증/AuthProvider.js 파일을 연 다음 getToken 클래스에 AuthProvider 메서드를 추가합니다.

class AuthProvider {
    //...
        getToken(scopes, redirectUri = "http://localhost:3000/") {
            return  async function (req, res, next) {
                const msalInstance = authProvider.getMsalInstance(authProvider.config.msalConfig);
                try {
                    msalInstance.getTokenCache().deserialize(req.session.tokenCache);
    
                    const silentRequest = {
                        account: req.session.account,
                        scopes: scopes,
                    };
                    const tokenResponse = await msalInstance.acquireTokenSilent(silentRequest);
    
                    req.session.tokenCache = msalInstance.getTokenCache().serialize();
                    req.session.accessToken = tokenResponse.accessToken;
                    next();
                } catch (error) {
                    if (error instanceof msal.InteractionRequiredAuthError) {
                        req.session.csrfToken = authProvider.cryptoProvider.createNewGuid();
    
                        const state = authProvider.cryptoProvider.base64Encode(
                            JSON.stringify({
                                redirectTo: redirectUri,
                                csrfToken: req.session.csrfToken,
                            })
                        );
                        
                        const authCodeUrlRequestParams = {
                            state: state,
                            scopes: scopes,
                        };
    
                        const authCodeRequestParams = {
                            state: state,
                            scopes: scopes,
                        };
    
                        authProvider.redirectToAuthCodeUrl(
                            req,
                            res,
                            next,
                            authCodeUrlRequestParams,
                            authCodeRequestParams,
                            msalInstance
                        );
                    }
    
                    next(error);
                }
            };
        }
}
    //...

getToken 메서드는 지정된 범위를 사용하여 액세스 토큰을 획득합니다.

호출 API 경로 추가

코드 편집기에서 경로/users.js 파일을 연 다음, 다음 경로를 추가합니다.

router.get(
    "/profile",
    isAuthenticated,
    authProvider.getToken(["User.Read"]), // check if user is authenticated
    async function (req, res, next) {
    const graphResponse = await fetch(
        GRAPH_ME_ENDPOINT,
        req.session.accessToken,
    );
    if (!graphResponse.id) {
        return res 
        .status(501) 
        .send("Failed to fetch profile details"); 
    }
    res.render("profile", {
        profile: graphResponse,
    });
    },
);
  • 고객 사용자가 /profile 링크를 선택하면 경로가 트리거됩니다. 앱:

    • User.Read 권한으로 액세스 토큰을 획득합니다.
    • Microsoft Graph API를 호출하여 로그인한 사용자의 프로필을 읽습니다.
    • profile.hbs UI에 사용자 세부 정보를 표시합니다.

Microsoft Graph API 호출

fetch.js 파일을 만든 다음, 다음 코드를 추가합니다.

var axios = require('axios');
var authProvider = require("./auth/AuthProvider");

/**
 * Makes an Authorization "Bearer" request with the given accessToken to the given endpoint.
 * @param endpoint
 * @param accessToken
 * @param method
 */
const fetch = async (endpoint, accessToken, method = "GET", data = null) => {
    const options = {
        headers: {
            Authorization: `Bearer ${accessToken}`,
        },
    };

    console.log(`request made to ${endpoint} at: ` + new Date().toString());

    try{
        const response = await axios.get(endpoint, options);
        return await response.data;

    }catch(error){
        throw new Error(error);
    }

};

module.exports = { fetch };

실제 API 호출은 fetch.js 파일에서 발생합니다.

노드/Express.js 웹앱 실행 및 테스트

  1. 실행의 단계를 사용하고 노드/Express.js 웹앱 테스트하여 웹앱을 실행합니다.
  2. 로그인한 후에 사용자 프로필 링크를 선택합니다. 앱이 제대로 작동하는 경우 로그인한 사용자의 프로필이 Microsoft Graph API에서 읽은 것으로 표시됩니다.