Share via


인증을 위해 Python Flask 웹앱 준비

이 자습서는 Python Flask 웹앱을 빌드하고 Microsoft ID 플랫폼 사용하여 로그인 지원을 추가하는 방법을 보여 주는 시리즈의 2부입니다. 이 시리즈의 1부에서는 Microsoft Entra ID 테넌트에 애플리케이션을 등록하고 구성했습니다.

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

  • 새 Python Flask 웹앱 프로젝트 만들기
  • 앱 종속성 업그레이드
  • 애플리케이션의 UI 구성 요소 추가
  • 인증에 Microsoft Entra ID를 사용하도록 Flask 웹앱 구성

필수 조건

새 Python 웹앱 프로젝트 만들기

자습서의 나머지 부분을 완료하려면 Python Flask 웹앱 프로젝트를 만들어야 합니다. 학습을 위해 완성된 코드 샘플을 사용하려는 경우 GitHub에서 Python Flask 웹앱 샘플을 다운로드합니다.

Python Flask 웹앱을 처음부터 빌드하려면 다음 단계를 수행합니다.

  1. 애플리케이션을 호스트하고 이름을 flask-web-app으로 지정하는 폴더를 만듭니다.
  2. 프로젝트 디렉터리로 이동하여 app.py, app.config.py 및 requirements.txt개의 파일을 만듭니다.
  3. 프로젝트의 루트 폴더에 .env 파일을 만듭니다.
  4. 프로젝트 루트 디렉터리에 템플릿이라는 폴더를 만듭니다. Flask는 이 하위 디렉터리에서 렌더링 템플릿을 찾습니다.

파일을 만든 후 프로젝트의 파일 및 디렉터리가 다음 구조와 유사해야 합니다.

python-webapp/
├── templates/
│     ├── display.html
│     ├── index.html
│     ├── login.html
├── .env.sample
├── app.py
├── app.config.py
│── requirements.txt

앱 종속성 업그레이드

빌드하는 애플리케이션은 Python용 MSAL(Microsoft 인증 라이브러리)에 대한 래퍼인 패키지를 사용합니다identity. 또한 Flask, Flask 세션, 요청 및 앱에 필요한 다른 모든 종속성을 설치합니다. requirements.txt를 이러한 종속성을 업데이트합니다.

Flask>=2.2
Flask-Session>=0.3.2,<0.6
werkzeug>=2
requests>=2,<3
identity>=0.5.1,<0.6
python-dotenv<0.22 

애플리케이션 UI 구성 요소 추가

이 섹션에서는 로그인, 로그아웃, API 호출 및 오류 템플릿을 포함하여 앱에서 정의하는 각 경로에 대한 HTML 템플릿을 만듭니다. 다음 단계에 따라 각 페이지에 대한 템플릿을 만듭니다.

로그인 템플릿

템플릿 폴더에서 login.html HTML 파일을 만들고 다음 콘텐츠를 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Login</title>
</head>
<body>
    <h1>Microsoft Identity Python Web App</h1>

    {% if user_code %}
    <ol>
      <li>To sign in, type <b>{{ user_code }}</b> into
        <a href='{{ auth_uri }}' target=_blank>{{ auth_uri }}</a>
        to authenticate.
      </li>
      <li>And then <a href="{{ url_for('auth_response') }}">proceed</a>.</li>
    </ol>
    {% else %}
    <ul><li><a href='{{ auth_uri }}'>Sign In</a></li></ul>
    {% endif %}

    <hr>
    <footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>

이 템플릿은 사용자가 애플리케이션에 로그인할 수 있는 로그인 페이지를 나타냅니다.

인덱스 템플릿

템플릿 폴더에서 index.html이라는 HTML 파일을 만들고 다음 콘텐츠를 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Index</title>
</head>
<body>
    <h1>Microsoft Identity Python Web App</h1>
    <h2>Welcome {{ user.get("name") }}!</h2>

    <ul>
    {% if config.get("ENDPOINT") %}
      <li><a href='/call_downstream_api'>Call a downstream API</a></li>
    {% endif %}

    <li><a href="/logout">Logout</a></li>
    </ul>

    <hr>
    <footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>

인덱스 템플릿은 사용자가 앱의 루트 URL을 방문할 때 렌더링되는 웹앱의 홈페이지 역할을 합니다.

표시 페이지

이 템플릿은 다운스트림 API 호출의 결과를 표시하는 데 사용됩니다. display.html 다음 코드 조각을 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: API</title>
</head>
<body>
    <a href="javascript:window.history.go(-1)">Back</a> <!-- Displayed on top of a potentially large JSON response, so it will remain visible -->
    <h1>Result of the downstream API Call</h1>
    <pre>{{ result |tojson(indent=4) }}</pre> <!-- Just a generic json viewer -->
</body>
</html>

오류 템플릿

인증 오류 템플릿

템플릿 폴더에서 올 수 있는 오류 메시지를 표시하는 auth_error.html HTML 파일을 만듭니다. auth_error.html 다음 코드를 추가합니다.

<!DOCTYPE html>*
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
    <h2>Login Failure</h2>
    <dl>
      {#
        Flask automatically escapes these unsafe input, so we do not have to.
        See also https://flask.palletsprojects.com/en/2.0.x/templating/#jinja-setup
      #}
      <dt>{{ result.get("error") }}</dt>
      <dd>{{ result.get("error_description") }}</dd>
    </dl>
    <hr>
    <a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>

구성 오류 템플릿

템플릿 폴더에서 필요한 구성이 누락된 경우 메시지를 표시하는 config_error.html이라는 HTML 파일을 만듭니다. config_error.html 다음 코드를 추가합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
    <h2>Config Missing</h2>
    <p>
        Almost there. Did you forget to set up
<a target=_blank
href="https://learn.microsoft.com/azure/active-directory/develop/web-app-quickstart?pivots=devlang-python#step-5-configure-the-sample-app">
necessary environment variables</a> for your deployment?
    </p>
    <hr>
    <a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>

구성 파일 만들기

코드 편집기에서 구성 매개 변수를 포함하는 app_config.py 열고 다음 코드를 추가합니다.

import os
AUTHORITY= os.getenv("AUTHORITY")

# Application (client) ID of app registration
CLIENT_ID = os.getenv("CLIENT_ID")
# Application's generated client secret: never check this into source control!
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
 
REDIRECT_PATH = "/getAToken"  # Used for forming an absolute URL to your redirect URI.

ENDPOINT = 'https://graph.microsoft.com/v1.0/me'  
SCOPE = ["User.Read"]

# Tells the Flask-session extension to store sessions in the filesystem
SESSION_TYPE = "filesystem"

구성 설정을 저장할 .env 파일을 만듭니다.

이 샘플에서는 .env 파일을 사용하여 코드에 포함되지 않아야 하는 애플리케이션의 구성 설정, 환경 변수 및 자격 증명을 저장하고 관리합니다. 프로젝트 디렉터리의 루트에서 만든 .env 파일을 열고 다음 값을 추가합니다.

# The following variables are required for the app to run.
CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>
AUTHORITY=<Enter_your_authority_url>

.env.sample 파일에서 다음의 자리 표시자를 바꿉합니다.

    • CLIENT_ID앱 등록 개요 페이지에서 사용할 수 있는 애플리케이션(클라이언트) ID를 사용합니다.
    • CLIENT_SECRET 인증서 및 비밀에서 만든 클라이언트 암호를 사용하여
    • AUTHORITYhttps://login.microsoftonline.com/<TENANT_GUID>으로 바꿉니다. 디렉터리(테넌트) ID는 앱 등록 개요 페이지에서 사용할 수 있습니다.

다음 단계

이 자습서 시리즈의 다음 부분에서 Python Flask 웹앱에 로그인 지원을 추가하는 방법을 알아봅니다.