자습서: Python Flask 웹앱에 로그인 추가
이 자습서는 Python Flask 웹앱을 처음부터 빌드하고 Microsoft ID 플랫폼을 사용하여 인증을 통합하는 방법을 보여 주는 자습서 시리즈의 세 번째 부분입니다. 이 자습서에서는 빌드한 앱에서 사용자를 인증하는 코드를 추가합니다.
- 필요한 모듈 및 구성 가져오기
- Flask 웹앱의 인스턴스 만들기
- 로컬 개발을 위한 ProxyFix 미들웨어 구성
- 로그인하고 사용자를 로그아웃하는 코드 추가
- 웹앱의 진입점 정의
필요한 패키지 및 구성 가져오기
빌드하는 웹앱은 MSAL Python을 기반으로 빌드된 identity.web
패키지를 사용하여 웹앱에서 사용자를 인증합니다.
identity.web
패키지, Flask 프레임워크, Flask 모듈, Flask 세션 및 이전 자습서에 정의된 앱 구성을 가져오려면 다음 코드를 추가하여 app.py.
import identity.web
import requests
from flask import Flask, redirect, render_template, request, session, url_for
from flask_session import Session
import app_config
이 코드 조각에서는 Flask에서 웹 요청 및 세션을 처리하기 위한 함수 및 개체인 redirect
, render_template
, request
, session
및 url_for
가져옵니다. 또한 앱에 대한 구성 설정을 포함하는 app_config
가져옵니다.
Flask 웹앱의 인스턴스 만들기
필요한 모듈을 가져온 후 app-config
구성을 사용하여 웹앱을 초기화합니다. 웹앱의 인스턴스를 만들려면 다음 코드 조각을 app.py
에 추가하세요.
app = Flask(__name__)
app.config.from_object(app_config)
assert app.config["REDIRECT_PATH"] != "/", "REDIRECT_PATH must not be /"
Session(app)
위의 코드 조각에서는 새 Flask 애플리케이션을 초기화하고 app.config.from_object(app_config)
사용하여 구성 설정을 로드합니다. 앱은 from_object
사용하여 지정된 (app_config)
구성을 상속합니다.
또한 어설션 검사를 수행하여 앱의 리디렉션 경로가 루트 경로("/")로 설정되지 않았는지 확인합니다.
Session(app)
여러 요청에 걸쳐 사용자 인증 상태와 같은 데이터를 처리하고 저장할 수 있도록 앱에 대한 세션 관리를 초기화합니다.
로컬 개발을 위한 ProxyFix 미들웨어 구성
샘플 웹앱은 로컬 호스트에서 실행되므로 ProxyFix
미들웨어를 사용하여 요청 헤더의 URL 구성표 및 호스트 정보를 수정합니다.
app.py
다음 코드를 추가하여 ProxyFix를 적용합니다.
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
인증용 객체 초기화
다음으로, identity.web.Auth
클래스의 인스턴스를 만들어 인증 개체를 초기화합니다. 또한 다음과 같이 Auth 개체를 초기화할 때 생성자에 session
, authority
, client_id
및 client_credential
매개 변수를 전달합니다.
app.jinja_env.globals.update(Auth=identity.web.Auth) # Useful in template for B2C
auth = identity.web.Auth(
session=session,
authority=app.config["AUTHORITY"],
client_id=app.config["CLIENT_ID"],
client_credential=app.config["CLIENT_SECRET"],
)
이 코드 조각에서 app.jinja_env.globals.update(Auth=identity.web.Auth)
Auth
이라는 새 전역 변수를 추가하고 identity.web.Auth
값을 할당합니다. 이렇게 하면 Flask 애플리케이션에서 렌더링하는 모든 템플릿에서 Auth
액세스할 수 있습니다.
사용자 로그인
이 앱에서 빌드하는 권한 부여 흐름은 두 다리로 구성됩니다. 첫 번째 레그에서는 다음과 같이 auth.log_in
함수를 호출하여 사용자를 로그인합니다.
@app.route("/login")
def login():
return render_template("login.html", version=__version__, **auth.log_in(
scopes=app_config.SCOPE, # Have user consent to scopes during log-in
redirect_uri=url_for("auth_response", _external=True), # Optional. If present, this absolute URL must match your app's redirect_uri registered in Microsoft Entra admin center
prompt="select_account", # Optional.
))
사용자가 앱에서 /login
URL로 이동하면 Flask는 요청을 처리하는 뷰 함수를 호출하여 login.html
템플릿을 렌더링합니다.
login()
내에서 사용자가 로그인 프로세스 중에 동의해야 하는 범위 목록을 사용하여 auth.log_in
함수를 호출합니다. 또한 앱의 리디렉션 URI i Microsoft Azure 관리 센터와 일치해야 하는 매개 변수에 redirect_uri
제공합니다.
필요에 따라 활성 세션이 있는 계정 간에 재인증, 사용자 동의 또는 계정 선택을 요청하여 로그인 프롬프트의 동작을 제어하는 prompt
같은 매개 변수를 추가할 수 있습니다.
권한 부여 흐름의 두 번째 레그에서는 다음과 같이 redirect_uri 컨트롤러 내에서 auth.complete_log_in
함수를 호출하여 인증 응답을 처리합니다.
@app.route(app_config.REDIRECT_PATH)
def auth_response():
result = auth.complete_log_in(request.args)
if "error" in result:
return render_template("auth_error.html", result=result)
return redirect(url_for("index"))
complete_log_in()
함수는 들어오는 auth_response
사전을 쿼리 매개 변수로 사용합니다. 성공하면 함수는 redirect(url_for("index"))
사용하여 사용자를 "인덱스" 경로로 리디렉션합니다. 즉, 사용자가 자신의 정보에 성공적으로 로그인한 경우 이미 유효성이 검사된 ID 토큰의 클레임을 포함하는 사전으로 사용할 수 있습니다.
결과에 if "error" in result:
조건에 따라 결정된 오류가 포함된 경우 "auth_error.html"
템플릿을 사용자에게 렌더링합니다.
사용자 로그아웃
Flask 애플리케이션에서 사용자를 로그아웃하려면 다음과 같이 auth.log_out()
메서드를 호출합니다.
@app.route("/logout")
def logout():
return redirect(auth.log_out(url_for("index", _external=True)))
사용자가 앱에서 /logout
URL 경로로 이동하면 Flask는 현재 앱에서 로그아웃하는 로그아웃 함수를 호출합니다. 또한 사용자가 로그아웃할 때 리디렉션해야 하는 페이지를 지정합니다. 코드 조각에서는 url_for("index", _external=True).
사용하여 사용자를 앱의 홈페이지로 리디렉션합니다.
웹앱의 진입점 정의
로그인 및 로그아웃 논리를 구현한 후 다음과 같이 index()
함수를 만들어 앱 홈페이지에 진입점을 추가합니다.
@app.route("/")
def index():
if not (app.config["CLIENT_ID"] and app.config["CLIENT_SECRET"]):
# This check is not strictly necessary.
# You can remove this check from your production code.
return render_template('config_error.html')
if not auth.get_user():
return redirect(url_for("login"))
return render_template('index.html', user=auth.get_user(), version=__version__)
index()
함수는 사용자가 앱의 루트 URL("/")로 이동할 때 호출됩니다. 앱의 홈페이지를 렌더링하기 전에 구성 검사를 처리하고 사용자 인증의 유효성을 검사합니다. 구성에서 클라이언트 ID 및 클라이언트 암호가 누락되었는지 확인하고 두 값 중 하나 또는 둘 다 누락된 경우 Flask는 "config_error.html"
템플릿을 렌더링합니다.
또한 함수는 auth.get_user()
호출하여 사용자가 인증되었는지 여부를 확인합니다. 사용자가 인증되지 않으면 "login"
경로로 리디렉션됩니다. 인증된 경우 Flask는 "index.html" 템플릿을 렌더링하고 렌더링을 위해 사용자 개체(auth.get_user()
에서 검색됨)를 전달합니다.
다음 단계
자습서: 보호된 API를 호출하고 Python Flask 웹앱 결과를 표시합니다.