자습서: Node.js 웹 애플리케이션에 로그인 및 로그아웃 추가
이 자습서는 Node.js 웹앱을 빌드하고 Microsoft Entra 관리 센터를 사용하여 인증을 준비하는 방법을 설명하는 시리즈의 마지막 부분입니다. 이 시리즈의 2부에서는 Node.js 웹앱을 만들고 필요한 모든 파일을 구성했습니다. 이 자습서에서는 Node.js 웹앱에 로그인, 등록 및 로그아웃을 추가합니다. Node.js 웹앱에 인증 추가를 간소화하려면 Node용 MSAL(Microsoft 인증 라이브러리)을 사용합니다. 로그인 흐름에서는 사용자를 안전하게 로그인시키는 OIDC(OpenID Connect) 인증 프로토콜을 사용합니다.
이 자습서에서는 다음을 수행합니다.
- 로그인 및 로그아웃 논리 추가
- ID 토큰 클레임 보기
- 앱을 실행하고 로그인 및 로그아웃 환경을 테스트합니다.
필수 조건
- 자습서: 인증을 위한 Node.js 웹 애플리케이션 준비의 단계를 완료했습니다.
MSAL 구성 개체 만들기
코드 편집기에서 authConfig.js 파일을 연 다음, 다음 코드를 추가합니다.
require('dotenv').config();
const TENANT_SUBDOMAIN = process.env.TENANT_SUBDOMAIN || 'Enter_the_Tenant_Subdomain_Here';
const REDIRECT_URI = process.env.REDIRECT_URI || 'http://localhost:3000/auth/redirect';
const POST_LOGOUT_REDIRECT_URI = process.env.POST_LOGOUT_REDIRECT_URI || 'http://localhost:3000';
/**
* Configuration object to be passed to MSAL instance on creation.
* For a full list of MSAL Node configuration parameters, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
*/
const msalConfig = {
auth: {
clientId: process.env.CLIENT_ID || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
authority: process.env.AUTHORITY || `https://${TENANT_SUBDOMAIN}.ciamlogin.com/`, // replace "Enter_the_Tenant_Subdomain_Here" with your tenant name
clientSecret: process.env.CLIENT_SECRET || 'Enter_the_Client_Secret_Here', // Client secret generated from the app registration in Azure portal
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: 'Info',
},
},
};
module.exports = {
msalConfig,
REDIRECT_URI,
POST_LOGOUT_REDIRECT_URI,
TENANT_SUBDOMAIN
};
msalConfig
개체에는 인증 흐름의 동작을 사용자 지정하는 데 사용하는 구성 옵션 집합이 포함되어 있습니다.
authConfig.js 파일에서 다음을 대체합니다.
Enter_the_Application_Id_Here
를 이전에 등록한 앱의 애플리케이션(클라이언트) ID로 바꿉니다.Enter_the_Tenant_Subdomain_Here
를 디렉터리(테넌트) 하위 도메인으로 바꿉니다. 예를 들어, 테넌트 기본 도메인이contoso.onmicrosoft.com
인 경우contoso
를 사용합니다. 테넌트 이름이 없는 경우 테넌트 세부 정보를 읽는 방법을 알아봅니다.Enter_the_Client_Secret_Here
를 이전에 복사한 앱 비밀 값으로 바꿉니다.
.env 파일을 사용하여 구성 정보를 저장하는 경우:
코드 편집기에서 .env 파일을 열고 다음 코드를 추가합니다.
CLIENT_ID=Enter_the_Application_Id_Here TENANT_SUBDOMAIN=Enter_the_Tenant_Subdomain_Here CLIENT_SECRET=Enter_the_Client_Secret_Here REDIRECT_URI=http://localhost:3000/auth/redirect POST_LOGOUT_REDIRECT_URI=http://localhost:3000
앞에서 설명한 대로
Enter_the_Application_Id_Here
,Enter_the_Tenant_Subdomain_Here
및Enter_the_Client_Secret_Here
자리 표시자를 바꿉니다.
authConfig.js 파일에서 msalConfig
, REDIRECT_URI
, TENANT_SUBDOMAIN
및 POST_LOGOUT_REDIRECT_URI
변수를 내보내면 파일이 필요할 때마다 해당 변수에 액세스할 수 있습니다.
사용자 지정 URL 도메인 사용(선택 사항)
사용자 지정 도메인을 사용하여 인증 URL을 완전히 브랜딩합니다. 사용자 관점에서 볼 때, 사용자는 인증 과정 동안 ciamlogin.com 도메인 이름으로 리디렉션되는 것이 아니라 도메인에 남아 있습니다.
사용자 지정 도메인을 사용하려면 다음 단계를 따릅니다.
외부 테넌트에 대한 사용자 지정 URL 도메인을 사용하도록 설정하려면 외부 테넌트의 앱에 대한 사용자 지정 URL 도메인 사용의 단계를 사용합니다.
authConfig.js 파일에서
auth
개체를 찾은 후 다음을 수행합니다.authority
속성의 값을 https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here로 업데이트합니다.Enter_the_Custom_Domain_Here
를 사용자 지정 URL 도메인으로,Enter_the_Tenant_ID_Here
를 테넌트 ID로 바꿉니다. 테넌트 ID가 없는 경우 테넌트 세부 정보를 읽는 방법을 알아봅니다.- [Enter_the_Custom_Domain_Here] 값을 갖는
knownAuthorities
속성을 추가합니다.
authConfig.js 파일을 변경한 후 사용자 지정 URL 도메인이 login.contoso.com이고 테넌트 ID가 aaaabbbb-0000-cccc-1111-dddd2222eeee인 경우 파일은 다음 코드 조각과 유사해야 합니다.
//...
const msalConfig = {
auth: {
authority: process.env.AUTHORITY || 'https://login.contoso.com/aaaabbbb-0000-cccc-1111-dddd2222eeee',
knownAuthorities: ["login.contoso.com"],
//Other properties
},
//...
};
Express 경로 추가
기본 경로는 로그인, 로그아웃 및 ID 토큰 클레임 보기와 같은 작업을 실행할 수 있는 엔드포인트를 제공합니다.
앱 진입점
코드 편집기에서 routes/index.js 파일을 연 다음, 다음 코드를 추가합니다.
const express = require('express');
const router = express.Router();
router.get('/', function (req, res, next) {
res.render('index', {
title: 'MSAL Node & Express Web App',
isAuthenticated: req.session.isAuthenticated,
username: req.session.account?.username !== '' ? req.session.account?.username : req.session.account?.name,
});
});
module.exports = router;
/
경로는 애플리케이션의 진입점입니다. 이는 앞서 앱 UI 구성 요소 빌드에서 만든 views/index.hbs 뷰를 렌더링합니다. isAuthenticated
는 뷰에 표시되는 내용을 결정하는 부울 변수입니다.
로그인 및 로그아웃
코드 편집기에서 routes/auth.js 파일을 연 다음 auth.js 코드를 추가합니다.
코드 편집기에서 controller/authController.js 파일을 연 다음 authController.js 코드를 추가합니다.
코드 편집기에서 auth/AuthProvider.js 파일을 연 다음 AuthProvider.js 코드를 추가합니다.
/signin
,/signout
및/redirect
경로는 routes/auth.js 파일에 정의되어 있지만 해당 논리는 auth/AuthProvider.js 클래스에서 구현합니다.
login
메서드는/signin
경로를 처리합니다.인증 코드 흐름의 첫 번째 구간을 트리거하여 로그인 흐름을 시작합니다.
이전에 만든 MSAL 구성 개체
msalConfig
를 사용하여 기밀 클라이언트 애플리케이션 인스턴스를 초기화합니다.const msalInstance = this.getMsalInstance(this.config.msalConfig);
getMsalInstance
메서드는 다음과 같이 정의됩니다.getMsalInstance(msalConfig) { return new msal.ConfidentialClientApplication(msalConfig); }
인증 코드 흐름의 첫 번째 레그는 인증 코드 요청 URL을 생성한 다음, 해당 URL로 리디렉션하여 인증 코드를 가져옵니다. 이 첫 번째 레그는
redirectToAuthCodeUrl
메서드에서 구현됩니다. MSAL getAuthCodeUrl 메서드를 사용하여 인증 코드 URL을 생성하는 방법을 확인하세요.//... const authCodeUrlResponse = await msalInstance.getAuthCodeUrl(req.session.authCodeUrlRequest); //...
그런 다음 인증 코드 URL 자체로 리디렉션합니다.
//... res.redirect(authCodeUrlResponse); //...
handleRedirect
메서드는/redirect
경로를 처리합니다.이 URL은 웹앱 등록의 앞부분에서 Microsoft Entra 관리 센터에서 웹앱에 대한 리디렉션 URI로 설정했습니다.
이 엔드포인트는 인증 코드 흐름에서 사용하는 두 번째 레그를 구현합니다. 인증 코드를 사용하여 MSAL의 acquireTokenByCode 메서드를 사용하여 ID 토큰을 요청합니다.
//... const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body); //...
응답을 받은 후 Express 세션을 만들고 원하는 정보를 저장할 수 있습니다.
isAuthenticated
를 포함하고true
로 설정해야 합니다.//... req.session.idToken = tokenResponse.idToken; req.session.account = tokenResponse.account; req.session.isAuthenticated = true; //...
logout
메서드는/signout
경로를 처리합니다.async logout(req, res, next) { /** * Construct a logout URI and redirect the user to end the * session with Azure AD. For more information, visit: * https://docs.microsoft.com/azure/active-directory/develop/v2-protocols-oidc#send-a-sign-out-request */ const logoutUri = `${this.config.msalConfig.auth.authority}${TENANT_SUBDOMAIN}.onmicrosoft.com/oauth2/v2.0/logout?post_logout_redirect_uri=${this.config.postLogoutRedirectUri}`; req.session.destroy(() => { res.redirect(logoutUri); }); }
로그아웃 요청이 시작됩니다.
사용자를 애플리케이션에서 로그아웃하려는 경우 사용자 세션을 종료하는 것만으로는 충분하지 않습니다. 사용자를 logoutUri로 리디렉션해야 합니다. 그렇지 않으면 사용자가 자격 증명을 다시 입력하지 않고 애플리케이션에 다시 인증할 수 있습니다. 테넌트 이름이 contoso인 경우 logoutUri는
https://contoso.ciamlogin.com/contoso.onmicrosoft.com/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000
과 유사합니다.
ID 토큰 클레임 보기
코드 편집기에서 routes/todos.js 파일을 연 다음, 다음 코드를 추가합니다.
const express = require('express');
const router = express.Router();
// custom middleware to check auth state
function isAuthenticated(req, res, next) {
if (!req.session.isAuthenticated) {
return res.redirect('/auth/signin'); // redirect to sign-in route
}
next();
};
router.get('/id',
isAuthenticated, // check if user is authenticated
async function (req, res, next) {
res.render('id', { idTokenClaims: req.session.account.idTokenClaims });
}
);
module.exports = router;
사용자가 인증되면 /id
경로는 views/id.hbs 뷰를 사용하여 ID 토큰 클레임을 표시합니다. 앱 UI 구성 요소 빌드의 앞부분에서 이 보기를 추가했습니다.
지정된 이름과 같은 특정 ID 토큰 클레임을 추출하려면:
const givenName = req.session.account.idTokenClaims.given_name
웹앱 완성하기
코드 편집기에서 app.js 파일을 열고 app.js의 코드를 여기에 추가합니다.
코드 편집기에서 server.js 파일을 열고 server.js의 코드를 여기에 추가합니다.
코드 편집기에서 package.json 파일을 연 다음,
scripts
속성을 다음 위치에 업데이트합니다."scripts": { "start": "node server.js" }
웹앱 실행 및 테스트
터미널에서
ciam-sign-in-node-express-web-app
와 같은 웹앱이 포함된 프로젝트 폴더에 있는지 확인합니다.터미널에서 다음 명령을 실행합니다.
npm start
브라우저를 연 다음
http://localhost:3000
으로 이동합니다. 다음 스크린샷과 비슷한 페이지가 표시됩니다.페이지 로드가 완료되면 로그인 링크를 선택합니다. 로그인하라는 메시지가 나타납니다.
로그인 페이지에서 이메일 주소를 입력하고, 다음을 선택하고, 암호를 입력한 다음, 로그인을 선택합니다. 계정이 없는 경우 등록 흐름을 시작하는 계정이 없으신가요? 만들기 링크를 선택합니다.
등록 옵션을 선택한 경우 이메일, 일회용 암호, 새 암호 및 기타 계정 세부 정보를 입력한 후 전체 등록 흐름을 완료합니다. 다음 스크린샷과 비슷한 페이지가 표시됩니다. 로그인 옵션을 선택하면 비슷한 페이지가 표시됩니다.
웹앱에서 사용자를 로그아웃하려면 로그아웃을 선택하고, 모든 ID 토큰 클레임을 보려면 ID 토큰 클레임 보기를 선택합니다.